starmallow 0.8.0__py3-none-any.whl → 0.9.0__py3-none-any.whl

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.
@@ -1,33 +1,20 @@
1
- import os
1
+ from collections.abc import Awaitable, Callable, Mapping, Sequence
2
+ from contextlib import AbstractAsyncContextManager
2
3
  from enum import Enum
3
4
  from logging import getLogger
4
- from string import Template
5
- from typing import (
6
- Any,
7
- AsyncContextManager,
8
- Awaitable,
9
- Callable,
10
- Dict,
11
- List,
12
- Mapping,
13
- Optional,
14
- Sequence,
15
- Set,
16
- Type,
17
- Union,
18
- )
5
+ from typing import Any
19
6
 
20
7
  from starlette.applications import Starlette
21
8
  from starlette.datastructures import State
22
9
  from starlette.exceptions import HTTPException
23
10
  from starlette.middleware import Middleware
24
- from starlette.middleware.base import BaseHTTPMiddleware
11
+ from starlette.middleware.base import BaseHTTPMiddleware, DispatchFunction
25
12
  from starlette.middleware.errors import ServerErrorMiddleware
26
13
  from starlette.middleware.exceptions import ExceptionMiddleware
27
14
  from starlette.requests import Request
28
15
  from starlette.responses import HTMLResponse, Response
29
16
  from starlette.routing import BaseRoute
30
- from starlette.types import ASGIApp, Receive, Scope, Send
17
+ from starlette.types import ASGIApp, ExceptionHandler, Receive, Scope, Send
31
18
 
32
19
  from starmallow.datastructures import Default
33
20
  from starmallow.docs import get_redoc_html, get_swagger_ui_html, get_swagger_ui_oauth2_redirect_html
@@ -41,42 +28,41 @@ from starmallow.middleware import AsyncExitStackMiddleware
41
28
  from starmallow.responses import JSONResponse
42
29
  from starmallow.routing import APIRoute, APIRouter
43
30
  from starmallow.schema_generator import SchemaGenerator
44
- from starmallow.types import DecoratedCallable
31
+ from starmallow.types import DecoratedCallable, WebSocketEndpointCallable
45
32
  from starmallow.utils import generate_unique_id
46
33
 
47
34
  logger = getLogger(__name__)
48
35
 
36
+
49
37
  class StarMallow(Starlette):
50
38
 
51
39
  def __init__(
52
40
  self,
53
41
  *args,
54
42
  debug: bool = False,
55
- routes: Optional[List[BaseRoute]] = None,
56
- middleware: Sequence[Middleware] = None,
43
+ routes: list[BaseRoute] | None = None,
44
+ middleware: Sequence[Middleware] | None = None,
57
45
  exception_handlers: Mapping[
58
46
  Any,
59
- Callable[
60
- [Request, Exception], Union[Response, Awaitable[Response]],
61
- ],
62
- ] = None,
63
- on_startup: Optional[Sequence[Callable[[], Any]]] = None,
64
- on_shutdown: Optional[Sequence[Callable[[], Any]]] = None,
65
- lifespan: Callable[[Starlette], AsyncContextManager] = None,
47
+ Callable[[Request, Exception], Response | Awaitable[Response]],
48
+ ] | None = None,
49
+ on_startup: Sequence[Callable[[], Any]] | None = None,
50
+ on_shutdown: Sequence[Callable[[], Any]] | None = None,
51
+ lifespan: Callable[[Starlette], AbstractAsyncContextManager] | None = None,
66
52
 
67
53
  title: str = "StarMallow",
68
54
  description: str = "",
69
55
  version: str = "0.1.0",
70
56
  root_path: str = "",
71
- openapi_url: Optional[str] = "/openapi.json",
72
- openapi_tags: Optional[List[Dict[str, Any]]] = None,
73
- docs_url: Optional[str] = "/docs",
74
- redoc_url: Optional[str] = "/redoc",
75
- swagger_ui_oauth2_redirect_url: Optional[str] = "/docs/oauth2-redirect",
76
- swagger_ui_init_oauth: Optional[Dict[str, Any]] = None,
77
- swagger_ui_parameters: Optional[Dict[str, Any]] = None,
78
-
79
- deprecated: Optional[bool] = None,
57
+ openapi_url: str | None = "/openapi.json",
58
+ openapi_tags: list[dict[str, Any]] | None = None,
59
+ docs_url: str | None = "/docs",
60
+ redoc_url: str | None = "/redoc",
61
+ swagger_ui_oauth2_redirect_url: str | None = "/docs/oauth2-redirect",
62
+ swagger_ui_init_oauth: dict[str, Any] | None = None,
63
+ swagger_ui_parameters: dict[str, Any] | None = None,
64
+
65
+ deprecated: bool | None = None,
80
66
  include_in_schema: bool = True,
81
67
 
82
68
  **kwargs,
@@ -95,7 +81,7 @@ class StarMallow(Starlette):
95
81
  self.openapi_url = openapi_url
96
82
  self.openapi_tags = openapi_tags
97
83
  self.openapi_version = "3.0.2"
98
- self.openapi_schema: Optional[Dict[str, Any]] = None
84
+ self.openapi_schema: dict[str, Any] | None = None
99
85
  self.docs_url = docs_url
100
86
  self.redoc_url = redoc_url
101
87
  self.swagger_ui_oauth2_redirect_url = swagger_ui_oauth2_redirect_url
@@ -118,20 +104,18 @@ class StarMallow(Starlette):
118
104
  self.exception_handlers = (
119
105
  {} if exception_handlers is None else dict(exception_handlers)
120
106
  )
121
- self.exception_handlers.setdefault(HTTPException, http_exception_handler)
122
- self.exception_handlers.setdefault(
123
- RequestValidationError, request_validation_exception_handler,
124
- )
107
+ self.exception_handlers.setdefault(HTTPException, http_exception_handler) # type: ignore
108
+ self.exception_handlers.setdefault(RequestValidationError, request_validation_exception_handler) # type: ignore
125
109
 
126
110
  self.user_middleware = [] if middleware is None else list(middleware)
127
- self.middleware_stack: Union[ASGIApp, None] = None
111
+ self.middleware_stack: ASGIApp | None = None
128
112
  self.init_openapi()
129
113
 
130
114
  def build_middleware_stack(self) -> ASGIApp:
131
115
  debug = self.debug
132
116
  error_handler = None
133
- exception_handlers: Dict[
134
- Any, Callable[[Request, Exception], Response],
117
+ exception_handlers: dict[
118
+ Any, Callable[[Request, Exception], Response | Awaitable[Response]],
135
119
  ] = {}
136
120
 
137
121
  for key, value in self.exception_handlers.items():
@@ -143,24 +127,20 @@ class StarMallow(Starlette):
143
127
 
144
128
  exception_handlers[key] = value
145
129
 
146
- middleware = (
147
- [Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)]
148
- + self.user_middleware
149
- + [
150
- Middleware(
151
- ExceptionMiddleware, handlers=exception_handlers, debug=debug,
152
- ),
153
- # Teardown all ResolvedParam contextmanagers
154
- Middleware(AsyncExitStackMiddleware),
155
- ]
156
- )
130
+ middleware = [
131
+ Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug),
132
+ *self.user_middleware,
133
+ Middleware(ExceptionMiddleware, handlers=exception_handlers, debug=debug), # type: ignore Starlette does support awaitable
134
+ # Teardown all ResolvedParam contextmanagers
135
+ Middleware(AsyncExitStackMiddleware),
136
+ ]
157
137
 
158
138
  app = self.router
159
139
  for cls, args, kwargs in reversed(middleware):
160
- app = cls(app=app, *args, **kwargs) # noqa: B026
140
+ app = cls(app, *args, **kwargs)
161
141
  return app
162
142
 
163
- def openapi(self) -> Dict[str, Any]:
143
+ def openapi(self) -> dict[str, Any]:
164
144
  if not self.openapi_schema:
165
145
  self.openapi_schema = SchemaGenerator(
166
146
  self.title,
@@ -171,25 +151,28 @@ class StarMallow(Starlette):
171
151
  return self.openapi_schema
172
152
 
173
153
  def init_openapi(self):
174
- if self.openapi_url:
175
- async def openapi(req: Request) -> JSONResponse:
176
- try:
177
- return JSONResponse(self.openapi())
178
- except Exception as e:
179
- logger.exception('Failed to generate OpenAPI schema')
180
- raise SchemaGenerationError() from e
154
+ if not self.openapi_url:
155
+ return
156
+
157
+ openapi_url: str = self.openapi_url
158
+
159
+ async def openapi(req: Request) -> JSONResponse:
160
+ try:
161
+ return JSONResponse(self.openapi())
162
+ except Exception as e:
163
+ logger.exception('Failed to generate OpenAPI schema')
164
+ raise SchemaGenerationError() from e
181
165
 
182
- self.add_route(self.openapi_url, openapi, include_in_schema=False)
166
+ self.add_route(openapi_url, openapi, include_in_schema=False)
183
167
 
184
- if self.openapi_url and self.docs_url:
168
+ if self.docs_url:
185
169
  async def swagger_ui_html(req: Request) -> HTMLResponse:
186
- root_path = req.scope.get("root_path", "").rstrip("/")
187
- openapi_url = root_path + self.openapi_url
170
+ root_path: str = req.scope.get("root_path", "").rstrip("/")
188
171
  oauth2_redirect_url = self.swagger_ui_oauth2_redirect_url
189
172
  if oauth2_redirect_url:
190
173
  oauth2_redirect_url = root_path + oauth2_redirect_url
191
174
  return get_swagger_ui_html(
192
- openapi_url=openapi_url,
175
+ openapi_url=root_path + openapi_url,
193
176
  title=self.title + " - Swagger UI",
194
177
  oauth2_redirect_url=oauth2_redirect_url,
195
178
  init_oauth=self.swagger_ui_init_oauth,
@@ -209,34 +192,15 @@ class StarMallow(Starlette):
209
192
  include_in_schema=False,
210
193
  )
211
194
 
212
- if self.openapi_url and self.redoc_url:
195
+ if self.redoc_url:
213
196
  async def redoc_html(req: Request) -> HTMLResponse:
214
197
  root_path = req.scope.get("root_path", "").rstrip("/")
215
- openapi_url = root_path + self.openapi_url
216
198
  return get_redoc_html(
217
- openapi_url=openapi_url, title=self.title + " - ReDoc",
199
+ openapi_url=root_path + openapi_url, title=self.title + " - ReDoc",
218
200
  )
219
201
 
220
202
  self.add_route(self.redoc_url, redoc_html, include_in_schema=False)
221
203
 
222
- def add_docs_route(self):
223
- def swagger_ui() -> HTMLResponse:
224
- with open(os.path.join(os.path.dirname(__file__), "templates/swagger_ui.html")) as f:
225
- content = Template(f.read()).substitute(title=self.title, schema_url=self.schema_url)
226
-
227
- return HTMLResponse(content)
228
-
229
- self.add_route(path=self.docs_url, route=swagger_ui, methods=["GET"], include_in_schema=False)
230
-
231
- def add_redoc_route(self):
232
- def redoc() -> HTMLResponse:
233
- with open(os.path.join(os.path.dirname(__file__), "templates/redoc.html")) as f:
234
- content = Template(f.read()).substitute(title=self.title, schema_url=self.schema_url)
235
-
236
- return HTMLResponse(content)
237
-
238
- self.add_route(path=self.redoc_url, route=redoc, methods=["GET"], include_in_schema=False)
239
-
240
204
  async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
241
205
  if self.root_path:
242
206
  scope["root_path"] = self.root_path
@@ -245,30 +209,30 @@ class StarMallow(Starlette):
245
209
  def add_api_route(
246
210
  self,
247
211
  path: str,
248
- endpoint: Union[Callable[..., Any], APIHTTPEndpoint],
212
+ endpoint: Callable[..., Any] | APIHTTPEndpoint,
249
213
  *,
250
- methods: Optional[Union[Set[str], List[str]]] = None,
251
- name: str = None,
214
+ methods: set[str] | list[str] | None = None,
215
+ name: str | None = None,
252
216
  include_in_schema: bool = True,
253
- status_code: Optional[int] = None,
217
+ status_code: int | None = None,
254
218
  middleware: Sequence[Middleware] | None = None,
255
- request_class: Type[Request] = Default(Request),
256
- response_model: Optional[Type[Any]] = None,
257
- response_class: Type[Response] = JSONResponse,
219
+ request_class: type[Request] = Default(Request),
220
+ response_model: type[Any] | None = None,
221
+ response_class: type[Response] = JSONResponse,
258
222
  # OpenAPI summary
259
- summary: Optional[str] = None,
260
- description: Optional[str] = None,
223
+ summary: str | None = None,
224
+ description: str | None = None,
261
225
  response_description: str = "Successful Response",
262
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
263
- callbacks: Optional[List[BaseRoute]] = None,
226
+ responses: dict[int | str, dict[str, Any]] | None = None,
227
+ callbacks: list[BaseRoute] | None = None,
264
228
  # Sets the OpenAPI operationId to be used in your path operation
265
- operation_id: Optional[str] = None,
229
+ operation_id: str | None = None,
266
230
  # If operation_id is None, this function will be used to create one.
267
231
  generate_unique_id_function: Callable[["APIRoute"], str] = Default(generate_unique_id),
268
232
  # OpenAPI tags
269
- tags: Optional[List[Union[str, Enum]]] = None,
233
+ tags: list[str | Enum] | None = None,
270
234
  # Will be deeply merged with the automatically generated OpenAPI schema for the path operation.
271
- openapi_extra: Optional[Dict[str, Any]] = None,
235
+ openapi_extra: dict[str, Any] | None = None,
272
236
  ) -> None:
273
237
  return self.router.add_api_route(
274
238
  path=path,
@@ -296,28 +260,28 @@ class StarMallow(Starlette):
296
260
  self,
297
261
  path: str,
298
262
  *,
299
- methods: Optional[Union[Set[str], List[str]]] = None,
300
- name: str = None,
263
+ methods: set[str] | list[str] | None = None,
264
+ name: str | None = None,
301
265
  include_in_schema: bool = True,
302
- status_code: Optional[int] = None,
266
+ status_code: int | None = None,
303
267
  middleware: Sequence[Middleware] | None = None,
304
- request_class: Type[Request] = Default(Request),
305
- response_model: Optional[Type[Any]] = None,
306
- response_class: Type[Response] = JSONResponse,
268
+ request_class: type[Request] = Default(Request),
269
+ response_model: type[Any] | None = None,
270
+ response_class: type[Response] = JSONResponse,
307
271
  # OpenAPI summary
308
- summary: Optional[str] = None,
309
- description: Optional[str] = None,
272
+ summary: str | None = None,
273
+ description: str | None = None,
310
274
  response_description: str = "Successful Response",
311
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
312
- callbacks: Optional[List[BaseRoute]] = None,
275
+ responses: dict[int | str, dict[str, Any]] | None = None,
276
+ callbacks: list[BaseRoute] | None = None,
313
277
  # Sets the OpenAPI operationId to be used in your path operation
314
- operation_id: Optional[str] = None,
278
+ operation_id: str | None = None,
315
279
  # If operation_id is None, this function will be used to create one.
316
280
  generate_unique_id_function: Callable[["APIRoute"], str] = Default(generate_unique_id),
317
281
  # OpenAPI tags
318
- tags: Optional[List[Union[str, Enum]]] = None,
282
+ tags: list[str | Enum] | None = None,
319
283
  # Will be deeply merged with the automatically generated OpenAPI schema for the path operation.
320
- openapi_extra: Optional[Dict[str, Any]] = None,
284
+ openapi_extra: dict[str, Any] | None = None,
321
285
  ) -> Callable[[DecoratedCallable], DecoratedCallable]:
322
286
  return self.router.api_route(
323
287
  path=path,
@@ -341,14 +305,14 @@ class StarMallow(Starlette):
341
305
  )
342
306
 
343
307
  def add_api_websocket_route(
344
- self, path: str, endpoint: Callable[..., Any], name: Optional[str] = None,
308
+ self, path: str, endpoint: WebSocketEndpointCallable, name: str | None = None,
345
309
  ) -> None:
346
310
  self.router.add_api_websocket_route(path, endpoint, name=name)
347
311
 
348
312
  def websocket(
349
- self, path: str, name: Optional[str] = None,
350
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
351
- def decorator(func: DecoratedCallable) -> DecoratedCallable:
313
+ self, path: str, name: str | None = None,
314
+ ) -> Callable[[WebSocketEndpointCallable], WebSocketEndpointCallable]:
315
+ def decorator(func: WebSocketEndpointCallable) -> WebSocketEndpointCallable:
352
316
  self.add_api_websocket_route(path, func, name=name)
353
317
  return func
354
318
 
@@ -359,13 +323,13 @@ class StarMallow(Starlette):
359
323
  router: APIRouter,
360
324
  *,
361
325
  prefix: str = "",
362
- tags: Optional[List[Union[str, Enum]]] = None,
363
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
364
- callbacks: Optional[List[BaseRoute]] = None,
365
- deprecated: Optional[bool] = None,
326
+ tags: list[str | Enum] | None = None,
327
+ responses: dict[int | str, dict[str, Any]] | None = None,
328
+ callbacks: list[BaseRoute] | None = None,
329
+ deprecated: bool | None = None,
366
330
  include_in_schema: bool = True,
367
- default_request_class: Type[Request] = Default(Request),
368
- default_response_class: Type[Response] = Default(JSONResponse),
331
+ default_request_class: type[Request] = Default(Request),
332
+ default_response_class: type[Response] = Default(JSONResponse),
369
333
  generate_unique_id_function: Callable[[APIRoute], str] = Default(
370
334
  generate_unique_id,
371
335
  ),
@@ -387,27 +351,27 @@ class StarMallow(Starlette):
387
351
  self,
388
352
  path: str,
389
353
  *,
390
- name: str = None,
354
+ name: str | None = None,
391
355
  include_in_schema: bool = True,
392
- status_code: Optional[int] = None,
356
+ status_code: int | None = None,
393
357
  middleware: Sequence[Middleware] | None = None,
394
- request_class: Type[Request] = Default(Request),
395
- response_model: Optional[Type[Any]] = None,
396
- response_class: Type[Response] = JSONResponse,
358
+ request_class: type[Request] = Default(Request),
359
+ response_model: type[Any] | None = None,
360
+ response_class: type[Response] = JSONResponse,
397
361
  # OpenAPI summary
398
- summary: Optional[str] = None,
399
- description: Optional[str] = None,
362
+ summary: str | None = None,
363
+ description: str | None = None,
400
364
  response_description: str = "Successful Response",
401
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
402
- callbacks: Optional[List[BaseRoute]] = None,
365
+ responses: dict[int | str, dict[str, Any]] | None = None,
366
+ callbacks: list[BaseRoute] | None = None,
403
367
  # Sets the OpenAPI operationId to be used in your path operation
404
- operation_id: Optional[str] = None,
368
+ operation_id: str | None = None,
405
369
  # If operation_id is None, this function will be used to create one.
406
370
  generate_unique_id_function: Callable[["APIRoute"], str] = Default(generate_unique_id),
407
371
  # OpenAPI tags
408
- tags: Optional[List[Union[str, Enum]]] = None,
372
+ tags: list[str | Enum] | None = None,
409
373
  # Will be deeply merged with the automatically generated OpenAPI schema for the path operation.
410
- openapi_extra: Optional[Dict[str, Any]] = None,
374
+ openapi_extra: dict[str, Any] | None = None,
411
375
  ):
412
376
  return self.router.get(
413
377
  path,
@@ -433,27 +397,27 @@ class StarMallow(Starlette):
433
397
  self,
434
398
  path: str,
435
399
  *,
436
- name: str = None,
400
+ name: str | None = None,
437
401
  include_in_schema: bool = True,
438
- status_code: Optional[int] = None,
402
+ status_code: int | None = None,
439
403
  middleware: Sequence[Middleware] | None = None,
440
- request_class: Type[Request] = Default(Request),
441
- response_model: Optional[Type[Any]] = None,
442
- response_class: Type[Response] = JSONResponse,
404
+ request_class: type[Request] = Default(Request),
405
+ response_model: type[Any] | None = None,
406
+ response_class: type[Response] = JSONResponse,
443
407
  # OpenAPI summary
444
- summary: Optional[str] = None,
445
- description: Optional[str] = None,
408
+ summary: str | None = None,
409
+ description: str | None = None,
446
410
  response_description: str = "Successful Response",
447
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
448
- callbacks: Optional[List[BaseRoute]] = None,
411
+ responses: dict[int | str, dict[str, Any]] | None = None,
412
+ callbacks: list[BaseRoute] | None = None,
449
413
  # Sets the OpenAPI operationId to be used in your path operation
450
- operation_id: Optional[str] = None,
414
+ operation_id: str | None = None,
451
415
  # If operation_id is None, this function will be used to create one.
452
416
  generate_unique_id_function: Callable[["APIRoute"], str] = Default(generate_unique_id),
453
417
  # OpenAPI tags
454
- tags: Optional[List[Union[str, Enum]]] = None,
418
+ tags: list[str | Enum] | None = None,
455
419
  # Will be deeply merged with the automatically generated OpenAPI schema for the path operation.
456
- openapi_extra: Optional[Dict[str, Any]] = None,
420
+ openapi_extra: dict[str, Any] | None = None,
457
421
  ):
458
422
  return self.router.put(
459
423
  path,
@@ -479,27 +443,27 @@ class StarMallow(Starlette):
479
443
  self,
480
444
  path: str,
481
445
  *,
482
- name: str = None,
446
+ name: str | None = None,
483
447
  include_in_schema: bool = True,
484
- status_code: Optional[int] = None,
448
+ status_code: int | None = None,
485
449
  middleware: Sequence[Middleware] | None = None,
486
- request_class: Type[Request] = Default(Request),
487
- response_model: Optional[Type[Any]] = None,
488
- response_class: Type[Response] = JSONResponse,
450
+ request_class: type[Request] = Default(Request),
451
+ response_model: type[Any] | None = None,
452
+ response_class: type[Response] = JSONResponse,
489
453
  # OpenAPI summary
490
- summary: Optional[str] = None,
491
- description: Optional[str] = None,
454
+ summary: str | None = None,
455
+ description: str | None = None,
492
456
  response_description: str = "Successful Response",
493
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
494
- callbacks: Optional[List[BaseRoute]] = None,
457
+ responses: dict[int | str, dict[str, Any]] | None = None,
458
+ callbacks: list[BaseRoute] | None = None,
495
459
  # Sets the OpenAPI operationId to be used in your path operation
496
- operation_id: Optional[str] = None,
460
+ operation_id: str | None = None,
497
461
  # If operation_id is None, this function will be used to create one.
498
462
  generate_unique_id_function: Callable[["APIRoute"], str] = Default(generate_unique_id),
499
463
  # OpenAPI tags
500
- tags: Optional[List[Union[str, Enum]]] = None,
464
+ tags: list[str | Enum] | None = None,
501
465
  # Will be deeply merged with the automatically generated OpenAPI schema for the path operation.
502
- openapi_extra: Optional[Dict[str, Any]] = None,
466
+ openapi_extra: dict[str, Any] | None = None,
503
467
  ):
504
468
  return self.router.post(
505
469
  path,
@@ -525,27 +489,27 @@ class StarMallow(Starlette):
525
489
  self,
526
490
  path: str,
527
491
  *,
528
- name: str = None,
492
+ name: str | None = None,
529
493
  include_in_schema: bool = True,
530
- status_code: Optional[int] = None,
494
+ status_code: int | None = None,
531
495
  middleware: Sequence[Middleware] | None = None,
532
- request_class: Type[Request] = Default(Request),
533
- response_model: Optional[Type[Any]] = None,
534
- response_class: Type[Response] = JSONResponse,
496
+ request_class: type[Request] = Default(Request),
497
+ response_model: type[Any] | None = None,
498
+ response_class: type[Response] = JSONResponse,
535
499
  # OpenAPI summary
536
- summary: Optional[str] = None,
537
- description: Optional[str] = None,
500
+ summary: str | None = None,
501
+ description: str | None = None,
538
502
  response_description: str = "Successful Response",
539
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
540
- callbacks: Optional[List[BaseRoute]] = None,
503
+ responses: dict[int | str, dict[str, Any]] | None = None,
504
+ callbacks: list[BaseRoute] | None = None,
541
505
  # Sets the OpenAPI operationId to be used in your path operation
542
- operation_id: Optional[str] = None,
506
+ operation_id: str | None = None,
543
507
  # If operation_id is None, this function will be used to create one.
544
508
  generate_unique_id_function: Callable[["APIRoute"], str] = Default(generate_unique_id),
545
509
  # OpenAPI tags
546
- tags: Optional[List[Union[str, Enum]]] = None,
510
+ tags: list[str | Enum] | None = None,
547
511
  # Will be deeply merged with the automatically generated OpenAPI schema for the path operation.
548
- openapi_extra: Optional[Dict[str, Any]] = None,
512
+ openapi_extra: dict[str, Any] | None = None,
549
513
  ):
550
514
  return self.router.delete(
551
515
  path,
@@ -571,27 +535,27 @@ class StarMallow(Starlette):
571
535
  self,
572
536
  path: str,
573
537
  *,
574
- name: str = None,
538
+ name: str | None = None,
575
539
  include_in_schema: bool = True,
576
- status_code: Optional[int] = None,
540
+ status_code: int | None = None,
577
541
  middleware: Sequence[Middleware] | None = None,
578
- request_class: Type[Request] = Default(Request),
579
- response_model: Optional[Type[Any]] = None,
580
- response_class: Type[Response] = JSONResponse,
542
+ request_class: type[Request] = Default(Request),
543
+ response_model: type[Any] | None = None,
544
+ response_class: type[Response] = JSONResponse,
581
545
  # OpenAPI summary
582
- summary: Optional[str] = None,
583
- description: Optional[str] = None,
546
+ summary: str | None = None,
547
+ description: str | None = None,
584
548
  response_description: str = "Successful Response",
585
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
586
- callbacks: Optional[List[BaseRoute]] = None,
549
+ responses: dict[int | str, dict[str, Any]] | None = None,
550
+ callbacks: list[BaseRoute] | None = None,
587
551
  # Sets the OpenAPI operationId to be used in your path operation
588
- operation_id: Optional[str] = None,
552
+ operation_id: str | None = None,
589
553
  # If operation_id is None, this function will be used to create one.
590
554
  generate_unique_id_function: Callable[["APIRoute"], str] = Default(generate_unique_id),
591
555
  # OpenAPI tags
592
- tags: Optional[List[Union[str, Enum]]] = None,
556
+ tags: list[str | Enum] | None = None,
593
557
  # Will be deeply merged with the automatically generated OpenAPI schema for the path operation.
594
- openapi_extra: Optional[Dict[str, Any]] = None,
558
+ openapi_extra: dict[str, Any] | None = None,
595
559
  ):
596
560
  return self.router.options(
597
561
  path,
@@ -617,27 +581,27 @@ class StarMallow(Starlette):
617
581
  self,
618
582
  path: str,
619
583
  *,
620
- name: str = None,
584
+ name: str | None = None,
621
585
  include_in_schema: bool = True,
622
- status_code: Optional[int] = None,
586
+ status_code: int | None = None,
623
587
  middleware: Sequence[Middleware] | None = None,
624
- request_class: Type[Request] = Default(Request),
625
- response_model: Optional[Type[Any]] = None,
626
- response_class: Type[Response] = JSONResponse,
588
+ request_class: type[Request] = Default(Request),
589
+ response_model: type[Any] | None = None,
590
+ response_class: type[Response] = JSONResponse,
627
591
  # OpenAPI summary
628
- summary: Optional[str] = None,
629
- description: Optional[str] = None,
592
+ summary: str | None = None,
593
+ description: str | None = None,
630
594
  response_description: str = "Successful Response",
631
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
632
- callbacks: Optional[List[BaseRoute]] = None,
595
+ responses: dict[int | str, dict[str, Any]] | None = None,
596
+ callbacks: list[BaseRoute] | None = None,
633
597
  # Sets the OpenAPI operationId to be used in your path operation
634
- operation_id: Optional[str] = None,
598
+ operation_id: str | None = None,
635
599
  # If operation_id is None, this function will be used to create one.
636
600
  generate_unique_id_function: Callable[["APIRoute"], str] = Default(generate_unique_id),
637
601
  # OpenAPI tags
638
- tags: Optional[List[Union[str, Enum]]] = None,
602
+ tags: list[str | Enum] | None = None,
639
603
  # Will be deeply merged with the automatically generated OpenAPI schema for the path operation.
640
- openapi_extra: Optional[Dict[str, Any]] = None,
604
+ openapi_extra: dict[str, Any] | None = None,
641
605
  ):
642
606
  return self.router.head(
643
607
  path,
@@ -663,27 +627,27 @@ class StarMallow(Starlette):
663
627
  self,
664
628
  path: str,
665
629
  *,
666
- name: str = None,
630
+ name: str | None = None,
667
631
  include_in_schema: bool = True,
668
- status_code: Optional[int] = None,
632
+ status_code: int | None = None,
669
633
  middleware: Sequence[Middleware] | None = None,
670
- request_class: Type[Request] = Default(Request),
671
- response_model: Optional[Type[Any]] = None,
672
- response_class: Type[Response] = JSONResponse,
634
+ request_class: type[Request] = Default(Request),
635
+ response_model: type[Any] | None = None,
636
+ response_class: type[Response] = JSONResponse,
673
637
  # OpenAPI summary
674
- summary: Optional[str] = None,
675
- description: Optional[str] = None,
638
+ summary: str | None = None,
639
+ description: str | None = None,
676
640
  response_description: str = "Successful Response",
677
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
678
- callbacks: Optional[List[BaseRoute]] = None,
641
+ responses: dict[int | str, dict[str, Any]] | None = None,
642
+ callbacks: list[BaseRoute] | None = None,
679
643
  # Sets the OpenAPI operationId to be used in your path operation
680
- operation_id: Optional[str] = None,
644
+ operation_id: str | None = None,
681
645
  # If operation_id is None, this function will be used to create one.
682
646
  generate_unique_id_function: Callable[["APIRoute"], str] = Default(generate_unique_id),
683
647
  # OpenAPI tags
684
- tags: Optional[List[Union[str, Enum]]] = None,
648
+ tags: list[str | Enum] | None = None,
685
649
  # Will be deeply merged with the automatically generated OpenAPI schema for the path operation.
686
- openapi_extra: Optional[Dict[str, Any]] = None,
650
+ openapi_extra: dict[str, Any] | None = None,
687
651
  ):
688
652
  return self.router.patch(
689
653
  path,
@@ -709,27 +673,27 @@ class StarMallow(Starlette):
709
673
  self,
710
674
  path: str,
711
675
  *,
712
- name: str = None,
676
+ name: str | None = None,
713
677
  include_in_schema: bool = True,
714
- status_code: Optional[int] = None,
678
+ status_code: int | None = None,
715
679
  middleware: Sequence[Middleware] | None = None,
716
- request_class: Type[Request] = Default(Request),
717
- response_model: Optional[Type[Any]] = None,
718
- response_class: Type[Response] = JSONResponse,
680
+ request_class: type[Request] = Default(Request),
681
+ response_model: type[Any] | None = None,
682
+ response_class: type[Response] = JSONResponse,
719
683
  # OpenAPI summary
720
- summary: Optional[str] = None,
721
- description: Optional[str] = None,
684
+ summary: str | None = None,
685
+ description: str | None = None,
722
686
  response_description: str = "Successful Response",
723
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
724
- callbacks: Optional[List[BaseRoute]] = None,
687
+ responses: dict[int | str, dict[str, Any]] | None = None,
688
+ callbacks: list[BaseRoute] | None = None,
725
689
  # Sets the OpenAPI operationId to be used in your path operation
726
- operation_id: Optional[str] = None,
690
+ operation_id: str | None = None,
727
691
  # If operation_id is None, this function will be used to create one.
728
692
  generate_unique_id_function: Callable[["APIRoute"], str] = Default(generate_unique_id),
729
693
  # OpenAPI tags
730
- tags: Optional[List[Union[str, Enum]]] = None,
694
+ tags: list[str | Enum] | None = None,
731
695
  # Will be deeply merged with the automatically generated OpenAPI schema for the path operation.
732
- openapi_extra: Optional[Dict[str, Any]] = None,
696
+ openapi_extra: dict[str, Any] | None = None,
733
697
  ):
734
698
  return self.router.trace(
735
699
  path,
@@ -752,9 +716,9 @@ class StarMallow(Starlette):
752
716
  )
753
717
 
754
718
  def websocket_route(
755
- self, path: str, name: Union[str, None] = None,
756
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
757
- def decorator(func: DecoratedCallable) -> DecoratedCallable:
719
+ self, path: str, name: str | None = None,
720
+ ) -> Callable[[WebSocketEndpointCallable], WebSocketEndpointCallable]:
721
+ def decorator(func: WebSocketEndpointCallable) -> WebSocketEndpointCallable:
758
722
  self.router.add_api_websocket_route(path, func, name=name)
759
723
  return func
760
724
 
@@ -767,17 +731,17 @@ class StarMallow(Starlette):
767
731
 
768
732
  def middleware(
769
733
  self, middleware_type: str,
770
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
771
- def decorator(func: DecoratedCallable) -> DecoratedCallable:
734
+ ) -> Callable[[DispatchFunction], DispatchFunction]:
735
+ def decorator(func: DispatchFunction) -> DispatchFunction:
772
736
  self.add_middleware(BaseHTTPMiddleware, dispatch=func)
773
737
  return func
774
738
 
775
739
  return decorator
776
740
 
777
741
  def exception_handler(
778
- self, exc_class_or_status_code: Union[int, Type[Exception]],
779
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
780
- def decorator(func: DecoratedCallable) -> DecoratedCallable:
742
+ self, exc_class_or_status_code: int | type[Exception],
743
+ ) -> Callable[[ExceptionHandler], ExceptionHandler]:
744
+ def decorator(func: ExceptionHandler) -> ExceptionHandler:
781
745
  self.add_exception_handler(exc_class_or_status_code, func)
782
746
  return func
783
747