Skip to content

Commit 8fe6153

Browse files
committed
test-coverage: increased test coverage and some code refactoring
1 parent 0173c67 commit 8fe6153

17 files changed

+265
-119
lines changed

ellar/common/decorators/controller.py

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,28 +48,35 @@ def reflect_all_controller_type_routes(cls: t.Type[ControllerBase]) -> None:
4848
)
4949
reflect.define_metadata(CONTROLLER_CLASS_KEY, cls, item)
5050

51-
parameter = item.__dict__[ROUTE_OPERATION_PARAMETERS]
51+
parameters = item.__dict__[ROUTE_OPERATION_PARAMETERS]
5252
operation: t.Union[
5353
ControllerRouteOperation, ControllerWebsocketRouteOperation
5454
]
55-
if isinstance(parameter, RouteParameters):
56-
operation = ControllerRouteOperation(**parameter.dict())
57-
elif isinstance(parameter, WsRouteParameters):
58-
operation = ControllerWebsocketRouteOperation(**parameter.dict())
59-
else: # pragma: no cover
60-
logger.warning(
61-
f"Parameter type is not recognized. {type(parameter) if not isinstance(parameter, type) else parameter}"
55+
56+
if not isinstance(parameters, list):
57+
parameters = [parameters]
58+
59+
for parameter in parameters:
60+
if isinstance(parameter, RouteParameters):
61+
operation = ControllerRouteOperation(**parameter.dict())
62+
elif isinstance(parameter, WsRouteParameters):
63+
operation = ControllerWebsocketRouteOperation(
64+
**parameter.dict()
65+
)
66+
else: # pragma: no cover
67+
logger.warning(
68+
f"Parameter type is not recognized. {type(parameter) if not isinstance(parameter, type) else parameter}"
69+
)
70+
continue
71+
72+
reflect.define_metadata(
73+
CONTROLLER_OPERATION_HANDLER_KEY,
74+
[operation],
75+
cls,
6276
)
63-
continue
6477

6578
del item.__dict__[ROUTE_OPERATION_PARAMETERS]
6679

67-
reflect.define_metadata(
68-
CONTROLLER_OPERATION_HANDLER_KEY,
69-
[operation],
70-
cls,
71-
)
72-
7380

7481
@t.no_type_check
7582
def Controller(

ellar/common/responses/models/base.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from ellar.common.exceptions import RequestValidationError
77
from ellar.common.interfaces import IExecutionContext, IResponseModel
88
from ellar.common.logging import request_logger
9-
from ellar.common.serializer import BaseSerializer, SerializerFilter
9+
from ellar.common.serializer import BaseSerializer, SerializerFilter, serialize_object
1010
from ellar.pydantic import ModelField, create_model_field
1111
from ellar.reflect import reflect
1212
from starlette.responses import Response
@@ -204,7 +204,18 @@ def serialize(
204204
response_obj: t.Any,
205205
serializer_filter: t.Optional[SerializerFilter] = None,
206206
) -> t.Union[t.List[t.Dict], t.Dict, t.Any]:
207-
return response_obj
207+
return self._serialize_with_serializer_object(response_obj)
208+
209+
def _serialize_with_serializer_object(
210+
self,
211+
response_obj: t.Any,
212+
serializer_filter: t.Optional[SerializerFilter] = None,
213+
) -> t.Union[t.List[t.Dict], t.Dict, t.Any]:
214+
try:
215+
return serialize_object(response_obj, serializer_filter=serializer_filter)
216+
except Exception: # pragma: no cover
217+
"""Could not serialize response obj"""
218+
return response_obj
208219

209220

210221
class ResponseResolver(t.NamedTuple):

ellar/common/responses/models/json.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from ellar.common.constants import SERIALIZER_FILTER_KEY
44
from ellar.common.interfaces import IExecutionContext
55
from ellar.common.logging import request_logger
6-
from ellar.common.serializer import SerializerFilter, serialize_object
6+
from ellar.common.serializer import SerializerFilter
77
from ellar.pydantic import as_pydantic_validator, create_model_field
88
from ellar.reflect import reflect
99

@@ -85,10 +85,6 @@ def serialize(
8585
try:
8686
return super().serialize(response_obj, serializer_filter)
8787
except Exception:
88-
try:
89-
return serialize_object(
90-
response_obj, serializer_filter=serializer_filter
91-
)
92-
except Exception: # pragma:no cover
93-
"""Could not serialize response obj"""
94-
return response_obj
88+
return self._serialize_with_serializer_object(
89+
response_obj, serializer_filter
90+
)

ellar/common/responses/models/type_converter.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,7 @@
33

44
from ellar.common.constants import primitive_types
55
from ellar.common.converters import TypeDefinitionConverter
6-
from ellar.common.serializer.base import (
7-
BaseSerializer,
8-
Serializer,
9-
SerializerBase,
10-
convert_dataclass_to_pydantic_model,
11-
)
6+
from ellar.common.serializer.base import BaseSerializer, Serializer
127
from ellar.pydantic import BaseModel
138

149

@@ -27,14 +22,15 @@ def _get_converted_type(
2722
return outer_type_
2823

2924
if is_dataclass(outer_type_):
30-
pydantic_dataclass = convert_dataclass_to_pydantic_model(outer_type_)
31-
32-
cls = type(
33-
outer_type_.__name__,
34-
(pydantic_dataclass, SerializerBase),
35-
{},
36-
)
37-
return t.cast(t.Type[BaseSerializer], cls)
25+
# pydantic_dataclass = convert_dataclass_to_pydantic_model(outer_type_)
26+
#
27+
# cls = type(
28+
# outer_type_.__name__,
29+
# (pydantic_dataclass, SerializerBase),
30+
# {},
31+
# )
32+
# return t.cast(t.Type[BaseSerializer], cls)
33+
return outer_type_
3834

3935
if outer_type_ in primitive_types:
4036
return outer_type_

ellar/common/responses/response_types.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@
2424

2525
try:
2626
import ujson
27-
except ImportError: # pragma: nocover
27+
except ImportError: # pragma: no cover
2828
ujson = None # type: ignore
2929

3030

3131
try:
3232
import orjson
33-
except ImportError: # pragma: nocover
33+
except ImportError: # pragma: no cover
3434
orjson = None # type: ignore
3535

3636

ellar/common/routing/operation_definitions.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,11 @@ class OperationDefinitions:
5858

5959
def _get_operation(self, route_parameter: RouteParameters) -> t.Callable:
6060
setattr(route_parameter.endpoint, OPERATION_ENDPOINT_KEY, True)
61-
setattr(route_parameter.endpoint, ROUTE_OPERATION_PARAMETERS, route_parameter)
61+
route_parameters = getattr(
62+
route_parameter.endpoint, ROUTE_OPERATION_PARAMETERS, []
63+
)
64+
route_parameters.append(route_parameter)
65+
setattr(route_parameter.endpoint, ROUTE_OPERATION_PARAMETERS, route_parameters)
6266
return route_parameter.endpoint
6367

6468
def _get_ws_operation(self, ws_route_parameters: WsRouteParameters) -> t.Callable:

ellar/common/serializer/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
SerializerConfig,
66
SerializerFilter,
77
default_serializer_filter,
8-
get_dataclass_pydantic_model,
98
serialize_object,
109
)
1110

@@ -16,6 +15,5 @@
1615
"SerializerBase",
1716
"BaseSerializer",
1817
"serialize_object",
19-
"get_dataclass_pydantic_model",
2018
"default_serializer_filter",
2119
]

ellar/common/serializer/base.py

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
BaseModel,
1212
TypeAdapter,
1313
model_dump,
14-
pydantic_dataclass,
1514
)
1615

1716
__pydantic_model__ = "__pydantic_core_schema__"
@@ -20,12 +19,26 @@
2019
__skip_filter__ = "__skip_filter__"
2120

2221

23-
@t.no_type_check
24-
def get_dataclass_pydantic_model(
25-
dataclass_type: t.Type,
26-
) -> t.Optional[t.Type[BaseModel]]:
27-
if hasattr(dataclass_type, __pydantic_model__):
28-
return t.cast(t.Type[BaseModel], dataclass_type)
22+
# @t.no_type_check
23+
# def get_dataclass_pydantic_model(
24+
# dataclass_type: t.Type,
25+
# ) -> t.Optional[t.Type[BaseModel]]:
26+
# if hasattr(dataclass_type, __pydantic_model__):
27+
# return t.cast(t.Type[BaseModel], dataclass_type)
28+
#
29+
# def convert_dataclass_to_pydantic_model(dataclass_type: t.Type) -> t.Type[BaseModel]:
30+
# if is_dataclass(dataclass_type):
31+
# if get_dataclass_pydantic_model(dataclass_type):
32+
# return t.cast(t.Type[BaseModel], dataclass_type)
33+
#
34+
# # convert to dataclass
35+
# decorator = pydantic_dataclass(
36+
# config=getattr(dataclass_type, __pydantic_config__, SerializerConfig),
37+
# )
38+
# pydantic_dataclass_cls = decorator(t.cast(t.Any, dataclass_type))
39+
# # sa = {item: getattr(pydantic_dataclass, item) for item in dir(pydantic_dataclass)}
40+
# return t.cast(t.Type[BaseModel], pydantic_dataclass_cls)
41+
# raise Exception(f"{dataclass_type} is not a dataclass")
2942

3043

3144
class SerializerConfig(BaseConfig):
@@ -108,21 +121,6 @@ class Serializer(SerializerBase, BaseModel, __skip_filter__=True):
108121
model_config = {"from_attributes": True}
109122

110123

111-
def convert_dataclass_to_pydantic_model(dataclass_type: t.Type) -> t.Type[BaseModel]:
112-
if is_dataclass(dataclass_type):
113-
if get_dataclass_pydantic_model(dataclass_type):
114-
return t.cast(t.Type[BaseModel], dataclass_type)
115-
116-
# convert to dataclass
117-
decorator = pydantic_dataclass(
118-
config=getattr(dataclass_type, __pydantic_config__, SerializerConfig),
119-
)
120-
pydantic_dataclass_cls = decorator(t.cast(t.Any, dataclass_type))
121-
# sa = {item: getattr(pydantic_dataclass, item) for item in dir(pydantic_dataclass)}
122-
return t.cast(t.Type[BaseModel], pydantic_dataclass_cls)
123-
raise Exception(f"{dataclass_type} is not a dataclass")
124-
125-
126124
def _lazy_current_config() -> t.Any:
127125
return LazyStrImport("ellar.app:current_config")
128126

ellar/core/routing/app.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ def __init__(
5353
self.routes: RouteCollection = RouteCollection(routes)
5454

5555
def append(self, item: t.Union[BaseRoute, t.Callable]) -> None:
56-
_item: t.Any = build_route_handler(item)
57-
self.routes.append(_item)
56+
_items: t.Any = build_route_handler(item)
57+
if _items:
58+
self.routes.extend(_items)
5859

5960
def extend(self, routes: t.Sequence[t.Union[BaseRoute, t.Callable]]) -> None:
6061
for route in routes:

ellar/core/routing/helper.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919

2020
@t.no_type_check
21-
def build_route_handler(item: t.Callable) -> t.Optional[RouteOperationBase]:
21+
def build_route_handler(item: t.Callable) -> t.Optional[t.List[RouteOperationBase]]:
2222
_item: t.Any = item
2323

2424
if callable(item) and type(item) == FunctionType:
@@ -28,11 +28,19 @@ def build_route_handler(item: t.Callable) -> t.Optional[RouteOperationBase]:
2828
reflect.define_metadata(CONTROLLER_CLASS_KEY, get_unique_control_type(), item)
2929

3030
if not _item and hasattr(item, ROUTE_OPERATION_PARAMETERS):
31-
operations = build_route_parameters([item.__dict__[ROUTE_OPERATION_PARAMETERS]])
32-
if not operations:
33-
return None # pragma: no cover
34-
return operations[0]
35-
return _item
31+
parameters = item.__dict__[ROUTE_OPERATION_PARAMETERS]
32+
33+
if not isinstance(parameters, list):
34+
parameters = [parameters]
35+
36+
operations = build_route_parameters(parameters)
37+
if isinstance(operations, list):
38+
return operations
39+
40+
if _item:
41+
return [_item]
42+
43+
return _item # pragma: no cover
3644

3745

3846
@t.no_type_check

0 commit comments

Comments
 (0)