From 5fcc45149c9c580c1578f43c7875e4d887124e7f Mon Sep 17 00:00:00 2001 From: Jelmer Draaijer Date: Sun, 11 Feb 2024 21:04:47 +0100 Subject: [PATCH] Formatting --- .github/workflows/constraints.txt | 8 +- docs/conf.py | 1 + src/requestmodel/adapters/httpx.py | 10 +-- tests/fastapi_server/schema.py | 8 +- tests/locatieserver/requests.py | 2 +- tests/test_locatieserver.py | 1 + tests/test_param_types.py | 2 +- tests/test_request_model.py | 123 +++++++++++++++-------------- 8 files changed, 79 insertions(+), 76 deletions(-) diff --git a/.github/workflows/constraints.txt b/.github/workflows/constraints.txt index 6e89933..e33b554 100644 --- a/.github/workflows/constraints.txt +++ b/.github/workflows/constraints.txt @@ -1,5 +1,5 @@ -pip==23.1.2 -nox==2022.11.21 +pip==24.0 +nox==2023.4.22 nox-poetry==1.0.3 -poetry==1.3.2 -virtualenv==20.15.0 +poetry==1.7.1 +virtualenv==20.25.0 diff --git a/docs/conf.py b/docs/conf.py index bcdeeff..4b81081 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,5 @@ """Sphinx configuration.""" + project = "requestmodel" author = "Jelmer Draaijer" copyright = "2023, Jelmer Draaijer" diff --git a/src/requestmodel/adapters/httpx.py b/src/requestmodel/adapters/httpx.py index 7471238..d8a42f2 100644 --- a/src/requestmodel/adapters/httpx.py +++ b/src/requestmodel/adapters/httpx.py @@ -1,18 +1,18 @@ -from typing import Any - from httpx import Request from httpx._client import BaseClient +from requestmodel import params from requestmodel.adapters.base import BaseAdapter from requestmodel.model import RequestModel - -from .. import params +from requestmodel.typing import ResponseType class HTTPXAdapter(BaseAdapter): name = "httpx" - def transform(self, client: BaseClient, model: RequestModel[Any]) -> Request: + def transform( + self, client: BaseClient, model: RequestModel[ResponseType] + ) -> Request: request_args = model.request_args_for_values() headers = request_args[params.Header] diff --git a/tests/fastapi_server/schema.py b/tests/fastapi_server/schema.py index 115838b..db18415 100644 --- a/tests/fastapi_server/schema.py +++ b/tests/fastapi_server/schema.py @@ -2,13 +2,11 @@ from typing import List from typing import Type -from fastapi import File -from fastapi import Header -from fastapi import params from pydantic import BaseModel from typing_extensions import Annotated from requestmodel import RequestModel +from requestmodel import params class FileUploadResponse(BaseModel): @@ -38,5 +36,5 @@ class FileUploadRequest(RequestModel[FileUploadResponse]): path: str name: str - file: Annotated[bytes, File()] - extra_header: Annotated[str, Header()] + file: Annotated[bytes, params.File()] + extra_header: Annotated[str, params.Header()] diff --git a/tests/locatieserver/requests.py b/tests/locatieserver/requests.py index 2bfdbc1..c904bfd 100644 --- a/tests/locatieserver/requests.py +++ b/tests/locatieserver/requests.py @@ -3,11 +3,11 @@ from typing import Optional from typing import Type -from fastapi import Query from typing_extensions import Annotated from requestmodel import RequestModel from requestmodel.adapters.requests import RequestsRequestModel +from requestmodel.params import Query from .models import LookupResponse diff --git a/tests/test_locatieserver.py b/tests/test_locatieserver.py index e55f0df..5c011a6 100644 --- a/tests/test_locatieserver.py +++ b/tests/test_locatieserver.py @@ -1,4 +1,5 @@ """Testing the LookupRequest.""" + import pytest from httpx import AsyncClient from httpx import Client diff --git a/tests/test_param_types.py b/tests/test_param_types.py index 6b4f5ea..a51c9a2 100644 --- a/tests/test_param_types.py +++ b/tests/test_param_types.py @@ -1,11 +1,11 @@ from typing import ClassVar from typing import Type -from fastapi import Header from typing_extensions import Annotated from requestmodel.model import IteratorRequestModel from requestmodel.model import RequestModel +from requestmodel.params import Header from tests.fastapi_server import client from tests.fastapi_server.schema import FileCreateSchema from tests.fastapi_server.schema import FileUploadRequest diff --git a/tests/test_request_model.py b/tests/test_request_model.py index 8280ca6..7207472 100644 --- a/tests/test_request_model.py +++ b/tests/test_request_model.py @@ -6,7 +6,6 @@ from typing import Type import pytest -from fastapi import params from fastapi._compat import field_annotation_is_scalar from fastapi._compat import field_annotation_is_sequence from pydantic import BaseModel @@ -17,23 +16,45 @@ from typing_extensions import get_type_hints from requestmodel import RequestModel +from requestmodel import params from requestmodel.utils import get_annotated_type -def test_request_args_for_values() -> None: - class SimpleResponse(BaseModel): - data: str +class SimpleResponse(BaseModel): + data: str + + +class SimpleBody(BaseModel): + data: str - class SimpleBody(BaseModel): - data: str - class ModelWithClassVar(RequestModel[SimpleResponse]): - url: ClassVar[str] = "test" - method: ClassVar[str] = "POST" - response_model: ClassVar[Type[SimpleResponse]] = SimpleResponse - body: SimpleBody +class ModelWithClassVar(RequestModel[SimpleResponse]): + url: ClassVar[str] = "test" + method: ClassVar[str] = "POST" + response_model: ClassVar[Type[SimpleResponse]] = SimpleResponse + body: SimpleBody + header_underscore: Annotated[ + str, params.Header(convert_underscores=False, alias="X_Test") + ] + header: Annotated[str, params.Header(convert_underscores=False, alias="X-Scored")] + excluded: Annotated[str, params.Header(exclude=True)] - x = ModelWithClassVar(body=SimpleBody(data="test")) + +class ModelWithClassVar2(RequestModel[SimpleResponse]): + url: ClassVar[str] = "test" + method: ClassVar[str] = "POST" + response_model: ClassVar[Type[SimpleResponse]] = SimpleResponse + page: Optional[int] + + +def test_request_args_for_values() -> None: + header_value = "test" + x = ModelWithClassVar( + body=SimpleBody(data="test"), + header_underscore=header_value, + header=header_value + "2", + excluded="not present in the output", + ) v = x.request_args_for_values() @@ -46,39 +67,28 @@ class ModelWithClassVar(RequestModel[SimpleResponse]): def test_none_as_query_param_value() -> None: """We want to override a value and set it to null""" - class SimpleResponse(BaseModel): - data: str - - class ModelWithClassVar(RequestModel[SimpleResponse]): - url: ClassVar[str] = "test" - method: ClassVar[str] = "POST" - response_model: ClassVar[Type[SimpleResponse]] = SimpleResponse - page: Optional[int] - - x = ModelWithClassVar(page=None) + x = ModelWithClassVar2(page=None) v = x.request_args_for_values() assert "page" in v[params.Query] -def test_get_annotated_type() -> None: - class SimpleResponse(BaseModel): - data: str +class AnnotatedType(RequestModel[SimpleResponse]): + a: Annotated[str, params.Query()] + b: Annotated[SimpleResponse, params.Body()] + c: Annotated[str, params.Header()] - class AnnotatedType(RequestModel[Any]): - a: Annotated[str, params.Query()] - b: Annotated[SimpleResponse, params.Body()] - c: Annotated[str, params.Header()] + # a BaseModel cannot be used as query param so should be placed in the body + d: SimpleResponse + e: Annotated[SimpleResponse, params.Body()] - # a BaseModel cannot be used as query param so should be placed in the body - d: SimpleResponse - e: Annotated[SimpleResponse, params.Body()] + # this should race an exception + f: Annotated[SimpleResponse, params.Path()] + g: Annotated[SimpleResponse, params.Query()] - # this should race an exception - f: Annotated[SimpleResponse, params.Path()] - g: Annotated[SimpleResponse, params.Query()] +def test_get_annotated_type() -> None: hints = get_type_hints(AnnotatedType, include_extras=True) assert isinstance(get_annotated_type("a", hints["a"]), params.Query) @@ -95,9 +105,6 @@ class AnnotatedType(RequestModel[Any]): def test_annotated_type() -> None: - class SimpleResponse(BaseModel): - data: str - assert isinstance( get_annotated_type("w", Annotated[List[str], params.Query()]), params.Query ) @@ -117,19 +124,12 @@ class SimpleResponse(BaseModel): def test_field_annotation_is_sequence() -> None: - class SimpleResponse(BaseModel): - data: str - assert field_annotation_is_sequence(str) is False assert field_annotation_is_sequence(List[str]) is True assert field_annotation_is_sequence(SimpleResponse) is False def test_field_annotation_is_scalar() -> None: - class SimpleResponse(BaseModel): - data: str - - # assert field_annotation_is_complex(SimpleResponse) is True assert field_annotation_is_scalar(Annotated[SimpleResponse, params.Path()]) is True assert field_annotation_is_scalar(SimpleResponse) is False @@ -138,12 +138,24 @@ class SimpleResponse(BaseModel): assert field_annotation_is_scalar(Annotated[SimpleResponse, params.Path()]) is True -def test_field_annotation_with_constraints() -> None: - class SimpleRequest(RequestModel[Any]): - url: ClassVar[str] = "test" - method: ClassVar[str] = "test" - data: Annotated[str, params.Query(min_length=8, max_length=10)] +class SimpleRequest(RequestModel[SimpleResponse]): + url: ClassVar[str] = "test" + method: ClassVar[str] = "test" + data: Annotated[str, params.Query(min_length=8, max_length=10)] + +class SimpleRequest2(RequestModel[SimpleResponse]): + url: ClassVar[str] = "test" + method: ClassVar[str] = "test" + query_list: Annotated[List[int], params.Query()] + data_str: Annotated[str, params.Body()] + data_int: Annotated[int, params.Body()] + data_list: Annotated[List[int], params.Body()] + data_dict: Annotated[Dict[str, int], params.Body(embed=True)] + response_model: ClassVar[Type[SimpleResponse]] = SimpleResponse + + +def test_field_annotation_with_constraints() -> None: with pytest.raises( ValidationError, match="String should have at least 8 characters" ): @@ -151,20 +163,11 @@ class SimpleRequest(RequestModel[Any]): def test_field_unified_body() -> None: - class SimpleRequest(RequestModel[Any]): - url: ClassVar[str] = "test" - method: ClassVar[str] = "test" - query_list: Annotated[List[int], params.Query()] - data_str: Annotated[str, params.Body()] - data_int: Annotated[int, params.Body()] - data_list: Annotated[List[int], params.Body()] - data_dict: Annotated[Dict[str, int], params.Body(embed=True)] - data: Dict[str, Any] = dict( data_str="test", data_int=1, data_list=[0, 1, 2], data_dict={"key": 1925} ) - r = SimpleRequest(query_list=[1, 2, 3], **data) + r = SimpleRequest2(query_list=[1, 2, 3], **data) x = r.request_args_for_values()