Fix - Does not work with from __future__ import annotations

This commit is contained in:
Vincent Maillol 2022-02-05 10:28:05 +01:00
parent 3648dde1ea
commit 69fb553635
18 changed files with 54 additions and 14 deletions

View File

@ -1,5 +1,5 @@
from .view import PydanticView
__version__ = "1.12.0"
__version__ = "1.12.1"
__all__ = ("PydanticView", "__version__")

View File

@ -3,7 +3,7 @@ import typing
from inspect import signature, getmro
from json.decoder import JSONDecodeError
from types import SimpleNamespace
from typing import Callable, Tuple, Literal, Type
from typing import Callable, Tuple, Literal, Type, get_type_hints
from aiohttp.web_exceptions import HTTPBadRequest
from aiohttp.web_request import BaseRequest
@ -201,13 +201,19 @@ def _get_group_signature(cls) -> Tuple[dict, dict]:
mro = getmro(cls)
for base in reversed(mro[: mro.index(Group)]):
attrs = vars(base)
# Use __annotations__ to know if an attribute is
# overwrite to remove the default value.
for attr_name, type_ in base.__annotations__.items():
sig[attr_name] = type_
if (default := attrs.get(attr_name)) is None:
defaults.pop(attr_name, None)
else:
defaults[attr_name] = default
# Use get_type_hints to have postponed annotations.
for attr_name, type_ in get_type_hints(base).items():
sig[attr_name] = type_
return sig, defaults
@ -229,26 +235,29 @@ def _parse_func_signature(
header_args = {}
defaults = {}
annotations = get_type_hints(func)
for param_name, param_spec in signature(func).parameters.items():
if param_name == "self":
continue
if param_spec.annotation == param_spec.empty:
raise RuntimeError(f"The parameter {param_name} must have an annotation")
annotation = annotations[param_name]
if param_spec.default is not param_spec.empty:
defaults[param_name] = param_spec.default
if param_spec.kind is param_spec.POSITIONAL_ONLY:
path_args[param_name] = param_spec.annotation
path_args[param_name] = annotation
elif param_spec.kind is param_spec.POSITIONAL_OR_KEYWORD:
if is_pydantic_base_model(param_spec.annotation):
body_args[param_name] = param_spec.annotation
if is_pydantic_base_model(annotation):
body_args[param_name] = annotation
else:
qs_args[param_name] = param_spec.annotation
qs_args[param_name] = annotation
elif param_spec.kind is param_spec.KEYWORD_ONLY:
header_args[param_name] = param_spec.annotation
header_args[param_name] = annotation
else:
raise RuntimeError(f"You cannot use {param_spec.VAR_POSITIONAL} parameters")

View File

@ -1,7 +1,7 @@
import typing
from inspect import getdoc
from itertools import count
from typing import List, Type, Optional
from typing import List, Type, Optional, get_type_hints
from aiohttp.web import Response, json_response
from aiohttp.web_app import Application
@ -126,7 +126,7 @@ def _add_http_method_to_oas(
ref_template="#/components/schemas/{model}"
)
return_type = handler.__annotations__.get("return")
return_type = get_type_hints(handler).get("return")
if return_type is not None:
_OASResponseBuilder(oas, oas_operation, status_code_descriptions).build(
return_type

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from aiohttp_pydantic.injectors import (

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from typing import Iterator, List, Optional
from aiohttp import web

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from typing import Any
from aiohttp_pydantic import PydanticView

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from aiohttp import web
from aiohttp_pydantic import PydanticView

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import argparse
from textwrap import dedent
from io import StringIO

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from textwrap import dedent
from aiohttp_pydantic.oas.docstring_parser import (

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from aiohttp_pydantic.oas.struct import OpenApiSpec3

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from aiohttp_pydantic.oas.struct import OpenApiSpec3

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from aiohttp_pydantic.oas.struct import OpenApiSpec3

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from enum import Enum
from typing import List, Optional, Union, Literal
from uuid import UUID
@ -385,15 +387,16 @@ async def test_generated_view_info_as_title():
}
class Pagination(Group):
page: int = 1
page_size: int = 20
async def test_use_parameters_group_should_not_impact_the_oas(aiohttp_client):
class PetCollectionView1(PydanticView):
async def get(self, page: int = 1, page_size: int = 20) -> r200[List[Pet]]:
return web.json_response()
class Pagination(Group):
page: int = 1
page_size: int = 20
class PetCollectionView2(PydanticView):
async def get(self, pagination: Pagination) -> r200[List[Pet]]:
return web.json_response()

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from uuid import UUID
from pydantic import BaseModel

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from typing import Iterator, List, Optional
from aiohttp import web

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import json
from datetime import datetime
from enum import Enum

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from aiohttp import web
from aiohttp_pydantic import PydanticView

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from typing import Optional, List
from pydantic import Field
from aiohttp import web