pyboot-web 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 pyboot contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,234 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyboot-web
3
+ Version: 0.1.0
4
+ Summary: Starlette web plugin for PyBoot
5
+ License-Expression: MIT
6
+ Requires-Python: >=3.11
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: pyboot-framework>=0.1.0
10
+ Requires-Dist: starlette>=0.40.0
11
+ Requires-Dist: pydantic>=2.0
12
+ Dynamic: license-file
13
+
14
+ # pyboot-web
15
+
16
+ `pyboot-web` is the Starlette web plugin for [PyBoot](../../pyboot/README.md).
17
+ It adds decorator-based HTTP controllers, route mappings, services, request
18
+ middleware, centralized exception handlers, and `.env` configuration loading
19
+ to a PyBoot application.
20
+
21
+ The plugin is intentionally small: PyBoot remains responsible for class
22
+ discovery, dependency injection, bean creation, and lifecycle orchestration;
23
+ this package translates annotated classes and methods into Starlette routes.
24
+
25
+ ## Documentation
26
+
27
+ - [Examples](./EXAMPLES.md) - runnable snippets for routing, services,
28
+ middleware, exception advice, and configuration.
29
+ - [Production starter](./STARTER.md) - a recommended project layout,
30
+ bootstrap implementation, deployment checklist, and testing approach.
31
+ - [License](./LICENSE) - MIT license terms.
32
+
33
+ ## Features
34
+
35
+ | Capability | API |
36
+ | --- | --- |
37
+ | HTTP controller | `RestController` |
38
+ | HTTP routes | `GetMapping`, `PostMapping`, `PutMapping`, `PatchMapping`, `DeleteMapping` |
39
+ | Application services | `Service` |
40
+ | PyBoot-managed components | `Component` |
41
+ | Bean factories | `Configuration`, `Bean` |
42
+ | Middleware | `MiddlewareBase`, `MiddlewareComponent`, `UseMiddleware` |
43
+ | Exception advice | `RestControllerAdvice`, `ExceptionHandler` |
44
+ | Environment configuration | `Value`, `ValuePlugin` |
45
+ | PyBoot integration | `WebPlugin`, registered as the `web` PyBoot plugin |
46
+
47
+ The package supports Python 3.11 and newer and uses Starlette for routing and
48
+ request/response types.
49
+
50
+ ## Installation
51
+
52
+ Install PyBoot and this plugin in the same environment:
53
+
54
+ ```bash
55
+ python -m pip install pyboot-framework pyboot-web
56
+ python -m pip install python-dotenv uvicorn
57
+ ```
58
+
59
+ For a source checkout, from the repository root:
60
+
61
+ ```bash
62
+ python -m pip install -e pyboot
63
+ python -m pip install -e plugins/pyboot_web
64
+ python -m pip install python-dotenv uvicorn
65
+ ```
66
+
67
+ The package metadata declares `starlette`. `python-dotenv` is required by the
68
+ `ValuePlugin` implementation.
69
+
70
+ Verify that PyBoot can discover the plugin entry points:
71
+
72
+ ```bash
73
+ python -c "from importlib.metadata import entry_points; print([e.name for e in entry_points(group='pyboot.plugins')])"
74
+ ```
75
+
76
+ The output should include `web`. It may also include `value` and other
77
+ installed plugins.
78
+
79
+ ## Minimal bootstrap contract
80
+
81
+ Create a Starlette application, pass it to PyBoot, bootstrap the package that
82
+ contains the application classes, and expose the original Starlette object:
83
+
84
+ ```python
85
+ from starlette.applications import Starlette
86
+ from pyboot.core.application import PyBoot
87
+
88
+
89
+ app = Starlette(debug=False)
90
+ PyBoot(app_instance=app, debug=False).bootstrap(package="app")
91
+ ```
92
+
93
+ Run it with an ASGI server:
94
+
95
+ ```bash
96
+ python -m uvicorn main:app --host 127.0.0.1 --port 8000
97
+ ```
98
+
99
+ `PyBoot.bootstrap()` returns `None`; it mutates the supplied Starlette
100
+ application by registering routes. Do not assign the return value to `app`.
101
+
102
+ ## API reference
103
+
104
+ ### `pyboot_web.rest_mapping`
105
+
106
+ - `RestController(path: str)` marks a class as an HTTP controller.
107
+ - `GetMapping(path)`, `PostMapping(path)`, `PutMapping(path)`,
108
+ `PatchMapping(path)`, and `DeleteMapping(path)` provide method-specific
109
+ route decorators for methods declared inside a `RestController` class.
110
+
111
+ Route decorators are intended for controller methods, following the
112
+ class-oriented style used by Spring Boot:
113
+
114
+ ```python
115
+ @RestController("/api")
116
+ class HealthController:
117
+ @GetMapping("/health")
118
+ async def health(self, request: Request) -> JSONResponse:
119
+ ...
120
+ ```
121
+
122
+ Supported methods are `GET`, `POST`, `PUT`, `PATCH`, and `DELETE`. A standalone
123
+ function decorated as a route is not discovered by `WebPlugin`.
124
+
125
+ ### `pyboot_web.service`
126
+
127
+ - `Service()` marks a class for web-plugin registration and IoC construction.
128
+
129
+ Use `Service` for web-layer services. Use PyBoot's built-in `Component` for
130
+ general application dependencies that should be managed by the core IoC
131
+ container:
132
+
133
+ ```python
134
+ from pyboot.core.builtins.component import Component
135
+
136
+
137
+ @Component()
138
+ class AuditService:
139
+ ...
140
+ ```
141
+
142
+ `Component` classes can be injected into `Service` classes and controllers
143
+ when their constructor parameters have type annotations.
144
+
145
+ ### PyBoot built-in bean management
146
+
147
+ `Component` is the general-purpose PyBoot IoC decorator. For factory-created
148
+ objects, use a configuration class with methods annotated by `Bean`:
149
+
150
+ ```python
151
+ from pyboot.core.builtins.configuration import Bean, Configuration
152
+
153
+
154
+ class Clock:
155
+ ...
156
+
157
+
158
+ @Configuration()
159
+ class ApplicationConfiguration:
160
+ @Bean()
161
+ def clock(self) -> Clock:
162
+ return Clock()
163
+ ```
164
+
165
+ The `@Bean` method must have a return annotation. PyBoot registers that return
166
+ type as a bean factory, resolves any annotated method dependencies, and creates
167
+ the bean through the IoC container. `Component`, `Configuration`, and `Bean`
168
+ are core PyBoot features, not web-specific decorators.
169
+
170
+ ### `pyboot_web.middlewares`
171
+
172
+ - `MiddlewareBase` defines the callable middleware contract.
173
+ - `MiddlewareComponent()` marks a middleware class for IoC registration.
174
+ - `UseMiddleware(middlewares)` attaches middleware classes to a controller or
175
+ route method.
176
+
177
+ Pass middleware classes, not instances. The plugin obtains instances from
178
+ PyBoot's IoC container.
179
+
180
+ ### `pyboot_web.exception_handler`
181
+
182
+ - `RestControllerAdvice()` marks an exception advice class.
183
+ - `ExceptionHandler(exception_type)` maps an exception type to a handler method.
184
+
185
+ Handlers receive `(request, exception)` after `self` and should return a
186
+ Starlette response. A matching base-class handler can handle subclasses.
187
+ Duplicate registrations for the same exception type are rejected. Unhandled
188
+ exceptions are re-raised.
189
+
190
+ ### `pyboot_web.value`
191
+
192
+ - `Value(key, default)` returns an environment value or the supplied default.
193
+ - `MissingValueException` is raised when both are `None`.
194
+ - `ValuePlugin` loads a discovered `.env` file before class discovery.
195
+
196
+ Environment values are strings and should be converted explicitly at the
197
+ configuration boundary. `ValuePlugin` uses `override=True`, so `.env` values
198
+ can replace values already present in the process environment.
199
+
200
+ ### `pyboot_web.plugin`
201
+
202
+ - `WebPlugin` registers web beans, resolves exception advice, wraps routes with
203
+ middleware and exception handling, and adds routes to the supplied Starlette
204
+ application.
205
+
206
+ ## Discovery and lifecycle
207
+
208
+ PyBoot loads installed `pyboot.plugins` entry points, imports the package
209
+ passed to `bootstrap()`, and scans its submodules for classes defined there.
210
+ The web plugin then:
211
+
212
+ 1. Registers `Service`, `Component`, `MiddlewareComponent`,
213
+ `RestControllerAdvice`, and `RestController` classes with the IoC container.
214
+ 2. Lets PyBoot create registered beans.
215
+ 3. Registers exception advice handlers.
216
+ 4. Combines controller and route middleware.
217
+ 5. Adds annotated controller methods as Starlette routes.
218
+
219
+ Keep application classes inside the scanned package and keep module-level
220
+ side effects small and deterministic. Directories intended as packages should
221
+ contain `__init__.py`.
222
+
223
+ ## Compatibility and scope
224
+
225
+ - This package targets Starlette and does not provide Flask or Django adapters.
226
+ - It adds routes to a supplied Starlette application; it does not create one.
227
+ - Services and middleware depend on PyBoot IoC registration and constructor
228
+ resolution.
229
+ - The package root does not re-export the decorators; import them from their
230
+ defining modules.
231
+
232
+ ## License
233
+
234
+ This project is distributed under the MIT License. See [LICENSE](./LICENSE).
@@ -0,0 +1,221 @@
1
+ # pyboot-web
2
+
3
+ `pyboot-web` is the Starlette web plugin for [PyBoot](../../pyboot/README.md).
4
+ It adds decorator-based HTTP controllers, route mappings, services, request
5
+ middleware, centralized exception handlers, and `.env` configuration loading
6
+ to a PyBoot application.
7
+
8
+ The plugin is intentionally small: PyBoot remains responsible for class
9
+ discovery, dependency injection, bean creation, and lifecycle orchestration;
10
+ this package translates annotated classes and methods into Starlette routes.
11
+
12
+ ## Documentation
13
+
14
+ - [Examples](./EXAMPLES.md) - runnable snippets for routing, services,
15
+ middleware, exception advice, and configuration.
16
+ - [Production starter](./STARTER.md) - a recommended project layout,
17
+ bootstrap implementation, deployment checklist, and testing approach.
18
+ - [License](./LICENSE) - MIT license terms.
19
+
20
+ ## Features
21
+
22
+ | Capability | API |
23
+ | --- | --- |
24
+ | HTTP controller | `RestController` |
25
+ | HTTP routes | `GetMapping`, `PostMapping`, `PutMapping`, `PatchMapping`, `DeleteMapping` |
26
+ | Application services | `Service` |
27
+ | PyBoot-managed components | `Component` |
28
+ | Bean factories | `Configuration`, `Bean` |
29
+ | Middleware | `MiddlewareBase`, `MiddlewareComponent`, `UseMiddleware` |
30
+ | Exception advice | `RestControllerAdvice`, `ExceptionHandler` |
31
+ | Environment configuration | `Value`, `ValuePlugin` |
32
+ | PyBoot integration | `WebPlugin`, registered as the `web` PyBoot plugin |
33
+
34
+ The package supports Python 3.11 and newer and uses Starlette for routing and
35
+ request/response types.
36
+
37
+ ## Installation
38
+
39
+ Install PyBoot and this plugin in the same environment:
40
+
41
+ ```bash
42
+ python -m pip install pyboot-framework pyboot-web
43
+ python -m pip install python-dotenv uvicorn
44
+ ```
45
+
46
+ For a source checkout, from the repository root:
47
+
48
+ ```bash
49
+ python -m pip install -e pyboot
50
+ python -m pip install -e plugins/pyboot_web
51
+ python -m pip install python-dotenv uvicorn
52
+ ```
53
+
54
+ The package metadata declares `starlette`. `python-dotenv` is required by the
55
+ `ValuePlugin` implementation.
56
+
57
+ Verify that PyBoot can discover the plugin entry points:
58
+
59
+ ```bash
60
+ python -c "from importlib.metadata import entry_points; print([e.name for e in entry_points(group='pyboot.plugins')])"
61
+ ```
62
+
63
+ The output should include `web`. It may also include `value` and other
64
+ installed plugins.
65
+
66
+ ## Minimal bootstrap contract
67
+
68
+ Create a Starlette application, pass it to PyBoot, bootstrap the package that
69
+ contains the application classes, and expose the original Starlette object:
70
+
71
+ ```python
72
+ from starlette.applications import Starlette
73
+ from pyboot.core.application import PyBoot
74
+
75
+
76
+ app = Starlette(debug=False)
77
+ PyBoot(app_instance=app, debug=False).bootstrap(package="app")
78
+ ```
79
+
80
+ Run it with an ASGI server:
81
+
82
+ ```bash
83
+ python -m uvicorn main:app --host 127.0.0.1 --port 8000
84
+ ```
85
+
86
+ `PyBoot.bootstrap()` returns `None`; it mutates the supplied Starlette
87
+ application by registering routes. Do not assign the return value to `app`.
88
+
89
+ ## API reference
90
+
91
+ ### `pyboot_web.rest_mapping`
92
+
93
+ - `RestController(path: str)` marks a class as an HTTP controller.
94
+ - `GetMapping(path)`, `PostMapping(path)`, `PutMapping(path)`,
95
+ `PatchMapping(path)`, and `DeleteMapping(path)` provide method-specific
96
+ route decorators for methods declared inside a `RestController` class.
97
+
98
+ Route decorators are intended for controller methods, following the
99
+ class-oriented style used by Spring Boot:
100
+
101
+ ```python
102
+ @RestController("/api")
103
+ class HealthController:
104
+ @GetMapping("/health")
105
+ async def health(self, request: Request) -> JSONResponse:
106
+ ...
107
+ ```
108
+
109
+ Supported methods are `GET`, `POST`, `PUT`, `PATCH`, and `DELETE`. A standalone
110
+ function decorated as a route is not discovered by `WebPlugin`.
111
+
112
+ ### `pyboot_web.service`
113
+
114
+ - `Service()` marks a class for web-plugin registration and IoC construction.
115
+
116
+ Use `Service` for web-layer services. Use PyBoot's built-in `Component` for
117
+ general application dependencies that should be managed by the core IoC
118
+ container:
119
+
120
+ ```python
121
+ from pyboot.core.builtins.component import Component
122
+
123
+
124
+ @Component()
125
+ class AuditService:
126
+ ...
127
+ ```
128
+
129
+ `Component` classes can be injected into `Service` classes and controllers
130
+ when their constructor parameters have type annotations.
131
+
132
+ ### PyBoot built-in bean management
133
+
134
+ `Component` is the general-purpose PyBoot IoC decorator. For factory-created
135
+ objects, use a configuration class with methods annotated by `Bean`:
136
+
137
+ ```python
138
+ from pyboot.core.builtins.configuration import Bean, Configuration
139
+
140
+
141
+ class Clock:
142
+ ...
143
+
144
+
145
+ @Configuration()
146
+ class ApplicationConfiguration:
147
+ @Bean()
148
+ def clock(self) -> Clock:
149
+ return Clock()
150
+ ```
151
+
152
+ The `@Bean` method must have a return annotation. PyBoot registers that return
153
+ type as a bean factory, resolves any annotated method dependencies, and creates
154
+ the bean through the IoC container. `Component`, `Configuration`, and `Bean`
155
+ are core PyBoot features, not web-specific decorators.
156
+
157
+ ### `pyboot_web.middlewares`
158
+
159
+ - `MiddlewareBase` defines the callable middleware contract.
160
+ - `MiddlewareComponent()` marks a middleware class for IoC registration.
161
+ - `UseMiddleware(middlewares)` attaches middleware classes to a controller or
162
+ route method.
163
+
164
+ Pass middleware classes, not instances. The plugin obtains instances from
165
+ PyBoot's IoC container.
166
+
167
+ ### `pyboot_web.exception_handler`
168
+
169
+ - `RestControllerAdvice()` marks an exception advice class.
170
+ - `ExceptionHandler(exception_type)` maps an exception type to a handler method.
171
+
172
+ Handlers receive `(request, exception)` after `self` and should return a
173
+ Starlette response. A matching base-class handler can handle subclasses.
174
+ Duplicate registrations for the same exception type are rejected. Unhandled
175
+ exceptions are re-raised.
176
+
177
+ ### `pyboot_web.value`
178
+
179
+ - `Value(key, default)` returns an environment value or the supplied default.
180
+ - `MissingValueException` is raised when both are `None`.
181
+ - `ValuePlugin` loads a discovered `.env` file before class discovery.
182
+
183
+ Environment values are strings and should be converted explicitly at the
184
+ configuration boundary. `ValuePlugin` uses `override=True`, so `.env` values
185
+ can replace values already present in the process environment.
186
+
187
+ ### `pyboot_web.plugin`
188
+
189
+ - `WebPlugin` registers web beans, resolves exception advice, wraps routes with
190
+ middleware and exception handling, and adds routes to the supplied Starlette
191
+ application.
192
+
193
+ ## Discovery and lifecycle
194
+
195
+ PyBoot loads installed `pyboot.plugins` entry points, imports the package
196
+ passed to `bootstrap()`, and scans its submodules for classes defined there.
197
+ The web plugin then:
198
+
199
+ 1. Registers `Service`, `Component`, `MiddlewareComponent`,
200
+ `RestControllerAdvice`, and `RestController` classes with the IoC container.
201
+ 2. Lets PyBoot create registered beans.
202
+ 3. Registers exception advice handlers.
203
+ 4. Combines controller and route middleware.
204
+ 5. Adds annotated controller methods as Starlette routes.
205
+
206
+ Keep application classes inside the scanned package and keep module-level
207
+ side effects small and deterministic. Directories intended as packages should
208
+ contain `__init__.py`.
209
+
210
+ ## Compatibility and scope
211
+
212
+ - This package targets Starlette and does not provide Flask or Django adapters.
213
+ - It adds routes to a supplied Starlette application; it does not create one.
214
+ - Services and middleware depend on PyBoot IoC registration and constructor
215
+ resolution.
216
+ - The package root does not re-export the decorators; import them from their
217
+ defining modules.
218
+
219
+ ## License
220
+
221
+ This project is distributed under the MIT License. See [LICENSE](./LICENSE).
@@ -0,0 +1,24 @@
1
+ [build-system]
2
+ requires = ["setuptools>=75"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pyboot-web"
7
+ version = "0.1.0"
8
+ description = "Starlette web plugin for PyBoot"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "MIT"
12
+
13
+ dependencies = [
14
+ "pyboot-framework>=0.1.0",
15
+ "starlette>=0.40.0",
16
+ "pydantic>=2.0"
17
+ ]
18
+
19
+ [project.entry-points."pyboot.plugins"]
20
+ web = "pyboot_web.plugin:WebPlugin"
21
+ value = "pyboot_web.value:ValuePlugin"
22
+
23
+ [tool.setuptools.packages.find]
24
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,33 @@
1
+ from typing import Callable
2
+
3
+ from starlette.requests import Request
4
+ from starlette.responses import JSONResponse
5
+
6
+ #Exception Resolver
7
+ class ExceptionResolver:
8
+ def __init__(self) -> None:
9
+ self.handlers: dict[
10
+ type[Exception], Callable[[Request, Exception], JSONResponse]
11
+ ] = dict()
12
+ return
13
+
14
+ def register(
15
+ self,
16
+ exception_type: type[Exception],
17
+ handler: Callable[[Request, Exception], JSONResponse],
18
+ ):
19
+ if exception_type in self.handlers:
20
+ raise TypeError(f"Handler already registered for {exception_type.__name__}")
21
+
22
+ self.handlers[exception_type] = handler
23
+ return
24
+
25
+ def resolve(self, request: Request, exception: Exception) -> JSONResponse:
26
+ for exception_class in type(exception).__mro__:
27
+ handler = self.handlers.get(exception_class)
28
+
29
+ if handler is not None:
30
+ return handler(request, exception)
31
+
32
+ raise exception
33
+
@@ -0,0 +1,18 @@
1
+ from enum import Enum
2
+
3
+ class WebAttr(Enum):
4
+ IS_REST_CONTROLLER="__is_rest_controller__"
5
+ REST_CONTROLLER_PATH="__rest_controller_path__"
6
+
7
+ IS_ROUTE="__is_route__"
8
+ ROUTE_PATH="__route_path__"
9
+ ROUTE_METHOD="__route_method__"
10
+
11
+ IS_MIDDLEWARE_COMPONENT="__is_middleware_component__"
12
+ MIDDLEWARE_LIST="__middleware_list__"
13
+
14
+ IS_WEB_SERVICE="__is_web_service__"
15
+
16
+ IS_REST_CONTROLLER_ADVICE="__is_rest_controller_advice__"
17
+ IS_EXCEPTION_HANDLER_METHOD="__is_exception_handler__"
18
+ EXCEPTION_HANDLER_FOR="__exception_handler_for__"
File without changes
@@ -0,0 +1,25 @@
1
+ from pyboot.core.types import ClassT
2
+
3
+ from .WebAttr import WebAttr
4
+
5
+ from .types import *
6
+
7
+ class RestControllerAdvice:
8
+ def __init__(self) -> None:
9
+ pass
10
+
11
+ def __call__(self,clazz:ClassT) -> ClassT:
12
+ setattr(clazz,WebAttr.IS_REST_CONTROLLER_ADVICE.value,True)
13
+ return clazz
14
+
15
+ class ExceptionHandler:
16
+ def __init__(self,exception_type:type[Exception]) -> None:
17
+ self.exception_type:type[Exception]=exception_type
18
+ pass
19
+
20
+ def __call__(self,func:Callable[[Any,Request,E],JSONResponse]) -> Callable[[Any,Request,E],JSONResponse]:
21
+ setattr(func,WebAttr.IS_EXCEPTION_HANDLER_METHOD.value,True)
22
+ setattr(func,WebAttr.EXCEPTION_HANDLER_FOR.value,self.exception_type)
23
+
24
+ return func
25
+
@@ -0,0 +1,44 @@
1
+ from starlette.requests import Request
2
+ from starlette.responses import JSONResponse
3
+
4
+ from typing import Callable,Awaitable,overload
5
+ from abc import ABC,abstractmethod
6
+
7
+ from .WebAttr import WebAttr
8
+
9
+ from .rest_mapping import ControllerMethodT
10
+
11
+ from pyboot.core.types import ClassTBase,ClassT
12
+
13
+ CallNext=Callable[[Request],JSONResponse | Awaitable[JSONResponse]]
14
+
15
+ class MiddlewareBase(ABC):
16
+ @abstractmethod
17
+ def __call__(self,request:Request,call_next:CallNext) -> JSONResponse|Awaitable[JSONResponse]:
18
+ pass
19
+
20
+ class UseMiddleware:
21
+ def __init__(self,middlewares:list[type[MiddlewareBase]]) -> None:
22
+ self.middlewares:list[type[MiddlewareBase]]=middlewares
23
+ pass
24
+
25
+ @overload
26
+ def __call__(self,target:ClassTBase)->ClassTBase:
27
+ pass
28
+
29
+ @overload
30
+ def __call__(self,target:ControllerMethodT)->ControllerMethodT:
31
+ pass
32
+
33
+ def __call__(self, target:ClassTBase|ControllerMethodT) -> ClassTBase|ControllerMethodT:
34
+ setattr(target,WebAttr.MIDDLEWARE_LIST.value,self.middlewares)
35
+ return target
36
+
37
+ class MiddlewareComponent:
38
+ def __init__(self) -> None:
39
+ pass
40
+
41
+ def __call__(self,clazz:ClassT) -> ClassT:
42
+ setattr(clazz,WebAttr.IS_MIDDLEWARE_COMPONENT.value,True)
43
+ return clazz
44
+