Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API Builder #557

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added api_builder/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions api_builder/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
6 changes: 6 additions & 0 deletions api_builder/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class ApiBuilderConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'api_builder'
26 changes: 26 additions & 0 deletions api_builder/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generated by Django 4.1.5 on 2023-09-02 01:17

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
('datahub', '0040_alter_datasetv2_name_alter_policy_description_and_more'),
]

operations = [
migrations.CreateModel(
name='API',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('endpoint', models.CharField(max_length=100)),
('selected_columns', models.JSONField()),
('access_key', models.CharField(blank=True, max_length=100, null=True)),
('dataset_file', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='apis', to='datahub.datasetv2file')),
],
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 4.1.5 on 2023-09-07 01:03

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('api_builder', '0001_initial'),
]

operations = [
migrations.AlterField(
model_name='api',
name='access_key',
field=models.CharField(max_length=100),
),
migrations.AlterField(
model_name='api',
name='endpoint',
field=models.CharField(max_length=100, unique=True),
),
]
Empty file.
25 changes: 25 additions & 0 deletions api_builder/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from django.db import models
from datahub.models import DatasetV2File


class API(models.Model):
"""
API Model - Represents an API configuration.

Attributes:
- dataset_file: ForeignKey to the associated DatasetV2File.
- endpoint: The API endpoint (unique).
- selected_columns: JSONField for storing selected columns.
- access_key: API access key.
"""

dataset_file = models.ForeignKey(DatasetV2File, on_delete=models.CASCADE, related_name="apis")
endpoint = models.CharField(max_length=100, unique=True)
selected_columns = models.JSONField()
access_key = models.CharField(max_length=100)

def __str__(self):
"""
Returns a string representation of the API instance.
"""
return self.endpoint
43 changes: 43 additions & 0 deletions api_builder/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from rest_framework import serializers
from api_builder.models import API
from datahub.models import DatasetV2File


class DatasetV2FileSerializer(serializers.ModelSerializer):
"""
Serializer for DatasetV2File model.

Serializes DatasetV2File fields and includes a method for getting the dataset name.
"""

dataset = serializers.SerializerMethodField()

class Meta:
model = DatasetV2File
fields = "__all__"

def get_dataset(self, obj):
"""
Get the dataset name associated with the DatasetV2File.

Args:
obj: The DatasetV2File instance.

Returns:
The dataset name.
"""
return obj.dataset.name


class APISerializer(serializers.ModelSerializer):
"""
Serializer for the API model.

Includes serialization of the associated DatasetV2File using DatasetV2FileSerializer.
"""

dataset_file = DatasetV2FileSerializer()

class Meta:
model = API
fields = "__all__"
3 changes: 3 additions & 0 deletions api_builder/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
88 changes: 88 additions & 0 deletions api_builder/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from django.test import Client, TestCase
from accounts.models import User, UserRole
from api_builder.models import API
from datahub.models import (
DatasetV2,
DatasetV2File,
Organization,
UserOrganizationMap,
)

datasets_dump_data = {
"name": "dump_datasets1",
"description": "dataset description",
"geography": "tpt",
"constantly_update": False,
}

class APITestModels(TestCase):
@classmethod
def setUpClass(cls):
"""
Set up the test environment for the APITestModels test case.

This method is called once before any test methods in this class run.
It creates necessary test objects and clients.
"""
super().setUpClass()
cls.user = Client()
cls.client_admin = Client()
cls.admin_role = UserRole.objects.create(id="1", role_name="datahub_admin")
cls.admin_user = User.objects.create(
email="[email protected]",
role_id=cls.admin_role.id,
)
cls.admin_org = Organization.objects.create(
org_email="[email protected]",
name="admin org",
phone_number="+91 83602-11483",
website="htttps://google.com",
address=({"city": "Bangalore"}),
)
cls.admin_map = UserOrganizationMap.objects.create(
user_id=cls.admin_user.id,
organization_id=cls.admin_org.id,
)
cls.dataset = DatasetV2.objects.create(user_map=cls.admin_map, **datasets_dump_data)
cls.dataset_id = cls.dataset.id
cls.dataset_file = DatasetV2File.objects.create(
file="api_builder/tests/test_data/File.csv", dataset=cls.dataset
)

def test_create_api(self):
"""
Test the creation of an API object.

This method creates an API object and asserts that its attributes
are correctly set.
"""
api = API.objects.create(
dataset_file=self.dataset_file,
endpoint="test_endpoint",
selected_columns=["column1", "column2"],
access_key="test_key",
)
self.assertEqual(api.endpoint, "test_endpoint")
self.assertEqual(api.dataset_file, self.dataset_file)
self.assertEqual(api.access_key, "test_key")

def test_duplicate_endpoint(self):
"""
Test the prevention of duplicate endpoint creation.

This method creates an API object with a duplicate endpoint and
asserts that it raises an exception.
"""
API.objects.create(
dataset_file=self.dataset_file,
endpoint="test_endpoint",
selected_columns=["Period", "Data_value"],
access_key="test_key",
)
with self.assertRaises(Exception):
API.objects.create(
dataset_file=self.dataset_file,
endpoint="test_endpoint",
selected_columns=["Period", "Data_value"],
access_key="test_key2",
)
26 changes: 26 additions & 0 deletions api_builder/tests/test_urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from django.test import TestCase
from django.urls import reverse, resolve
from api_builder import views

class APITestUrls(TestCase):
def test_create_api_url(self):
"""
Test that the 'create_api' URL resolves to the CreateAPIView view.
"""
url = reverse("create_api")
self.assertEqual(resolve(url).func.view_class, views.CreateAPIView)

def test_api_with_data_url(self):
"""
Test that the 'api-with-data' URL with arguments 'user_id' and 'endpoint_name'
resolves to the APIViewWithData view.
"""
url = reverse("api-with-data", args=["user_id", "endpoint_name"])
self.assertEqual(resolve(url).func.view_class, views.APIViewWithData)

def test_list_user_apis_url(self):
"""
Test that the 'list-user-apis' URL resolves to the ListUserAPIsView view.
"""
url = reverse("list-user-apis")
self.assertEqual(resolve(url).func.view_class, views.ListUserAPIsView)
Loading