Skip to content

Commit

Permalink
Formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
foarsitter committed Feb 11, 2024
1 parent 974aad0 commit 5fcc451
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 76 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/constraints.txt
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Sphinx configuration."""

project = "requestmodel"
author = "Jelmer Draaijer"
copyright = "2023, Jelmer Draaijer"
Expand Down
10 changes: 5 additions & 5 deletions src/requestmodel/adapters/httpx.py
Original file line number Diff line number Diff line change
@@ -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]
Expand Down
8 changes: 3 additions & 5 deletions tests/fastapi_server/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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()]
2 changes: 1 addition & 1 deletion tests/locatieserver/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions tests/test_locatieserver.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Testing the LookupRequest."""

import pytest
from httpx import AsyncClient
from httpx import Client
Expand Down
2 changes: 1 addition & 1 deletion tests/test_param_types.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
123 changes: 63 additions & 60 deletions tests/test_request_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()

Expand All @@ -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)
Expand All @@ -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
)
Expand All @@ -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
Expand All @@ -138,33 +138,36 @@ 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"
):
SimpleRequest(data="test")


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()

Expand Down

0 comments on commit 5fcc451

Please sign in to comment.