Skip to content

Commit 174e00f

Browse files
committed
Rename PydanticSerializer to Serializer
1 parent 139d9d5 commit 174e00f

File tree

21 files changed

+287
-175
lines changed

21 files changed

+287
-175
lines changed

ellar/core/conf/app_settings_models.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from starlette.responses import JSONResponse
77

88
from ellar.core.versioning import BaseAPIVersioning, DefaultAPIVersioning
9-
from ellar.serializer import PydanticSerializer, SerializerFilter
9+
from ellar.serializer import Serializer, SerializerFilter
1010

1111

1212
class TVersioning(BaseAPIVersioning):
@@ -37,7 +37,7 @@ def validate(cls: t.Type["Middleware"], v: t.Any) -> t.Any:
3737
return v
3838

3939

40-
class ConfigValidationSchema(PydanticSerializer):
40+
class ConfigValidationSchema(Serializer):
4141
_filter = SerializerFilter(
4242
exclude={
4343
"EXCEPTION_HANDLERS_DECORATOR",

ellar/core/response/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from ellar.serializer import (
22
BaseSerializer,
3-
DataClassSerializer,
4-
PydanticSerializer,
3+
DataclassSerializer,
4+
Serializer,
55
serialize_object,
66
)
77

@@ -27,8 +27,8 @@
2727
"PlainTextResponse",
2828
"RedirectResponse",
2929
"Response",
30-
"PydanticSerializer",
30+
"Serializer",
3131
"BaseSerializer",
32-
"DataClassSerializer",
32+
"DataclassSerializer",
3333
"serialize_object",
3434
]

ellar/core/response/model/base.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
from ellar.exceptions import RequestValidationError
1212
from ellar.serializer import (
1313
BaseSerializer,
14-
DataClassSerializer,
15-
PydanticSerializer,
16-
PydanticSerializerBase,
14+
DataclassSerializer,
15+
Serializer,
16+
SerializerBase,
1717
SerializerFilter,
1818
convert_dataclass_to_pydantic_model,
1919
serialize_object,
@@ -156,16 +156,16 @@ def _get_modified_type(
156156
if not isinstance(outer_type_, type):
157157
raise Exception(f"{outer_type_} is not a type")
158158

159-
if issubclass(outer_type_, DataClassSerializer):
159+
if issubclass(outer_type_, DataclassSerializer):
160160
schema_model = outer_type_.get_pydantic_model()
161-
cls = type(outer_type_.__name__, (schema_model, PydanticSerializerBase), {})
161+
cls = type(outer_type_.__name__, (schema_model, SerializerBase), {})
162162
return t.cast(t.Type[BaseSerializer], cls)
163163

164164
if isinstance(outer_type_, type) and issubclass(outer_type_, (BaseSerializer,)):
165165
return outer_type_
166166

167167
if issubclass(outer_type_, BaseModel):
168-
cls = type(outer_type_.__name__, (outer_type_, PydanticSerializer), dict())
168+
cls = type(outer_type_.__name__, (outer_type_, Serializer), dict())
169169
return t.cast(t.Type[BaseSerializer], cls)
170170

171171
if is_dataclass(outer_type_):
@@ -180,7 +180,7 @@ def _get_modified_type(
180180
return outer_type_
181181

182182
attrs = {"__annotations__": getattr(outer_type_, "__annotations__", ())}
183-
cls = type(outer_type_.__name__, (outer_type_, PydanticSerializer), attrs)
183+
cls = type(outer_type_.__name__, (outer_type_, Serializer), attrs)
184184

185185
return t.cast(t.Type[BaseSerializer], cls)
186186

ellar/core/routing/base.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020

2121
class RouteOperationBase:
2222
_meta: OperationMeta
23-
23+
path: str
2424
endpoint: t.Callable
25+
methods: t.Set[str]
2526

2627
@t.no_type_check
2728
def __call__(
@@ -98,4 +99,4 @@ def matches(self, scope: TScope) -> t.Tuple[Match, TScope]:
9899

99100

100101
class WebsocketRouteOperationBase(RouteOperationBase, ABC):
101-
pass
102+
methods: t.Set[str] = {"WS"} # just to avoid attribute error

ellar/core/routing/controller/decorator.py

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,15 @@
66

77
from ellar.constants import NOT_SET
88
from ellar.di import RequestScope, injectable
9-
from ellar.helper import get_name
109

1110
from .model import ControllerBase, ControllerType
1211
from .router import ControllerRouter
1312

14-
if t.TYPE_CHECKING:
13+
if t.TYPE_CHECKING: # pragma: no cover
1514
from ellar.core.guard import GuardCanActivate
1615
from ellar.core.routing.base import RouteOperationBase
1716

1817

19-
class MissingAPIControllerDecoratorException(Exception):
20-
pass
21-
22-
2318
def get_route_functions(cls: t.Type) -> t.Iterable["RouteOperationBase"]:
2419
from ellar.core.routing.base import RouteOperationBase
2520

@@ -28,20 +23,11 @@ def get_route_functions(cls: t.Type) -> t.Iterable["RouteOperationBase"]:
2823
yield method
2924

3025

31-
def compute_api_route_function(
32-
base_cls: t.Type, controller_instance: "ControllerDecorator"
33-
) -> None:
34-
for cls_route_function in get_route_functions(base_cls):
35-
controller_instance.add_route(cls_route_function)
36-
37-
3826
class ControllerDecorator:
3927
__slots__ = (
4028
"_controller_class",
41-
"_routes",
42-
"_mount",
43-
"_tag",
4429
"_meta",
30+
"_router",
4531
)
4632

4733
def __init__(
@@ -73,8 +59,6 @@ def __init__(
7359

7460
# `controller_class`
7561
self._controller_class: t.Optional[t.Type[ControllerBase]] = None
76-
# `_path_operations`
77-
self._routes: t.Dict[str, BaseRoute] = {}
7862

7963
self._meta = dict(
8064
tag=tag,
@@ -87,11 +71,14 @@ def __init__(
8771
guards=guards or [],
8872
include_in_schema=include_in_schema,
8973
)
90-
self._mount: t.Optional[ControllerRouter] = None
74+
self._router: t.Optional["ControllerRouter"] = None
9175

9276
if _controller_class:
9377
self(_controller_class)
9478

79+
def get_meta(self) -> t.Dict:
80+
return self._meta
81+
9582
def __call__(self, cls: t.Type) -> "ControllerDecorator":
9683
if type(cls) is not ControllerType:
9784
# We force the cls to inherit from `ControllerBase` by creating another type.
@@ -106,35 +93,38 @@ def __call__(self, cls: t.Type) -> "ControllerDecorator":
10693
if self._meta["path"] is NOT_SET:
10794
self._meta["path"] = f"/{tag}"
10895

96+
if not self._meta["name"]:
97+
self._meta["name"] = (
98+
str(self._controller_class.controller_class_name())
99+
.lower()
100+
.replace("controller", "")
101+
)
102+
103+
self._router = ControllerRouter(
104+
**self._meta, # type: ignore
105+
controller_type=self.get_controller_type(),
106+
)
109107
bases = inspect.getmro(cls)
110108
for base_cls in reversed(bases):
111109
if base_cls not in [ABC, ControllerBase, object]:
112-
compute_api_route_function(base_cls, self)
110+
self.compute_api_route_function(base_cls)
113111

114-
cls = injectable(RequestScope)(cls)
112+
injectable(RequestScope)(cls)
115113

116-
if not self._meta["name"]:
117-
self._meta["name"] = str(cls.__name__).lower().replace("controller", "")
118114
return self
119115

116+
def compute_api_route_function(self, base_cls: t.Type) -> None:
117+
for cls_route_function in get_route_functions(base_cls):
118+
self.get_router().routes.append(cls_route_function)
119+
120120
def get_controller_type(self) -> t.Type[ControllerBase]:
121121
assert self._controller_class, "Controller not properly initialised"
122122
return self._controller_class
123123

124-
def get_mount(self) -> "ControllerRouter":
125-
if not self._mount:
126-
self._mount = ControllerRouter(
127-
routes=list(self._routes.values()),
128-
**self._meta, # type: ignore
129-
controller_type=self.get_controller_type(),
130-
)
131-
return self._mount
132-
133-
def add_route(self, cls_route_function: "RouteOperationBase") -> None:
134-
self._routes[get_name(cls_route_function.endpoint)] = t.cast(
135-
BaseRoute, cls_route_function
136-
)
124+
def get_router(self) -> "ControllerRouter":
125+
assert self._router, "Controller not properly initialised"
126+
return self._router
137127

138128
def build_routes(self) -> t.List[BaseRoute]:
139-
mount = self.get_mount()
140-
return mount.build_routes()
129+
router = self.get_router()
130+
return router.build_routes()

ellar/core/routing/controller/model.py

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,6 @@
22

33
from ellar.core.context import ExecutionContext
44

5-
if t.TYPE_CHECKING:
6-
from ellar.core.routing.base import RouteOperationBase
7-
from ellar.core.routing.controller.decorator import ControllerDecorator
8-
9-
10-
class MissingAPIControllerDecoratorException(Exception):
11-
pass
12-
13-
14-
def get_route_functions(cls: t.Type) -> t.Iterable["RouteOperationBase"]:
15-
from ellar.core.routing.base import RouteOperationBase
16-
17-
for method in cls.__dict__.values():
18-
if isinstance(method, RouteOperationBase):
19-
yield method
20-
21-
22-
def compute_api_route_function(
23-
base_cls: t.Type, controller_instance: "ControllerDecorator"
24-
) -> None:
25-
for cls_route_function in get_route_functions(base_cls):
26-
controller_instance.add_route(cls_route_function)
27-
285

296
class ControllerType(type):
307
_controller_name: t.Optional[str]

ellar/core/routing/controller/route.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212

1313
class ControllerRouteOperation(ControllerRouteOperationBase, RouteOperation):
14+
methods: t.Set[str]
15+
1416
def build_route_operation( # type:ignore
1517
self,
1618
path_prefix: str = "/",

ellar/core/routing/controller/router.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
import typing as t
22

3-
from starlette.routing import BaseRoute
3+
from starlette.routing import Router
44

55
from ellar.core.guard import GuardCanActivate
66

7-
from ..router import ModuleRouterBase
7+
from ..router.module import ModuleRouterBase
8+
from ..router.route_collections import ModuleRouteCollection
89
from .model import ControllerBase
910
from .route import ControllerRouteOperation
1011
from .websocket.route import ControllerWebsocketRouteOperation
1112

1213

1314
class ControllerRouter(ModuleRouterBase):
15+
routes: ModuleRouteCollection # type:ignore
16+
1417
def __init__(
1518
self,
1619
path: str,
1720
controller_type: t.Type[ControllerBase],
18-
routes: t.Sequence[BaseRoute] = None,
1921
name: str = None,
2022
tag: t.Optional[str] = None,
2123
description: t.Optional[str] = None,
@@ -27,6 +29,8 @@ def __init__(
2729
] = None,
2830
include_in_schema: bool = True,
2931
) -> None:
32+
app = Router()
33+
app.routes = ModuleRouteCollection() # type:ignore
3034
super(ControllerRouter, self).__init__(
3135
path=path,
3236
tag=tag,
@@ -36,8 +40,8 @@ def __init__(
3640
external_doc_url=external_doc_url,
3741
version=version,
3842
guards=guards,
39-
routes=routes,
4043
include_in_schema=include_in_schema,
44+
app=app,
4145
)
4246
self.controller_type = controller_type
4347

ellar/core/routing/route.py

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ def __init__(
4848

4949
assert path.startswith("/"), "Routed paths must start with '/'"
5050
self.path = path
51+
self.path_regex, self.path_format, self.param_convertors = compile_path(
52+
self.path
53+
)
5154
self.endpoint = endpoint # type: ignore
5255

5356
self.name = get_name(endpoint) if name is None else name
@@ -71,24 +74,29 @@ def build_route_operation( # type:ignore
7174
include_in_schema: bool = True,
7275
**kwargs: t.Any,
7376
) -> None:
74-
self.path_regex, self.path_format, self.param_convertors = compile_path(
75-
f"{path_prefix.rstrip('/')}/{self.path.lstrip('/')}"
76-
)
77-
78-
self.endpoint_parameter_model = self.request_endpoint_args_model(
79-
path=self.path_format,
80-
endpoint=self.endpoint,
81-
operation_unique_id=self.get_operation_unique_id(
82-
method=list(self.methods)[0]
83-
),
84-
param_converters=self.param_convertors,
85-
)
86-
87-
if self._meta.extra_route_args:
88-
self.endpoint_parameter_model.add_extra_route_args(
89-
*self._meta.extra_route_args
77+
_path_changed = False
78+
if path_prefix not in ("", "/") and path_prefix not in self.path:
79+
self.path = f"{path_prefix.rstrip('/')}/{self.path.lstrip('/')}"
80+
self.path_regex, self.path_format, self.param_convertors = compile_path(
81+
self.path
82+
)
83+
_path_changed = True
84+
85+
if self.endpoint_parameter_model is NOT_SET or _path_changed:
86+
self.endpoint_parameter_model = self.request_endpoint_args_model(
87+
path=self.path_format,
88+
endpoint=self.endpoint,
89+
operation_unique_id=self.get_operation_unique_id(
90+
methods=list(self.methods)
91+
),
92+
param_converters=self.param_convertors,
9093
)
91-
self.endpoint_parameter_model.build_model()
94+
95+
if self._meta.extra_route_args:
96+
self.endpoint_parameter_model.add_extra_route_args(
97+
*self._meta.extra_route_args
98+
)
99+
self.endpoint_parameter_model.build_model()
92100
self.include_in_schema = include_in_schema
93101
if name:
94102
self.name = f"{name}:{self.name}"
@@ -105,9 +113,12 @@ def _load_model(self) -> None:
105113
route_responses=self._defined_responses # type: ignore
106114
)
107115

108-
def get_operation_unique_id(self, method: str) -> str:
116+
def get_operation_unique_id(self, methods: t.Union[t.Sequence[str], str]) -> str:
117+
_methods: t.Sequence[str] = (
118+
list(methods) if isinstance(methods, set) else [t.cast(str, methods)]
119+
)
109120
return generate_operation_unique_id(
110-
name=self.name, path=self.path_format, method=method
121+
name=self.name, path=self.path_format, methods=_methods
111122
)
112123

113124
async def _handle_request(self, context: ExecutionContext) -> None:
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
from .app import ApplicationRouter, RouteCollection
1+
from .app import ApplicationRouter
22
from .module import ModuleRouter, ModuleRouterBase
3+
from .route_collections import ModuleRouteCollection, RouteCollection
34

4-
__all__ = ["ApplicationRouter", "RouteCollection", "ModuleRouter", "ModuleRouterBase"]
5+
__all__ = [
6+
"ApplicationRouter",
7+
"RouteCollection",
8+
"ModuleRouter",
9+
"ModuleRouterBase",
10+
"ModuleRouteCollection",
11+
]

0 commit comments

Comments
 (0)