Skip to content

Commit 9608edc

Browse files
authored
Merge pull request #12 from eadwinCode/openapi_test
Openapi Module Test
2 parents 40a5877 + 5f34d21 commit 9608edc

File tree

22 files changed

+961
-108
lines changed

22 files changed

+961
-108
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ Project is still in development
108108
- Remaining testing modules:
109109
- configuration
110110
- guard
111-
- openapi
112111
- Project CLI scaffolding
113112
- Documentation
114113
- Database Plugin with [Encode/ORM](https://github.com/encode/orm)

ellar/common/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from .decorators.html import render, template_filter, template_global
99
from .decorators.middleware import middleware
1010
from .decorators.modules import Module
11-
from .decorators.openapi import openapi
11+
from .decorators.openapi import openapi_info
1212
from .decorators.request import on_shutdown, on_startup
1313
from .decorators.serializer import serializer_filter
1414
from .decorators.versioning import version
@@ -48,7 +48,7 @@
4848
"ParamTypes",
4949
"set_meta",
5050
"Controller",
51-
"openapi",
51+
"openapi_info",
5252
"version",
5353
"delete",
5454
"get",

ellar/common/decorators/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from .html import render, template_filter, template_global # noqa
66
from .middleware import middleware # noqa
77
from .modules import Module # noqa
8-
from .openapi import openapi # noqa
8+
from .openapi import openapi_info # noqa
99
from .request import on_shutdown, on_startup # noqa
1010
from .serializer import serializer_filter # noqa
1111
from .versioning import version # noqa

ellar/common/decorators/openapi.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from .base import set_meta
77

88

9-
def openapi(
9+
def openapi_info(
1010
operation_id: t.Optional[str] = None,
1111
summary: t.Optional[str] = None,
1212
description: t.Optional[str] = None,

ellar/core/modules/helper.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1+
import inspect
12
import typing as t
23
from functools import wraps
34

4-
from starlette.routing import iscoroutinefunction_or_partial
5-
65

76
def _executor_wrapper_async(
87
cls: t.Type, func: t.Callable
@@ -25,7 +24,7 @@ def _decorator(*args: t.Any, **kwargs: t.Any) -> t.Any:
2524
def class_parameter_executor_wrapper(
2625
cls: t.Type, func: t.Callable
2726
) -> t.Union[t.Callable, t.Callable[..., t.Coroutine]]:
28-
if iscoroutinefunction_or_partial(func):
27+
if inspect.iscoroutinefunction(func):
2928
return _executor_wrapper_async(cls, func)
3029

3130
return _executor_wrapper(cls, func)

ellar/core/response/model/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
ResponseTypeDefinitionConverter,
66
RouteResponseExecution,
77
)
8+
from .factory import create_response_model
89
from .html import HTMLResponseModel
910
from .interface import IResponseModel
1011
from .json import EmptyAPIResponseModel, JSONResponseModel
@@ -21,4 +22,5 @@
2122
"ResponseTypeDefinitionConverter",
2223
"IResponseModel",
2324
"HTMLResponseModel",
25+
"create_response_model",
2426
]

ellar/core/response/model/base.py

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import typing as t
2-
from abc import ABC
2+
from abc import ABC, abstractmethod
33
from dataclasses import is_dataclass
44

55
from pydantic import BaseModel
@@ -9,6 +9,7 @@
99
from ellar.core.context import IExecutionContext
1010
from ellar.core.converters import TypeDefinitionConverter
1111
from ellar.exceptions import RequestValidationError
12+
from ellar.helper.modelfield import create_model_field
1213
from ellar.reflect import reflect
1314
from ellar.serializer import (
1415
BaseSerializer,
@@ -64,7 +65,9 @@ def serialize(
6465

6566
class BaseResponseModel(IResponseModel, ABC):
6667
__slots__ = ("_response_type", "media_type", "description", "meta", "schema")
68+
6769
response_type: t.Type[Response] = Response
70+
model_schema: t.Union[ResponseModelField, t.Any] = None
6871

6972
def __init__(
7073
self,
@@ -80,17 +83,34 @@ def __init__(
8083
)
8184
self.description = description
8285
self.meta = kwargs
83-
self.schema = schema
8486

87+
_schema: t.Optional[ResponseModelField] = schema or self.model_schema
88+
if _schema and not isinstance(_schema, ResponseModelField):
89+
new_response_schema = ResponseTypeDefinitionConverter(
90+
_schema
91+
).re_group_outer_type()
92+
93+
_schema = t.cast(
94+
ResponseModelField,
95+
create_model_field(
96+
name="response_model",
97+
type_=new_response_schema,
98+
model_field_class=ResponseModelField,
99+
),
100+
)
101+
self.schema: t.Optional[ResponseModelField] = _schema
102+
103+
@abstractmethod
85104
def get_model_field(self) -> t.Optional[t.Union[ResponseModelField, t.Any]]:
86-
return self.schema
105+
pass
87106

107+
@abstractmethod
88108
def serialize(
89109
self,
90110
response_obj: t.Any,
91111
serializer_filter: t.Optional[SerializerFilter] = None,
92112
) -> t.Union[t.List[t.Dict], t.Dict, t.Any]:
93-
return response_obj
113+
pass
94114

95115
def create_response(
96116
self, context: IExecutionContext, response_obj: t.Any, status_code: int
@@ -131,22 +151,15 @@ def __copy__(self, memodict: t.Dict = {}) -> "BaseResponseModel":
131151

132152

133153
class ResponseModel(BaseResponseModel):
134-
@classmethod
135-
def create_model(
136-
cls,
137-
*args: t.Any,
138-
response_type: t.Type[Response] = None,
139-
description: str = "Successful Response",
140-
schema: t.Union[t.Type[ResponseModelField], t.Any] = None,
141-
**kwargs: t.Any,
142-
) -> "ResponseModel":
154+
def get_model_field(self) -> t.Optional[t.Union[ResponseModelField, t.Any]]:
155+
return self.schema
143156

144-
return cls(
145-
response_type=response_type,
146-
description=description,
147-
schema=schema,
148-
**kwargs,
149-
)
157+
def serialize(
158+
self,
159+
response_obj: t.Any,
160+
serializer_filter: t.Optional[SerializerFilter] = None,
161+
) -> t.Union[t.List[t.Dict], t.Dict, t.Any]:
162+
return response_obj
150163

151164

152165
class RouteResponseExecution(Exception):
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import typing as t
2+
3+
from starlette.responses import Response
4+
5+
if t.TYPE_CHECKING:
6+
from .base import ResponseModel, ResponseModelField
7+
8+
T = t.TypeVar("T")
9+
10+
11+
def create_response_model(
12+
response_model: t.Union[t.Type["ResponseModel"], t.Type[T]],
13+
*,
14+
response_type: t.Type[Response] = None,
15+
description: str = "Successful Response",
16+
schema: t.Union[t.Type["ResponseModelField"], t.Any] = None,
17+
**kwargs: t.Any,
18+
) -> t.Union["ResponseModel", T]:
19+
_init_kwargs: t.Dict[str, t.Any] = dict(
20+
response_type=response_type, description=description, schema=schema
21+
)
22+
_init_kwargs.update(kwargs)
23+
return response_model(**_init_kwargs)

ellar/core/response/model/interface.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,6 @@ class IResponseModel(ABC):
1414
media_type: str
1515
description: str
1616

17-
@classmethod
18-
@abstractmethod
19-
def create_model(
20-
cls,
21-
*args: t.Any,
22-
**kwargs: t.Any,
23-
) -> "IResponseModel":
24-
"""Creates ResponseModel Object"""
25-
2617
@abstractmethod
2718
def get_model_field(self) -> t.Optional[t.Union[ModelField, t.Any]]:
2819
"""Gets Model Fields"""

ellar/core/response/model/json.py

Lines changed: 13 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,26 @@
11
import typing as t
22

3-
from pydantic import BaseModel
4-
53
from ellar.constants import SERIALIZER_FILTER_KEY
64
from ellar.core.context import IExecutionContext
75
from ellar.helper.modelfield import create_model_field
86
from ellar.reflect import reflect
97
from ellar.serializer import SerializerFilter, serialize_object
108

119
from ..responses import JSONResponse, Response
12-
from .base import BaseResponseModel, ResponseModelField, ResponseTypeDefinitionConverter
13-
10+
from .base import ResponseModel, ResponseModelField
1411

15-
class JSONResponseModel(BaseResponseModel):
16-
response_type: t.Type[Response] = JSONResponse
17-
schema: ResponseModelField
12+
DictSchema: ResponseModelField = t.cast(
13+
ResponseModelField,
14+
create_model_field(
15+
name="response_model",
16+
type_=dict,
17+
model_field_class=ResponseModelField,
18+
),
19+
)
1820

19-
@classmethod
20-
def create_model( # type: ignore
21-
cls,
22-
schema: t.Union[t.Type[BaseModel], t.Any],
23-
description: str = "Successful Response",
24-
**kwargs: t.Any,
25-
) -> "JSONResponseModel":
26-
new_response_schema = ResponseTypeDefinitionConverter(
27-
schema
28-
).re_group_outer_type()
2921

30-
_schema = t.cast(
31-
ResponseModelField,
32-
create_model_field(
33-
name="response_model",
34-
type_=new_response_schema,
35-
model_field_class=ResponseModelField,
36-
),
37-
)
38-
return cls(
39-
description=description,
40-
schema=_schema,
41-
**kwargs,
42-
)
22+
class JSONResponseModel(ResponseModel):
23+
response_type: t.Type[Response] = JSONResponse
4324

4425
def create_response(
4526
self, context: IExecutionContext, response_obj: t.Any, status_code: int
@@ -64,32 +45,12 @@ def serialize(
6445
response_obj: t.Any,
6546
serializer_filter: t.Optional[SerializerFilter] = None,
6647
) -> t.Union[t.List[t.Dict], t.Dict, t.Any]:
48+
assert self.schema, "schema must exist for JSONResponseModel"
6749
return self.schema.serialize(response_obj, serializer_filter=serializer_filter)
6850

6951

7052
class EmptyAPIResponseModel(JSONResponseModel):
71-
@classmethod
72-
def create_model( # type: ignore
73-
cls,
74-
description: str = "Successful Response",
75-
**kwargs: t.Any,
76-
) -> "EmptyAPIResponseModel":
77-
new_response_schema = dict
78-
79-
_schema = t.cast(
80-
ResponseModelField,
81-
create_model_field(
82-
name="response_model",
83-
type_=new_response_schema,
84-
model_field_class=ResponseModelField,
85-
),
86-
)
87-
return cls(
88-
response_type=JSONResponse,
89-
description=description,
90-
schema=_schema,
91-
**kwargs,
92-
)
53+
model_schema = DictSchema
9354

9455
def serialize(
9556
self,

0 commit comments

Comments
 (0)