From f9ec12f273b554b5286a573d17dcdfee257a2b5e Mon Sep 17 00:00:00 2001 From: Satyam Seth Date: Fri, 25 Oct 2024 02:02:38 +0530 Subject: [PATCH] generate python openapi client --- openapi python client generation/README.md | 5 + .../backend/README.md | 39 +++ .../backend/core/__init__.py | 0 .../backend/core/admin.py | 9 + .../backend/core/apps.py | 6 + .../backend/core/migrations/0001_initial.py | 23 ++ .../backend/core/migrations/__init__.py | 0 .../backend/core/models.py | 9 + .../backend/core/serializers.py | 8 + .../backend/core/tests.py | 3 + .../backend/core/views.py | 10 + .../backend/db.sqlite3 | Bin 0 -> 135168 bytes .../backend/demo/__init__.py | 0 .../backend/demo/asgi.py | 16 + .../backend/demo/settings.py | 129 ++++++++ .../backend/demo/urls.py | 38 +++ .../backend/demo/wsgi.py | 16 + .../backend/manage.py | 22 ++ .../backend/openapi-schema.yml | 160 ++++++++++ .../backend/requirements.txt | 6 + .../frontend/client/__init__.py | 8 + .../frontend/client/api/__init__.py | 1 + .../client/api/studentapi/__init__.py | 0 .../client/api/studentapi/create_student.py | 194 ++++++++++++ .../client/api/studentapi/destroy_student.py | 97 ++++++ .../client/api/studentapi/list_students.py | 127 ++++++++ .../api/studentapi/partial_update_student.py | 209 +++++++++++++ .../client/api/studentapi/retrieve_student.py | 148 +++++++++ .../client/api/studentapi/update_student.py | 209 +++++++++++++ .../frontend/client/client.py | 286 ++++++++++++++++++ .../frontend/client/errors.py | 16 + .../frontend/client/models/__init__.py | 5 + .../frontend/client/models/student.py | 114 +++++++ .../frontend/client/types.py | 53 ++++ .../frontend/demo.py | 0 35 files changed, 1966 insertions(+) create mode 100644 openapi python client generation/README.md create mode 100644 openapi python client generation/backend/README.md create mode 100644 openapi python client generation/backend/core/__init__.py create mode 100644 openapi python client generation/backend/core/admin.py create mode 100644 openapi python client generation/backend/core/apps.py create mode 100644 openapi python client generation/backend/core/migrations/0001_initial.py create mode 100644 openapi python client generation/backend/core/migrations/__init__.py create mode 100644 openapi python client generation/backend/core/models.py create mode 100644 openapi python client generation/backend/core/serializers.py create mode 100644 openapi python client generation/backend/core/tests.py create mode 100644 openapi python client generation/backend/core/views.py create mode 100644 openapi python client generation/backend/db.sqlite3 create mode 100644 openapi python client generation/backend/demo/__init__.py create mode 100644 openapi python client generation/backend/demo/asgi.py create mode 100644 openapi python client generation/backend/demo/settings.py create mode 100644 openapi python client generation/backend/demo/urls.py create mode 100644 openapi python client generation/backend/demo/wsgi.py create mode 100644 openapi python client generation/backend/manage.py create mode 100644 openapi python client generation/backend/openapi-schema.yml create mode 100644 openapi python client generation/backend/requirements.txt create mode 100644 openapi python client generation/frontend/client/__init__.py create mode 100644 openapi python client generation/frontend/client/api/__init__.py create mode 100644 openapi python client generation/frontend/client/api/studentapi/__init__.py create mode 100644 openapi python client generation/frontend/client/api/studentapi/create_student.py create mode 100644 openapi python client generation/frontend/client/api/studentapi/destroy_student.py create mode 100644 openapi python client generation/frontend/client/api/studentapi/list_students.py create mode 100644 openapi python client generation/frontend/client/api/studentapi/partial_update_student.py create mode 100644 openapi python client generation/frontend/client/api/studentapi/retrieve_student.py create mode 100644 openapi python client generation/frontend/client/api/studentapi/update_student.py create mode 100644 openapi python client generation/frontend/client/client.py create mode 100644 openapi python client generation/frontend/client/errors.py create mode 100644 openapi python client generation/frontend/client/models/__init__.py create mode 100644 openapi python client generation/frontend/client/models/student.py create mode 100644 openapi python client generation/frontend/client/types.py create mode 100644 openapi python client generation/frontend/demo.py diff --git a/openapi python client generation/README.md b/openapi python client generation/README.md new file mode 100644 index 0000000..def42d6 --- /dev/null +++ b/openapi python client generation/README.md @@ -0,0 +1,5 @@ +[Reference Link](https://github.com/ajaishankar/openapi-typescript-fetch) + +#### Steps to run the demo +- Follow Backend Readme +- Follow Frontend Readme diff --git a/openapi python client generation/backend/README.md b/openapi python client generation/backend/README.md new file mode 100644 index 0000000..0c8001a --- /dev/null +++ b/openapi python client generation/backend/README.md @@ -0,0 +1,39 @@ +[Reference Link](https://www.django-rest-framework.org/api-guide/schemas/) + +#### Steps + +- Create virtual env + + ```sh + python -m venv .venv + ``` + +- Activate virtual env + + ```sh + source .venv/bin/activate + ``` + +- Install required dependencies + + ```sh + pip install -r requirements.txt + ``` + +- Generate Open Api Schema File + + ```sh + python manage.py generateschema --file 'openapi-schema.yml' + ``` + +- Run Backend Server + + ```sh + python manage.py runserver + ``` + += Generate OpenAPI Client + + ```sh + openapi-python-client generate --path openapi-schema.yml --meta none --fail-on-warning --output-path ../frontend/client + ``` \ No newline at end of file diff --git a/openapi python client generation/backend/core/__init__.py b/openapi python client generation/backend/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/openapi python client generation/backend/core/admin.py b/openapi python client generation/backend/core/admin.py new file mode 100644 index 0000000..201d949 --- /dev/null +++ b/openapi python client generation/backend/core/admin.py @@ -0,0 +1,9 @@ +from django.contrib import admin +from .models import Student + +# Register your models here. + + +@admin.register(Student) +class StudentAdmin(admin.ModelAdmin): + list_display = ['id', 'name', 'roll', 'city'] diff --git a/openapi python client generation/backend/core/apps.py b/openapi python client generation/backend/core/apps.py new file mode 100644 index 0000000..8115ae6 --- /dev/null +++ b/openapi python client generation/backend/core/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class CoreConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'core' diff --git a/openapi python client generation/backend/core/migrations/0001_initial.py b/openapi python client generation/backend/core/migrations/0001_initial.py new file mode 100644 index 0000000..2916ad6 --- /dev/null +++ b/openapi python client generation/backend/core/migrations/0001_initial.py @@ -0,0 +1,23 @@ +# Generated by Django 4.0.5 on 2022-06-15 18:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Student', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50)), + ('roll', models.IntegerField()), + ('city', models.CharField(max_length=50)), + ], + ), + ] diff --git a/openapi python client generation/backend/core/migrations/__init__.py b/openapi python client generation/backend/core/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/openapi python client generation/backend/core/models.py b/openapi python client generation/backend/core/models.py new file mode 100644 index 0000000..1bcb589 --- /dev/null +++ b/openapi python client generation/backend/core/models.py @@ -0,0 +1,9 @@ +from django.db import models + +# Create your models here. + + +class Student(models.Model): + name = models.CharField(max_length=50) + roll = models.IntegerField() + city = models.CharField(max_length=50) diff --git a/openapi python client generation/backend/core/serializers.py b/openapi python client generation/backend/core/serializers.py new file mode 100644 index 0000000..1c7491e --- /dev/null +++ b/openapi python client generation/backend/core/serializers.py @@ -0,0 +1,8 @@ +from rest_framework import serializers +from .models import Student + + +class StudentSerializer(serializers.ModelSerializer): + class Meta: + model = Student + fields = ['id', 'name', 'roll', 'city'] diff --git a/openapi python client generation/backend/core/tests.py b/openapi python client generation/backend/core/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/openapi python client generation/backend/core/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/openapi python client generation/backend/core/views.py b/openapi python client generation/backend/core/views.py new file mode 100644 index 0000000..3b0a1f2 --- /dev/null +++ b/openapi python client generation/backend/core/views.py @@ -0,0 +1,10 @@ +from .models import Student +from .serializers import StudentSerializer +from rest_framework import viewsets + +# Create your views here. + + +class StudentModelViewSet(viewsets.ModelViewSet): + queryset = Student.objects.all() + serializer_class = StudentSerializer diff --git a/openapi python client generation/backend/db.sqlite3 b/openapi python client generation/backend/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..e8be118b3e3ad4280ce4807419da3b98bea42b5d GIT binary patch literal 135168 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 Dict[str, Any]: + headers: Dict[str, Any] = {} + + _kwargs: Dict[str, Any] = { + "method": "post", + "url": "/studentapi/", + } + + if isinstance(body, Student): + _json_body = body.to_dict() + + _kwargs["json"] = _json_body + headers["Content-Type"] = "application/json" + if isinstance(body, Student): + _data_body = body.to_dict() + + _kwargs["data"] = _data_body + headers["Content-Type"] = "application/x-www-form-urlencoded" + if isinstance(body, Student): + _files_body = body.to_multipart() + + _kwargs["files"] = _files_body + headers["Content-Type"] = "multipart/form-data" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Student]: + if response.status_code == 201: + response_201 = Student.from_dict(response.json()) + + return response_201 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Student]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: Union[AuthenticatedClient, Client], + body: Union[ + Student, + Student, + Student, + ], +) -> Response[Student]: + """ + Args: + body (Student): + body (Student): + body (Student): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Student] + """ + + kwargs = _get_kwargs( + body=body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: Union[AuthenticatedClient, Client], + body: Union[ + Student, + Student, + Student, + ], +) -> Optional[Student]: + """ + Args: + body (Student): + body (Student): + body (Student): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Student + """ + + return sync_detailed( + client=client, + body=body, + ).parsed + + +async def asyncio_detailed( + *, + client: Union[AuthenticatedClient, Client], + body: Union[ + Student, + Student, + Student, + ], +) -> Response[Student]: + """ + Args: + body (Student): + body (Student): + body (Student): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Student] + """ + + kwargs = _get_kwargs( + body=body, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: Union[AuthenticatedClient, Client], + body: Union[ + Student, + Student, + Student, + ], +) -> Optional[Student]: + """ + Args: + body (Student): + body (Student): + body (Student): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Student + """ + + return ( + await asyncio_detailed( + client=client, + body=body, + ) + ).parsed diff --git a/openapi python client generation/frontend/client/api/studentapi/destroy_student.py b/openapi python client generation/frontend/client/api/studentapi/destroy_student.py new file mode 100644 index 0000000..00fd623 --- /dev/null +++ b/openapi python client generation/frontend/client/api/studentapi/destroy_student.py @@ -0,0 +1,97 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...types import Response + + +def _get_kwargs( + id: str, +) -> Dict[str, Any]: + _kwargs: Dict[str, Any] = { + "method": "delete", + "url": "/studentapi/{id}/".format( + id=id, + ), + } + + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Any]: + if response.status_code == 204: + return None + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Any]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Any]: + """ + Args: + id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Any] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +async def asyncio_detailed( + id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Any]: + """ + Args: + id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Any] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) diff --git a/openapi python client generation/frontend/client/api/studentapi/list_students.py b/openapi python client generation/frontend/client/api/studentapi/list_students.py new file mode 100644 index 0000000..9f25b24 --- /dev/null +++ b/openapi python client generation/frontend/client/api/studentapi/list_students.py @@ -0,0 +1,127 @@ +from http import HTTPStatus +from typing import Any, Dict, List, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.student import Student +from ...types import Response + + +def _get_kwargs() -> Dict[str, Any]: + _kwargs: Dict[str, Any] = { + "method": "get", + "url": "/studentapi/", + } + + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[List["Student"]]: + if response.status_code == 200: + response_200 = [] + _response_200 = response.json() + for response_200_item_data in _response_200: + response_200_item = Student.from_dict(response_200_item_data) + + response_200.append(response_200_item) + + return response_200 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[List["Student"]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: Union[AuthenticatedClient, Client], +) -> Response[List["Student"]]: + """ + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[List['Student']] + """ + + kwargs = _get_kwargs() + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[List["Student"]]: + """ + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + List['Student'] + """ + + return sync_detailed( + client=client, + ).parsed + + +async def asyncio_detailed( + *, + client: Union[AuthenticatedClient, Client], +) -> Response[List["Student"]]: + """ + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[List['Student']] + """ + + kwargs = _get_kwargs() + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[List["Student"]]: + """ + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + List['Student'] + """ + + return ( + await asyncio_detailed( + client=client, + ) + ).parsed diff --git a/openapi python client generation/frontend/client/api/studentapi/partial_update_student.py b/openapi python client generation/frontend/client/api/studentapi/partial_update_student.py new file mode 100644 index 0000000..162d6ee --- /dev/null +++ b/openapi python client generation/frontend/client/api/studentapi/partial_update_student.py @@ -0,0 +1,209 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.student import Student +from ...types import Response + + +def _get_kwargs( + id: str, + *, + body: Union[ + Student, + Student, + Student, + ], +) -> Dict[str, Any]: + headers: Dict[str, Any] = {} + + _kwargs: Dict[str, Any] = { + "method": "patch", + "url": "/studentapi/{id}/".format( + id=id, + ), + } + + if isinstance(body, Student): + _json_body = body.to_dict() + + _kwargs["json"] = _json_body + headers["Content-Type"] = "application/json" + if isinstance(body, Student): + _data_body = body.to_dict() + + _kwargs["data"] = _data_body + headers["Content-Type"] = "application/x-www-form-urlencoded" + if isinstance(body, Student): + _files_body = body.to_multipart() + + _kwargs["files"] = _files_body + headers["Content-Type"] = "multipart/form-data" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Student]: + if response.status_code == 200: + response_200 = Student.from_dict(response.json()) + + return response_200 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Student]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: str, + *, + client: Union[AuthenticatedClient, Client], + body: Union[ + Student, + Student, + Student, + ], +) -> Response[Student]: + """ + Args: + id (str): + body (Student): + body (Student): + body (Student): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Student] + """ + + kwargs = _get_kwargs( + id=id, + body=body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: str, + *, + client: Union[AuthenticatedClient, Client], + body: Union[ + Student, + Student, + Student, + ], +) -> Optional[Student]: + """ + Args: + id (str): + body (Student): + body (Student): + body (Student): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Student + """ + + return sync_detailed( + id=id, + client=client, + body=body, + ).parsed + + +async def asyncio_detailed( + id: str, + *, + client: Union[AuthenticatedClient, Client], + body: Union[ + Student, + Student, + Student, + ], +) -> Response[Student]: + """ + Args: + id (str): + body (Student): + body (Student): + body (Student): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Student] + """ + + kwargs = _get_kwargs( + id=id, + body=body, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: str, + *, + client: Union[AuthenticatedClient, Client], + body: Union[ + Student, + Student, + Student, + ], +) -> Optional[Student]: + """ + Args: + id (str): + body (Student): + body (Student): + body (Student): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Student + """ + + return ( + await asyncio_detailed( + id=id, + client=client, + body=body, + ) + ).parsed diff --git a/openapi python client generation/frontend/client/api/studentapi/retrieve_student.py b/openapi python client generation/frontend/client/api/studentapi/retrieve_student.py new file mode 100644 index 0000000..3d38fc3 --- /dev/null +++ b/openapi python client generation/frontend/client/api/studentapi/retrieve_student.py @@ -0,0 +1,148 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.student import Student +from ...types import Response + + +def _get_kwargs( + id: str, +) -> Dict[str, Any]: + _kwargs: Dict[str, Any] = { + "method": "get", + "url": "/studentapi/{id}/".format( + id=id, + ), + } + + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Student]: + if response.status_code == 200: + response_200 = Student.from_dict(response.json()) + + return response_200 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Student]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Student]: + """ + Args: + id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Student] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Student]: + """ + Args: + id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Student + """ + + return sync_detailed( + id=id, + client=client, + ).parsed + + +async def asyncio_detailed( + id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Response[Student]: + """ + Args: + id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Student] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: str, + *, + client: Union[AuthenticatedClient, Client], +) -> Optional[Student]: + """ + Args: + id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Student + """ + + return ( + await asyncio_detailed( + id=id, + client=client, + ) + ).parsed diff --git a/openapi python client generation/frontend/client/api/studentapi/update_student.py b/openapi python client generation/frontend/client/api/studentapi/update_student.py new file mode 100644 index 0000000..61dee79 --- /dev/null +++ b/openapi python client generation/frontend/client/api/studentapi/update_student.py @@ -0,0 +1,209 @@ +from http import HTTPStatus +from typing import Any, Dict, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.student import Student +from ...types import Response + + +def _get_kwargs( + id: str, + *, + body: Union[ + Student, + Student, + Student, + ], +) -> Dict[str, Any]: + headers: Dict[str, Any] = {} + + _kwargs: Dict[str, Any] = { + "method": "put", + "url": "/studentapi/{id}/".format( + id=id, + ), + } + + if isinstance(body, Student): + _json_body = body.to_dict() + + _kwargs["json"] = _json_body + headers["Content-Type"] = "application/json" + if isinstance(body, Student): + _data_body = body.to_dict() + + _kwargs["data"] = _data_body + headers["Content-Type"] = "application/x-www-form-urlencoded" + if isinstance(body, Student): + _files_body = body.to_multipart() + + _kwargs["files"] = _files_body + headers["Content-Type"] = "multipart/form-data" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Student]: + if response.status_code == 200: + response_200 = Student.from_dict(response.json()) + + return response_200 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Student]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: str, + *, + client: Union[AuthenticatedClient, Client], + body: Union[ + Student, + Student, + Student, + ], +) -> Response[Student]: + """ + Args: + id (str): + body (Student): + body (Student): + body (Student): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Student] + """ + + kwargs = _get_kwargs( + id=id, + body=body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: str, + *, + client: Union[AuthenticatedClient, Client], + body: Union[ + Student, + Student, + Student, + ], +) -> Optional[Student]: + """ + Args: + id (str): + body (Student): + body (Student): + body (Student): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Student + """ + + return sync_detailed( + id=id, + client=client, + body=body, + ).parsed + + +async def asyncio_detailed( + id: str, + *, + client: Union[AuthenticatedClient, Client], + body: Union[ + Student, + Student, + Student, + ], +) -> Response[Student]: + """ + Args: + id (str): + body (Student): + body (Student): + body (Student): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Student] + """ + + kwargs = _get_kwargs( + id=id, + body=body, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: str, + *, + client: Union[AuthenticatedClient, Client], + body: Union[ + Student, + Student, + Student, + ], +) -> Optional[Student]: + """ + Args: + id (str): + body (Student): + body (Student): + body (Student): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Student + """ + + return ( + await asyncio_detailed( + id=id, + client=client, + body=body, + ) + ).parsed diff --git a/openapi python client generation/frontend/client/client.py b/openapi python client generation/frontend/client/client.py new file mode 100644 index 0000000..eef9b71 --- /dev/null +++ b/openapi python client generation/frontend/client/client.py @@ -0,0 +1,286 @@ +import ssl +from typing import Any, Dict, Optional, Union + +import httpx +from attrs import define, evolve, field + + +@define +class Client: + """A class for keeping track of data related to the API + + The following are accepted as keyword arguments and will be used to construct httpx Clients internally: + + ``base_url``: The base URL for the API, all requests are made to a relative path to this URL + + ``cookies``: A dictionary of cookies to be sent with every request + + ``headers``: A dictionary of headers to be sent with every request + + ``timeout``: The maximum amount of a time a request can take. API functions will raise + httpx.TimeoutException if this is exceeded. + + ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, + but can be set to False for testing purposes. + + ``follow_redirects``: Whether or not to follow redirects. Default value is False. + + ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor. + + + Attributes: + raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a + status code that was not documented in the source OpenAPI document. Can also be provided as a keyword + argument to the constructor. + """ + + raise_on_unexpected_status: bool = field(default=False, kw_only=True) + _base_url: str = field(alias="base_url") + _cookies: Dict[str, str] = field(factory=dict, kw_only=True, alias="cookies") + _headers: Dict[str, str] = field(factory=dict, kw_only=True, alias="headers") + _timeout: Optional[httpx.Timeout] = field( + default=None, kw_only=True, alias="timeout" + ) + _verify_ssl: Union[str, bool, ssl.SSLContext] = field( + default=True, kw_only=True, alias="verify_ssl" + ) + _follow_redirects: bool = field( + default=False, kw_only=True, alias="follow_redirects" + ) + _httpx_args: Dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args") + _client: Optional[httpx.Client] = field(default=None, init=False) + _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) + + def with_headers(self, headers: Dict[str, str]) -> "Client": + """Get a new client matching this one with additional headers""" + if self._client is not None: + self._client.headers.update(headers) + if self._async_client is not None: + self._async_client.headers.update(headers) + return evolve(self, headers={**self._headers, **headers}) + + def with_cookies(self, cookies: Dict[str, str]) -> "Client": + """Get a new client matching this one with additional cookies""" + if self._client is not None: + self._client.cookies.update(cookies) + if self._async_client is not None: + self._async_client.cookies.update(cookies) + return evolve(self, cookies={**self._cookies, **cookies}) + + def with_timeout(self, timeout: httpx.Timeout) -> "Client": + """Get a new client matching this one with a new timeout (in seconds)""" + if self._client is not None: + self._client.timeout = timeout + if self._async_client is not None: + self._async_client.timeout = timeout + return evolve(self, timeout=timeout) + + def set_httpx_client(self, client: httpx.Client) -> "Client": + """Manually set the underlying httpx.Client + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._client = client + return self + + def get_httpx_client(self) -> httpx.Client: + """Get the underlying httpx.Client, constructing a new one if not previously set""" + if self._client is None: + self._client = httpx.Client( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + **self._httpx_args, + ) + return self._client + + def __enter__(self) -> "Client": + """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" + self.get_httpx_client().__enter__() + return self + + def __exit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for internal httpx.Client (see httpx docs)""" + self.get_httpx_client().__exit__(*args, **kwargs) + + def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Client": + """Manually the underlying httpx.AsyncClient + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._async_client = async_client + return self + + def get_async_httpx_client(self) -> httpx.AsyncClient: + """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" + if self._async_client is None: + self._async_client = httpx.AsyncClient( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + **self._httpx_args, + ) + return self._async_client + + async def __aenter__(self) -> "Client": + """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)""" + await self.get_async_httpx_client().__aenter__() + return self + + async def __aexit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)""" + await self.get_async_httpx_client().__aexit__(*args, **kwargs) + + +@define +class AuthenticatedClient: + """A Client which has been authenticated for use on secured endpoints + + The following are accepted as keyword arguments and will be used to construct httpx Clients internally: + + ``base_url``: The base URL for the API, all requests are made to a relative path to this URL + + ``cookies``: A dictionary of cookies to be sent with every request + + ``headers``: A dictionary of headers to be sent with every request + + ``timeout``: The maximum amount of a time a request can take. API functions will raise + httpx.TimeoutException if this is exceeded. + + ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production, + but can be set to False for testing purposes. + + ``follow_redirects``: Whether or not to follow redirects. Default value is False. + + ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor. + + + Attributes: + raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a + status code that was not documented in the source OpenAPI document. Can also be provided as a keyword + argument to the constructor. + token: The token to use for authentication + prefix: The prefix to use for the Authorization header + auth_header_name: The name of the Authorization header + """ + + raise_on_unexpected_status: bool = field(default=False, kw_only=True) + _base_url: str = field(alias="base_url") + _cookies: Dict[str, str] = field(factory=dict, kw_only=True, alias="cookies") + _headers: Dict[str, str] = field(factory=dict, kw_only=True, alias="headers") + _timeout: Optional[httpx.Timeout] = field( + default=None, kw_only=True, alias="timeout" + ) + _verify_ssl: Union[str, bool, ssl.SSLContext] = field( + default=True, kw_only=True, alias="verify_ssl" + ) + _follow_redirects: bool = field( + default=False, kw_only=True, alias="follow_redirects" + ) + _httpx_args: Dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args") + _client: Optional[httpx.Client] = field(default=None, init=False) + _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False) + + token: str + prefix: str = "Bearer" + auth_header_name: str = "Authorization" + + def with_headers(self, headers: Dict[str, str]) -> "AuthenticatedClient": + """Get a new client matching this one with additional headers""" + if self._client is not None: + self._client.headers.update(headers) + if self._async_client is not None: + self._async_client.headers.update(headers) + return evolve(self, headers={**self._headers, **headers}) + + def with_cookies(self, cookies: Dict[str, str]) -> "AuthenticatedClient": + """Get a new client matching this one with additional cookies""" + if self._client is not None: + self._client.cookies.update(cookies) + if self._async_client is not None: + self._async_client.cookies.update(cookies) + return evolve(self, cookies={**self._cookies, **cookies}) + + def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient": + """Get a new client matching this one with a new timeout (in seconds)""" + if self._client is not None: + self._client.timeout = timeout + if self._async_client is not None: + self._async_client.timeout = timeout + return evolve(self, timeout=timeout) + + def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient": + """Manually set the underlying httpx.Client + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._client = client + return self + + def get_httpx_client(self) -> httpx.Client: + """Get the underlying httpx.Client, constructing a new one if not previously set""" + if self._client is None: + self._headers[self.auth_header_name] = ( + f"{self.prefix} {self.token}" if self.prefix else self.token + ) + self._client = httpx.Client( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + **self._httpx_args, + ) + return self._client + + def __enter__(self) -> "AuthenticatedClient": + """Enter a context manager for self.client—you cannot enter twice (see httpx docs)""" + self.get_httpx_client().__enter__() + return self + + def __exit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for internal httpx.Client (see httpx docs)""" + self.get_httpx_client().__exit__(*args, **kwargs) + + def set_async_httpx_client( + self, async_client: httpx.AsyncClient + ) -> "AuthenticatedClient": + """Manually the underlying httpx.AsyncClient + + **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout. + """ + self._async_client = async_client + return self + + def get_async_httpx_client(self) -> httpx.AsyncClient: + """Get the underlying httpx.AsyncClient, constructing a new one if not previously set""" + if self._async_client is None: + self._headers[self.auth_header_name] = ( + f"{self.prefix} {self.token}" if self.prefix else self.token + ) + self._async_client = httpx.AsyncClient( + base_url=self._base_url, + cookies=self._cookies, + headers=self._headers, + timeout=self._timeout, + verify=self._verify_ssl, + follow_redirects=self._follow_redirects, + **self._httpx_args, + ) + return self._async_client + + async def __aenter__(self) -> "AuthenticatedClient": + """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)""" + await self.get_async_httpx_client().__aenter__() + return self + + async def __aexit__(self, *args: Any, **kwargs: Any) -> None: + """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)""" + await self.get_async_httpx_client().__aexit__(*args, **kwargs) diff --git a/openapi python client generation/frontend/client/errors.py b/openapi python client generation/frontend/client/errors.py new file mode 100644 index 0000000..5f92e76 --- /dev/null +++ b/openapi python client generation/frontend/client/errors.py @@ -0,0 +1,16 @@ +"""Contains shared errors types that can be raised from API functions""" + + +class UnexpectedStatus(Exception): + """Raised by api functions when the response status an undocumented status and Client.raise_on_unexpected_status is True""" + + def __init__(self, status_code: int, content: bytes): + self.status_code = status_code + self.content = content + + super().__init__( + f"Unexpected status code: {status_code}\n\nResponse content:\n{content.decode(errors='ignore')}" + ) + + +__all__ = ["UnexpectedStatus"] diff --git a/openapi python client generation/frontend/client/models/__init__.py b/openapi python client generation/frontend/client/models/__init__.py new file mode 100644 index 0000000..730f554 --- /dev/null +++ b/openapi python client generation/frontend/client/models/__init__.py @@ -0,0 +1,5 @@ +"""Contains all the data models used in inputs/outputs""" + +from .student import Student + +__all__ = ("Student",) diff --git a/openapi python client generation/frontend/client/models/student.py b/openapi python client generation/frontend/client/models/student.py new file mode 100644 index 0000000..134081f --- /dev/null +++ b/openapi python client generation/frontend/client/models/student.py @@ -0,0 +1,114 @@ +from typing import Any, Dict, List, Type, TypeVar, Union + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="Student") + + +@_attrs_define +class Student: + """ + Attributes: + name (str): + roll (int): + city (str): + id (Union[Unset, int]): + """ + + name: str + roll: int + city: str + id: Union[Unset, int] = UNSET + additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + name = self.name + + roll = self.roll + + city = self.city + + id = self.id + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "name": name, + "roll": roll, + "city": city, + } + ) + if id is not UNSET: + field_dict["id"] = id + + return field_dict + + def to_multipart(self) -> Dict[str, Any]: + name = (None, str(self.name).encode(), "text/plain") + + roll = (None, str(self.roll).encode(), "text/plain") + + city = (None, str(self.city).encode(), "text/plain") + + id = ( + self.id + if isinstance(self.id, Unset) + else (None, str(self.id).encode(), "text/plain") + ) + + field_dict: Dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + field_dict[prop_name] = (None, str(prop).encode(), "text/plain") + + field_dict.update( + { + "name": name, + "roll": roll, + "city": city, + } + ) + if id is not UNSET: + field_dict["id"] = id + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + name = d.pop("name") + + roll = d.pop("roll") + + city = d.pop("city") + + id = d.pop("id", UNSET) + + student = cls( + name=name, + roll=roll, + city=city, + id=id, + ) + + student.additional_properties = d + return student + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/openapi python client generation/frontend/client/types.py b/openapi python client generation/frontend/client/types.py new file mode 100644 index 0000000..05f5a22 --- /dev/null +++ b/openapi python client generation/frontend/client/types.py @@ -0,0 +1,53 @@ +"""Contains some shared types for properties""" + +from http import HTTPStatus +from typing import ( + BinaryIO, + Generic, + Literal, + MutableMapping, + Optional, + Tuple, + TypeVar, +) + +from attrs import define + + +class Unset: + def __bool__(self) -> Literal[False]: + return False + + +UNSET: Unset = Unset() + +FileJsonType = Tuple[Optional[str], BinaryIO, Optional[str]] + + +@define +class File: + """Contains information for file uploads""" + + payload: BinaryIO + file_name: Optional[str] = None + mime_type: Optional[str] = None + + def to_tuple(self) -> FileJsonType: + """Return a tuple representation that httpx will accept for multipart/form-data""" + return self.file_name, self.payload, self.mime_type + + +T = TypeVar("T") + + +@define +class Response(Generic[T]): + """A response from an endpoint""" + + status_code: HTTPStatus + content: bytes + headers: MutableMapping[str, str] + parsed: Optional[T] + + +__all__ = ["File", "Response", "FileJsonType", "Unset", "UNSET"] diff --git a/openapi python client generation/frontend/demo.py b/openapi python client generation/frontend/demo.py new file mode 100644 index 0000000..e69de29