prefect-client 2.19.4__py3-none-any.whl → 3.0.0rc2__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.
Files changed (242) hide show
  1. prefect/__init__.py +8 -56
  2. prefect/_internal/compatibility/deprecated.py +6 -115
  3. prefect/_internal/compatibility/experimental.py +4 -79
  4. prefect/_internal/concurrency/api.py +0 -34
  5. prefect/_internal/concurrency/calls.py +0 -6
  6. prefect/_internal/concurrency/cancellation.py +0 -3
  7. prefect/_internal/concurrency/event_loop.py +0 -20
  8. prefect/_internal/concurrency/inspection.py +3 -3
  9. prefect/_internal/concurrency/threads.py +35 -0
  10. prefect/_internal/concurrency/waiters.py +0 -28
  11. prefect/_internal/pydantic/__init__.py +0 -45
  12. prefect/_internal/pydantic/v1_schema.py +21 -22
  13. prefect/_internal/pydantic/v2_schema.py +0 -2
  14. prefect/_internal/pydantic/v2_validated_func.py +18 -23
  15. prefect/_internal/schemas/bases.py +44 -177
  16. prefect/_internal/schemas/fields.py +1 -43
  17. prefect/_internal/schemas/validators.py +60 -158
  18. prefect/artifacts.py +161 -14
  19. prefect/automations.py +39 -4
  20. prefect/blocks/abstract.py +1 -1
  21. prefect/blocks/core.py +268 -148
  22. prefect/blocks/fields.py +2 -57
  23. prefect/blocks/kubernetes.py +8 -12
  24. prefect/blocks/notifications.py +40 -20
  25. prefect/blocks/redis.py +168 -0
  26. prefect/blocks/system.py +22 -11
  27. prefect/blocks/webhook.py +2 -9
  28. prefect/client/base.py +4 -4
  29. prefect/client/cloud.py +8 -13
  30. prefect/client/orchestration.py +362 -340
  31. prefect/client/schemas/actions.py +92 -86
  32. prefect/client/schemas/filters.py +20 -40
  33. prefect/client/schemas/objects.py +158 -152
  34. prefect/client/schemas/responses.py +16 -24
  35. prefect/client/schemas/schedules.py +47 -35
  36. prefect/client/subscriptions.py +2 -2
  37. prefect/client/utilities.py +5 -2
  38. prefect/concurrency/asyncio.py +4 -2
  39. prefect/concurrency/events.py +1 -1
  40. prefect/concurrency/services.py +7 -4
  41. prefect/context.py +195 -27
  42. prefect/deployments/__init__.py +5 -6
  43. prefect/deployments/base.py +7 -5
  44. prefect/deployments/flow_runs.py +185 -0
  45. prefect/deployments/runner.py +50 -45
  46. prefect/deployments/schedules.py +28 -23
  47. prefect/deployments/steps/__init__.py +0 -1
  48. prefect/deployments/steps/core.py +1 -0
  49. prefect/deployments/steps/pull.py +7 -21
  50. prefect/engine.py +12 -2422
  51. prefect/events/actions.py +17 -23
  52. prefect/events/cli/automations.py +19 -6
  53. prefect/events/clients.py +14 -37
  54. prefect/events/filters.py +14 -18
  55. prefect/events/related.py +2 -2
  56. prefect/events/schemas/__init__.py +0 -5
  57. prefect/events/schemas/automations.py +55 -46
  58. prefect/events/schemas/deployment_triggers.py +7 -197
  59. prefect/events/schemas/events.py +36 -65
  60. prefect/events/schemas/labelling.py +10 -14
  61. prefect/events/utilities.py +2 -3
  62. prefect/events/worker.py +2 -3
  63. prefect/filesystems.py +6 -517
  64. prefect/{new_flow_engine.py → flow_engine.py} +315 -74
  65. prefect/flow_runs.py +379 -7
  66. prefect/flows.py +248 -165
  67. prefect/futures.py +187 -345
  68. prefect/infrastructure/__init__.py +0 -27
  69. prefect/infrastructure/provisioners/__init__.py +5 -3
  70. prefect/infrastructure/provisioners/cloud_run.py +11 -6
  71. prefect/infrastructure/provisioners/container_instance.py +11 -7
  72. prefect/infrastructure/provisioners/ecs.py +6 -4
  73. prefect/infrastructure/provisioners/modal.py +8 -5
  74. prefect/input/actions.py +2 -4
  75. prefect/input/run_input.py +9 -9
  76. prefect/logging/formatters.py +0 -2
  77. prefect/logging/handlers.py +3 -11
  78. prefect/logging/loggers.py +2 -2
  79. prefect/manifests.py +2 -1
  80. prefect/records/__init__.py +1 -0
  81. prefect/records/cache_policies.py +179 -0
  82. prefect/records/result_store.py +42 -0
  83. prefect/records/store.py +9 -0
  84. prefect/results.py +43 -39
  85. prefect/runner/runner.py +9 -9
  86. prefect/runner/server.py +6 -10
  87. prefect/runner/storage.py +3 -8
  88. prefect/runner/submit.py +2 -2
  89. prefect/runner/utils.py +2 -2
  90. prefect/serializers.py +24 -35
  91. prefect/server/api/collections_data/views/aggregate-worker-metadata.json +5 -14
  92. prefect/settings.py +76 -136
  93. prefect/states.py +22 -50
  94. prefect/task_engine.py +666 -56
  95. prefect/task_runners.py +272 -300
  96. prefect/task_runs.py +203 -0
  97. prefect/{task_server.py → task_worker.py} +89 -60
  98. prefect/tasks.py +358 -341
  99. prefect/transactions.py +224 -0
  100. prefect/types/__init__.py +61 -82
  101. prefect/utilities/asyncutils.py +195 -136
  102. prefect/utilities/callables.py +121 -41
  103. prefect/utilities/collections.py +23 -38
  104. prefect/utilities/dispatch.py +11 -3
  105. prefect/utilities/dockerutils.py +4 -0
  106. prefect/utilities/engine.py +140 -20
  107. prefect/utilities/importtools.py +26 -27
  108. prefect/utilities/pydantic.py +128 -38
  109. prefect/utilities/schema_tools/hydration.py +5 -1
  110. prefect/utilities/templating.py +12 -2
  111. prefect/variables.py +84 -62
  112. prefect/workers/__init__.py +0 -1
  113. prefect/workers/base.py +26 -18
  114. prefect/workers/process.py +3 -8
  115. prefect/workers/server.py +2 -2
  116. {prefect_client-2.19.4.dist-info → prefect_client-3.0.0rc2.dist-info}/METADATA +23 -21
  117. prefect_client-3.0.0rc2.dist-info/RECORD +179 -0
  118. prefect/_internal/pydantic/_base_model.py +0 -51
  119. prefect/_internal/pydantic/_compat.py +0 -82
  120. prefect/_internal/pydantic/_flags.py +0 -20
  121. prefect/_internal/pydantic/_types.py +0 -8
  122. prefect/_internal/pydantic/utilities/__init__.py +0 -0
  123. prefect/_internal/pydantic/utilities/config_dict.py +0 -72
  124. prefect/_internal/pydantic/utilities/field_validator.py +0 -150
  125. prefect/_internal/pydantic/utilities/model_construct.py +0 -56
  126. prefect/_internal/pydantic/utilities/model_copy.py +0 -55
  127. prefect/_internal/pydantic/utilities/model_dump.py +0 -136
  128. prefect/_internal/pydantic/utilities/model_dump_json.py +0 -112
  129. prefect/_internal/pydantic/utilities/model_fields.py +0 -50
  130. prefect/_internal/pydantic/utilities/model_fields_set.py +0 -29
  131. prefect/_internal/pydantic/utilities/model_json_schema.py +0 -82
  132. prefect/_internal/pydantic/utilities/model_rebuild.py +0 -80
  133. prefect/_internal/pydantic/utilities/model_validate.py +0 -75
  134. prefect/_internal/pydantic/utilities/model_validate_json.py +0 -68
  135. prefect/_internal/pydantic/utilities/model_validator.py +0 -87
  136. prefect/_internal/pydantic/utilities/type_adapter.py +0 -71
  137. prefect/_vendor/__init__.py +0 -0
  138. prefect/_vendor/fastapi/__init__.py +0 -25
  139. prefect/_vendor/fastapi/applications.py +0 -946
  140. prefect/_vendor/fastapi/background.py +0 -3
  141. prefect/_vendor/fastapi/concurrency.py +0 -44
  142. prefect/_vendor/fastapi/datastructures.py +0 -58
  143. prefect/_vendor/fastapi/dependencies/__init__.py +0 -0
  144. prefect/_vendor/fastapi/dependencies/models.py +0 -64
  145. prefect/_vendor/fastapi/dependencies/utils.py +0 -877
  146. prefect/_vendor/fastapi/encoders.py +0 -177
  147. prefect/_vendor/fastapi/exception_handlers.py +0 -40
  148. prefect/_vendor/fastapi/exceptions.py +0 -46
  149. prefect/_vendor/fastapi/logger.py +0 -3
  150. prefect/_vendor/fastapi/middleware/__init__.py +0 -1
  151. prefect/_vendor/fastapi/middleware/asyncexitstack.py +0 -25
  152. prefect/_vendor/fastapi/middleware/cors.py +0 -3
  153. prefect/_vendor/fastapi/middleware/gzip.py +0 -3
  154. prefect/_vendor/fastapi/middleware/httpsredirect.py +0 -3
  155. prefect/_vendor/fastapi/middleware/trustedhost.py +0 -3
  156. prefect/_vendor/fastapi/middleware/wsgi.py +0 -3
  157. prefect/_vendor/fastapi/openapi/__init__.py +0 -0
  158. prefect/_vendor/fastapi/openapi/constants.py +0 -2
  159. prefect/_vendor/fastapi/openapi/docs.py +0 -203
  160. prefect/_vendor/fastapi/openapi/models.py +0 -480
  161. prefect/_vendor/fastapi/openapi/utils.py +0 -485
  162. prefect/_vendor/fastapi/param_functions.py +0 -340
  163. prefect/_vendor/fastapi/params.py +0 -453
  164. prefect/_vendor/fastapi/requests.py +0 -4
  165. prefect/_vendor/fastapi/responses.py +0 -40
  166. prefect/_vendor/fastapi/routing.py +0 -1331
  167. prefect/_vendor/fastapi/security/__init__.py +0 -15
  168. prefect/_vendor/fastapi/security/api_key.py +0 -98
  169. prefect/_vendor/fastapi/security/base.py +0 -6
  170. prefect/_vendor/fastapi/security/http.py +0 -172
  171. prefect/_vendor/fastapi/security/oauth2.py +0 -227
  172. prefect/_vendor/fastapi/security/open_id_connect_url.py +0 -34
  173. prefect/_vendor/fastapi/security/utils.py +0 -10
  174. prefect/_vendor/fastapi/staticfiles.py +0 -1
  175. prefect/_vendor/fastapi/templating.py +0 -3
  176. prefect/_vendor/fastapi/testclient.py +0 -1
  177. prefect/_vendor/fastapi/types.py +0 -3
  178. prefect/_vendor/fastapi/utils.py +0 -235
  179. prefect/_vendor/fastapi/websockets.py +0 -7
  180. prefect/_vendor/starlette/__init__.py +0 -1
  181. prefect/_vendor/starlette/_compat.py +0 -28
  182. prefect/_vendor/starlette/_exception_handler.py +0 -80
  183. prefect/_vendor/starlette/_utils.py +0 -88
  184. prefect/_vendor/starlette/applications.py +0 -261
  185. prefect/_vendor/starlette/authentication.py +0 -159
  186. prefect/_vendor/starlette/background.py +0 -43
  187. prefect/_vendor/starlette/concurrency.py +0 -59
  188. prefect/_vendor/starlette/config.py +0 -151
  189. prefect/_vendor/starlette/convertors.py +0 -87
  190. prefect/_vendor/starlette/datastructures.py +0 -707
  191. prefect/_vendor/starlette/endpoints.py +0 -130
  192. prefect/_vendor/starlette/exceptions.py +0 -60
  193. prefect/_vendor/starlette/formparsers.py +0 -276
  194. prefect/_vendor/starlette/middleware/__init__.py +0 -17
  195. prefect/_vendor/starlette/middleware/authentication.py +0 -52
  196. prefect/_vendor/starlette/middleware/base.py +0 -220
  197. prefect/_vendor/starlette/middleware/cors.py +0 -176
  198. prefect/_vendor/starlette/middleware/errors.py +0 -265
  199. prefect/_vendor/starlette/middleware/exceptions.py +0 -74
  200. prefect/_vendor/starlette/middleware/gzip.py +0 -113
  201. prefect/_vendor/starlette/middleware/httpsredirect.py +0 -19
  202. prefect/_vendor/starlette/middleware/sessions.py +0 -82
  203. prefect/_vendor/starlette/middleware/trustedhost.py +0 -64
  204. prefect/_vendor/starlette/middleware/wsgi.py +0 -147
  205. prefect/_vendor/starlette/requests.py +0 -328
  206. prefect/_vendor/starlette/responses.py +0 -347
  207. prefect/_vendor/starlette/routing.py +0 -933
  208. prefect/_vendor/starlette/schemas.py +0 -154
  209. prefect/_vendor/starlette/staticfiles.py +0 -248
  210. prefect/_vendor/starlette/status.py +0 -199
  211. prefect/_vendor/starlette/templating.py +0 -231
  212. prefect/_vendor/starlette/testclient.py +0 -804
  213. prefect/_vendor/starlette/types.py +0 -30
  214. prefect/_vendor/starlette/websockets.py +0 -193
  215. prefect/agent.py +0 -698
  216. prefect/deployments/deployments.py +0 -1042
  217. prefect/deprecated/__init__.py +0 -0
  218. prefect/deprecated/data_documents.py +0 -350
  219. prefect/deprecated/packaging/__init__.py +0 -12
  220. prefect/deprecated/packaging/base.py +0 -96
  221. prefect/deprecated/packaging/docker.py +0 -146
  222. prefect/deprecated/packaging/file.py +0 -92
  223. prefect/deprecated/packaging/orion.py +0 -80
  224. prefect/deprecated/packaging/serializers.py +0 -171
  225. prefect/events/instrument.py +0 -135
  226. prefect/infrastructure/base.py +0 -323
  227. prefect/infrastructure/container.py +0 -818
  228. prefect/infrastructure/kubernetes.py +0 -920
  229. prefect/infrastructure/process.py +0 -289
  230. prefect/new_task_engine.py +0 -423
  231. prefect/pydantic/__init__.py +0 -76
  232. prefect/pydantic/main.py +0 -39
  233. prefect/software/__init__.py +0 -2
  234. prefect/software/base.py +0 -50
  235. prefect/software/conda.py +0 -199
  236. prefect/software/pip.py +0 -122
  237. prefect/software/python.py +0 -52
  238. prefect/workers/block.py +0 -218
  239. prefect_client-2.19.4.dist-info/RECORD +0 -292
  240. {prefect_client-2.19.4.dist-info → prefect_client-3.0.0rc2.dist-info}/LICENSE +0 -0
  241. {prefect_client-2.19.4.dist-info → prefect_client-3.0.0rc2.dist-info}/WHEEL +0 -0
  242. {prefect_client-2.19.4.dist-info → prefect_client-3.0.0rc2.dist-info}/top_level.txt +0 -0
@@ -1,1331 +0,0 @@
1
- import asyncio
2
- import dataclasses
3
- import email.message
4
- import inspect
5
- import json
6
- from contextlib import AsyncExitStack
7
- from enum import Enum, IntEnum
8
- from typing import (
9
- Any,
10
- Callable,
11
- Coroutine,
12
- Dict,
13
- List,
14
- Optional,
15
- Sequence,
16
- Set,
17
- Tuple,
18
- Type,
19
- Union,
20
- )
21
-
22
- from prefect._vendor.fastapi import params
23
- from prefect._vendor.fastapi.datastructures import Default, DefaultPlaceholder
24
- from prefect._vendor.fastapi.dependencies.models import Dependant
25
- from prefect._vendor.fastapi.dependencies.utils import (
26
- get_body_field,
27
- get_dependant,
28
- get_parameterless_sub_dependant,
29
- get_typed_return_annotation,
30
- solve_dependencies,
31
- )
32
- from prefect._vendor.fastapi.encoders import DictIntStrAny, SetIntStr, jsonable_encoder
33
- from prefect._vendor.fastapi.exceptions import (
34
- FastAPIError,
35
- RequestValidationError,
36
- WebSocketRequestValidationError,
37
- )
38
- from prefect._vendor.fastapi.types import DecoratedCallable
39
- from prefect._vendor.fastapi.utils import (
40
- create_cloned_field,
41
- create_response_field,
42
- generate_unique_id,
43
- get_value_or_default,
44
- is_body_allowed_for_status_code,
45
- )
46
-
47
- from prefect._internal.pydantic import HAS_PYDANTIC_V2
48
-
49
- if HAS_PYDANTIC_V2:
50
- from pydantic.v1 import BaseModel
51
- from pydantic.v1.error_wrappers import ErrorWrapper, ValidationError
52
- from pydantic.v1.fields import ModelField, Undefined
53
- from pydantic.v1.utils import lenient_issubclass
54
- else:
55
- from pydantic import BaseModel
56
- from pydantic.error_wrappers import ErrorWrapper, ValidationError
57
- from pydantic.fields import ModelField, Undefined
58
- from pydantic.utils import lenient_issubclass
59
-
60
- from prefect._vendor.starlette import routing
61
- from prefect._vendor.starlette.concurrency import run_in_threadpool
62
- from prefect._vendor.starlette.exceptions import HTTPException
63
- from prefect._vendor.starlette.requests import Request
64
- from prefect._vendor.starlette.responses import JSONResponse, Response
65
- from prefect._vendor.starlette.routing import (
66
- BaseRoute,
67
- Match,
68
- compile_path,
69
- get_name,
70
- request_response,
71
- websocket_session,
72
- )
73
- from prefect._vendor.starlette.routing import Mount as Mount # noqa
74
- from prefect._vendor.starlette.types import ASGIApp, Lifespan, Scope
75
- from prefect._vendor.starlette.websockets import WebSocket
76
-
77
-
78
- def _prepare_response_content(
79
- res: Any,
80
- *,
81
- exclude_unset: bool,
82
- exclude_defaults: bool = False,
83
- exclude_none: bool = False,
84
- ) -> Any:
85
- if isinstance(res, BaseModel):
86
- read_with_orm_mode = getattr(res.__config__, "read_with_orm_mode", None)
87
- if read_with_orm_mode:
88
- # Let from_orm extract the data from this model instead of converting
89
- # it now to a dict.
90
- # Otherwise there's no way to extract lazy data that requires attribute
91
- # access instead of dict iteration, e.g. lazy relationships.
92
- return res
93
- return res.dict(
94
- by_alias=True,
95
- exclude_unset=exclude_unset,
96
- exclude_defaults=exclude_defaults,
97
- exclude_none=exclude_none,
98
- )
99
- elif isinstance(res, list):
100
- return [
101
- _prepare_response_content(
102
- item,
103
- exclude_unset=exclude_unset,
104
- exclude_defaults=exclude_defaults,
105
- exclude_none=exclude_none,
106
- )
107
- for item in res
108
- ]
109
- elif isinstance(res, dict):
110
- return {
111
- k: _prepare_response_content(
112
- v,
113
- exclude_unset=exclude_unset,
114
- exclude_defaults=exclude_defaults,
115
- exclude_none=exclude_none,
116
- )
117
- for k, v in res.items()
118
- }
119
- elif dataclasses.is_dataclass(res):
120
- return dataclasses.asdict(res)
121
- return res
122
-
123
-
124
- async def serialize_response(
125
- *,
126
- field: Optional[ModelField] = None,
127
- response_content: Any,
128
- include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
129
- exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
130
- by_alias: bool = True,
131
- exclude_unset: bool = False,
132
- exclude_defaults: bool = False,
133
- exclude_none: bool = False,
134
- is_coroutine: bool = True,
135
- ) -> Any:
136
- if field:
137
- errors = []
138
- response_content = _prepare_response_content(
139
- response_content,
140
- exclude_unset=exclude_unset,
141
- exclude_defaults=exclude_defaults,
142
- exclude_none=exclude_none,
143
- )
144
- if is_coroutine:
145
- value, errors_ = field.validate(response_content, {}, loc=("response",))
146
- else:
147
- value, errors_ = await run_in_threadpool(
148
- field.validate, response_content, {}, loc=("response",)
149
- )
150
- if isinstance(errors_, ErrorWrapper):
151
- errors.append(errors_)
152
- elif isinstance(errors_, list):
153
- errors.extend(errors_)
154
- if errors:
155
- raise ValidationError(errors, field.type_)
156
- return jsonable_encoder(
157
- value,
158
- include=include,
159
- exclude=exclude,
160
- by_alias=by_alias,
161
- exclude_unset=exclude_unset,
162
- exclude_defaults=exclude_defaults,
163
- exclude_none=exclude_none,
164
- )
165
- else:
166
- return jsonable_encoder(response_content)
167
-
168
-
169
- async def run_endpoint_function(
170
- *, dependant: Dependant, values: Dict[str, Any], is_coroutine: bool
171
- ) -> Any:
172
- # Only called by get_request_handler. Has been split into its own function to
173
- # facilitate profiling endpoints, since inner functions are harder to profile.
174
- assert dependant.call is not None, "dependant.call must be a function"
175
-
176
- if is_coroutine:
177
- return await dependant.call(**values)
178
- else:
179
- return await run_in_threadpool(dependant.call, **values)
180
-
181
-
182
- def get_request_handler(
183
- dependant: Dependant,
184
- body_field: Optional[ModelField] = None,
185
- status_code: Optional[int] = None,
186
- response_class: Union[Type[Response], DefaultPlaceholder] = Default(JSONResponse),
187
- response_field: Optional[ModelField] = None,
188
- response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
189
- response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
190
- response_model_by_alias: bool = True,
191
- response_model_exclude_unset: bool = False,
192
- response_model_exclude_defaults: bool = False,
193
- response_model_exclude_none: bool = False,
194
- dependency_overrides_provider: Optional[Any] = None,
195
- ) -> Callable[[Request], Coroutine[Any, Any, Response]]:
196
- assert dependant.call is not None, "dependant.call must be a function"
197
- is_coroutine = asyncio.iscoroutinefunction(dependant.call)
198
- is_body_form = body_field and isinstance(body_field.field_info, params.Form)
199
- if isinstance(response_class, DefaultPlaceholder):
200
- actual_response_class: Type[Response] = response_class.value
201
- else:
202
- actual_response_class = response_class
203
-
204
- async def app(request: Request) -> Response:
205
- try:
206
- body: Any = None
207
- if body_field:
208
- if is_body_form:
209
- body = await request.form()
210
- stack = request.scope.get("fastapi_astack")
211
- assert isinstance(stack, AsyncExitStack)
212
- stack.push_async_callback(body.close)
213
- else:
214
- body_bytes = await request.body()
215
- if body_bytes:
216
- json_body: Any = Undefined
217
- content_type_value = request.headers.get("content-type")
218
- if not content_type_value:
219
- json_body = await request.json()
220
- else:
221
- message = email.message.Message()
222
- message["content-type"] = content_type_value
223
- if message.get_content_maintype() == "application":
224
- subtype = message.get_content_subtype()
225
- if subtype == "json" or subtype.endswith("+json"):
226
- json_body = await request.json()
227
- if json_body != Undefined:
228
- body = json_body
229
- else:
230
- body = body_bytes
231
- except json.JSONDecodeError as e:
232
- raise RequestValidationError(
233
- [ErrorWrapper(e, ("body", e.pos))], body=e.doc
234
- ) from e
235
- except HTTPException:
236
- raise
237
- except Exception as e:
238
- raise HTTPException(
239
- status_code=400, detail="There was an error parsing the body"
240
- ) from e
241
- solved_result = await solve_dependencies(
242
- request=request,
243
- dependant=dependant,
244
- body=body,
245
- dependency_overrides_provider=dependency_overrides_provider,
246
- )
247
- values, errors, background_tasks, sub_response, _ = solved_result
248
- if errors:
249
- raise RequestValidationError(errors, body=body)
250
- else:
251
- raw_response = await run_endpoint_function(
252
- dependant=dependant, values=values, is_coroutine=is_coroutine
253
- )
254
-
255
- if isinstance(raw_response, Response):
256
- if raw_response.background is None:
257
- raw_response.background = background_tasks
258
- return raw_response
259
- response_args: Dict[str, Any] = {"background": background_tasks}
260
- # If status_code was set, use it, otherwise use the default from the
261
- # response class, in the case of redirect it's 307
262
- current_status_code = (
263
- status_code if status_code else sub_response.status_code
264
- )
265
- if current_status_code is not None:
266
- response_args["status_code"] = current_status_code
267
- if sub_response.status_code:
268
- response_args["status_code"] = sub_response.status_code
269
- content = await serialize_response(
270
- field=response_field,
271
- response_content=raw_response,
272
- include=response_model_include,
273
- exclude=response_model_exclude,
274
- by_alias=response_model_by_alias,
275
- exclude_unset=response_model_exclude_unset,
276
- exclude_defaults=response_model_exclude_defaults,
277
- exclude_none=response_model_exclude_none,
278
- is_coroutine=is_coroutine,
279
- )
280
- response = actual_response_class(content, **response_args)
281
- if not is_body_allowed_for_status_code(response.status_code):
282
- response.body = b""
283
- response.headers.raw.extend(sub_response.headers.raw)
284
- return response
285
-
286
- return app
287
-
288
-
289
- def get_websocket_app(
290
- dependant: Dependant, dependency_overrides_provider: Optional[Any] = None
291
- ) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]:
292
- async def app(websocket: WebSocket) -> None:
293
- solved_result = await solve_dependencies(
294
- request=websocket,
295
- dependant=dependant,
296
- dependency_overrides_provider=dependency_overrides_provider,
297
- )
298
- values, errors, _, _2, _3 = solved_result
299
- if errors:
300
- raise WebSocketRequestValidationError(errors)
301
- assert dependant.call is not None, "dependant.call must be a function"
302
- await dependant.call(**values)
303
-
304
- return app
305
-
306
-
307
- class APIWebSocketRoute(routing.WebSocketRoute):
308
- def __init__(
309
- self,
310
- path: str,
311
- endpoint: Callable[..., Any],
312
- *,
313
- name: Optional[str] = None,
314
- dependencies: Optional[Sequence[params.Depends]] = None,
315
- dependency_overrides_provider: Optional[Any] = None,
316
- ) -> None:
317
- self.path = path
318
- self.endpoint = endpoint
319
- self.name = get_name(endpoint) if name is None else name
320
- self.dependencies = list(dependencies or [])
321
- self.path_regex, self.path_format, self.param_convertors = compile_path(path)
322
- self.dependant = get_dependant(path=self.path_format, call=self.endpoint)
323
- for depends in self.dependencies[::-1]:
324
- self.dependant.dependencies.insert(
325
- 0,
326
- get_parameterless_sub_dependant(depends=depends, path=self.path_format),
327
- )
328
-
329
- self.app = websocket_session(
330
- get_websocket_app(
331
- dependant=self.dependant,
332
- dependency_overrides_provider=dependency_overrides_provider,
333
- )
334
- )
335
-
336
- def matches(self, scope: Scope) -> Tuple[Match, Scope]:
337
- match, child_scope = super().matches(scope)
338
- if match != Match.NONE:
339
- child_scope["route"] = self
340
- return match, child_scope
341
-
342
-
343
- class APIRoute(routing.Route):
344
- def __init__(
345
- self,
346
- path: str,
347
- endpoint: Callable[..., Any],
348
- *,
349
- response_model: Any = Default(None),
350
- status_code: Optional[int] = None,
351
- tags: Optional[List[Union[str, Enum]]] = None,
352
- dependencies: Optional[Sequence[params.Depends]] = None,
353
- summary: Optional[str] = None,
354
- description: Optional[str] = None,
355
- response_description: str = "Successful Response",
356
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
357
- deprecated: Optional[bool] = None,
358
- name: Optional[str] = None,
359
- methods: Optional[Union[Set[str], List[str]]] = None,
360
- operation_id: Optional[str] = None,
361
- response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
362
- response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
363
- response_model_by_alias: bool = True,
364
- response_model_exclude_unset: bool = False,
365
- response_model_exclude_defaults: bool = False,
366
- response_model_exclude_none: bool = False,
367
- include_in_schema: bool = True,
368
- response_class: Union[Type[Response], DefaultPlaceholder] = Default(
369
- JSONResponse
370
- ),
371
- dependency_overrides_provider: Optional[Any] = None,
372
- callbacks: Optional[List[BaseRoute]] = None,
373
- openapi_extra: Optional[Dict[str, Any]] = None,
374
- generate_unique_id_function: Union[
375
- Callable[["APIRoute"], str], DefaultPlaceholder
376
- ] = Default(generate_unique_id),
377
- ) -> None:
378
- self.path = path
379
- self.endpoint = endpoint
380
- if isinstance(response_model, DefaultPlaceholder):
381
- return_annotation = get_typed_return_annotation(endpoint)
382
- if lenient_issubclass(return_annotation, Response):
383
- response_model = None
384
- else:
385
- response_model = return_annotation
386
- self.response_model = response_model
387
- self.summary = summary
388
- self.response_description = response_description
389
- self.deprecated = deprecated
390
- self.operation_id = operation_id
391
- self.response_model_include = response_model_include
392
- self.response_model_exclude = response_model_exclude
393
- self.response_model_by_alias = response_model_by_alias
394
- self.response_model_exclude_unset = response_model_exclude_unset
395
- self.response_model_exclude_defaults = response_model_exclude_defaults
396
- self.response_model_exclude_none = response_model_exclude_none
397
- self.include_in_schema = include_in_schema
398
- self.response_class = response_class
399
- self.dependency_overrides_provider = dependency_overrides_provider
400
- self.callbacks = callbacks
401
- self.openapi_extra = openapi_extra
402
- self.generate_unique_id_function = generate_unique_id_function
403
- self.tags = tags or []
404
- self.responses = responses or {}
405
- self.name = get_name(endpoint) if name is None else name
406
- self.path_regex, self.path_format, self.param_convertors = compile_path(path)
407
- if methods is None:
408
- methods = ["GET"]
409
- self.methods: Set[str] = {method.upper() for method in methods}
410
- if isinstance(generate_unique_id_function, DefaultPlaceholder):
411
- current_generate_unique_id: Callable[
412
- ["APIRoute"], str
413
- ] = generate_unique_id_function.value
414
- else:
415
- current_generate_unique_id = generate_unique_id_function
416
- self.unique_id = self.operation_id or current_generate_unique_id(self)
417
- # normalize enums e.g. http.HTTPStatus
418
- if isinstance(status_code, IntEnum):
419
- status_code = int(status_code)
420
- self.status_code = status_code
421
- if self.response_model:
422
- assert is_body_allowed_for_status_code(
423
- status_code
424
- ), f"Status code {status_code} must not have a response body"
425
- response_name = "Response_" + self.unique_id
426
- self.response_field = create_response_field(
427
- name=response_name, type_=self.response_model
428
- )
429
- # Create a clone of the field, so that a Pydantic submodel is not returned
430
- # as is just because it's an instance of a subclass of a more limited class
431
- # e.g. UserInDB (containing hashed_password) could be a subclass of User
432
- # that doesn't have the hashed_password. But because it's a subclass, it
433
- # would pass the validation and be returned as is.
434
- # By being a new field, no inheritance will be passed as is. A new model
435
- # will be always created.
436
- self.secure_cloned_response_field: Optional[
437
- ModelField
438
- ] = create_cloned_field(self.response_field)
439
- else:
440
- self.response_field = None # type: ignore
441
- self.secure_cloned_response_field = None
442
- self.dependencies = list(dependencies or [])
443
- self.description = description or inspect.cleandoc(self.endpoint.__doc__ or "")
444
- # if a "form feed" character (page break) is found in the description text,
445
- # truncate description text to the content preceding the first "form feed"
446
- self.description = self.description.split("\f")[0].strip()
447
- response_fields = {}
448
- for additional_status_code, response in self.responses.items():
449
- assert isinstance(response, dict), "An additional response must be a dict"
450
- model = response.get("model")
451
- if model:
452
- assert is_body_allowed_for_status_code(
453
- additional_status_code
454
- ), f"Status code {additional_status_code} must not have a response body"
455
- response_name = f"Response_{additional_status_code}_{self.unique_id}"
456
- response_field = create_response_field(name=response_name, type_=model)
457
- response_fields[additional_status_code] = response_field
458
- if response_fields:
459
- self.response_fields: Dict[Union[int, str], ModelField] = response_fields
460
- else:
461
- self.response_fields = {}
462
-
463
- assert callable(endpoint), "An endpoint must be a callable"
464
- self.dependant = get_dependant(path=self.path_format, call=self.endpoint)
465
- for depends in self.dependencies[::-1]:
466
- self.dependant.dependencies.insert(
467
- 0,
468
- get_parameterless_sub_dependant(depends=depends, path=self.path_format),
469
- )
470
- self.body_field = get_body_field(dependant=self.dependant, name=self.unique_id)
471
- self.app = request_response(self.get_route_handler())
472
-
473
- def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]:
474
- return get_request_handler(
475
- dependant=self.dependant,
476
- body_field=self.body_field,
477
- status_code=self.status_code,
478
- response_class=self.response_class,
479
- response_field=self.secure_cloned_response_field,
480
- response_model_include=self.response_model_include,
481
- response_model_exclude=self.response_model_exclude,
482
- response_model_by_alias=self.response_model_by_alias,
483
- response_model_exclude_unset=self.response_model_exclude_unset,
484
- response_model_exclude_defaults=self.response_model_exclude_defaults,
485
- response_model_exclude_none=self.response_model_exclude_none,
486
- dependency_overrides_provider=self.dependency_overrides_provider,
487
- )
488
-
489
- def matches(self, scope: Scope) -> Tuple[Match, Scope]:
490
- match, child_scope = super().matches(scope)
491
- if match != Match.NONE:
492
- child_scope["route"] = self
493
- return match, child_scope
494
-
495
-
496
- class APIRouter(routing.Router):
497
- def __init__(
498
- self,
499
- *,
500
- prefix: str = "",
501
- tags: Optional[List[Union[str, Enum]]] = None,
502
- dependencies: Optional[Sequence[params.Depends]] = None,
503
- default_response_class: Type[Response] = Default(JSONResponse),
504
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
505
- callbacks: Optional[List[BaseRoute]] = None,
506
- routes: Optional[List[routing.BaseRoute]] = None,
507
- redirect_slashes: bool = True,
508
- default: Optional[ASGIApp] = None,
509
- dependency_overrides_provider: Optional[Any] = None,
510
- route_class: Type[APIRoute] = APIRoute,
511
- on_startup: Optional[Sequence[Callable[[], Any]]] = None,
512
- on_shutdown: Optional[Sequence[Callable[[], Any]]] = None,
513
- # the generic to Lifespan[AppType] is the type of the top level application
514
- # which the router cannot know statically, so we use typing.Any
515
- lifespan: Optional[Lifespan[Any]] = None,
516
- deprecated: Optional[bool] = None,
517
- include_in_schema: bool = True,
518
- generate_unique_id_function: Callable[[APIRoute], str] = Default(
519
- generate_unique_id
520
- ),
521
- ) -> None:
522
- super().__init__(
523
- routes=routes,
524
- redirect_slashes=redirect_slashes,
525
- default=default,
526
- on_startup=on_startup,
527
- on_shutdown=on_shutdown,
528
- lifespan=lifespan,
529
- )
530
- if prefix:
531
- assert prefix.startswith("/"), "A path prefix must start with '/'"
532
- assert not prefix.endswith(
533
- "/"
534
- ), "A path prefix must not end with '/', as the routes will start with '/'"
535
- self.prefix = prefix
536
- self.tags: List[Union[str, Enum]] = tags or []
537
- self.dependencies = list(dependencies or [])
538
- self.deprecated = deprecated
539
- self.include_in_schema = include_in_schema
540
- self.responses = responses or {}
541
- self.callbacks = callbacks or []
542
- self.dependency_overrides_provider = dependency_overrides_provider
543
- self.route_class = route_class
544
- self.default_response_class = default_response_class
545
- self.generate_unique_id_function = generate_unique_id_function
546
-
547
- def route(
548
- self,
549
- path: str,
550
- methods: Optional[List[str]] = None,
551
- name: Optional[str] = None,
552
- include_in_schema: bool = True,
553
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
554
- def decorator(func: DecoratedCallable) -> DecoratedCallable:
555
- self.add_route(
556
- path,
557
- func,
558
- methods=methods,
559
- name=name,
560
- include_in_schema=include_in_schema,
561
- )
562
- return func
563
-
564
- return decorator
565
-
566
- def add_api_route(
567
- self,
568
- path: str,
569
- endpoint: Callable[..., Any],
570
- *,
571
- response_model: Any = Default(None),
572
- status_code: Optional[int] = None,
573
- tags: Optional[List[Union[str, Enum]]] = None,
574
- dependencies: Optional[Sequence[params.Depends]] = None,
575
- summary: Optional[str] = None,
576
- description: Optional[str] = None,
577
- response_description: str = "Successful Response",
578
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
579
- deprecated: Optional[bool] = None,
580
- methods: Optional[Union[Set[str], List[str]]] = None,
581
- operation_id: Optional[str] = None,
582
- response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
583
- response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
584
- response_model_by_alias: bool = True,
585
- response_model_exclude_unset: bool = False,
586
- response_model_exclude_defaults: bool = False,
587
- response_model_exclude_none: bool = False,
588
- include_in_schema: bool = True,
589
- response_class: Union[Type[Response], DefaultPlaceholder] = Default(
590
- JSONResponse
591
- ),
592
- name: Optional[str] = None,
593
- route_class_override: Optional[Type[APIRoute]] = None,
594
- callbacks: Optional[List[BaseRoute]] = None,
595
- openapi_extra: Optional[Dict[str, Any]] = None,
596
- generate_unique_id_function: Union[
597
- Callable[[APIRoute], str], DefaultPlaceholder
598
- ] = Default(generate_unique_id),
599
- ) -> None:
600
- route_class = route_class_override or self.route_class
601
- responses = responses or {}
602
- combined_responses = {**self.responses, **responses}
603
- current_response_class = get_value_or_default(
604
- response_class, self.default_response_class
605
- )
606
- current_tags = self.tags.copy()
607
- if tags:
608
- current_tags.extend(tags)
609
- current_dependencies = self.dependencies.copy()
610
- if dependencies:
611
- current_dependencies.extend(dependencies)
612
- current_callbacks = self.callbacks.copy()
613
- if callbacks:
614
- current_callbacks.extend(callbacks)
615
- current_generate_unique_id = get_value_or_default(
616
- generate_unique_id_function, self.generate_unique_id_function
617
- )
618
- route = route_class(
619
- self.prefix + path,
620
- endpoint=endpoint,
621
- response_model=response_model,
622
- status_code=status_code,
623
- tags=current_tags,
624
- dependencies=current_dependencies,
625
- summary=summary,
626
- description=description,
627
- response_description=response_description,
628
- responses=combined_responses,
629
- deprecated=deprecated or self.deprecated,
630
- methods=methods,
631
- operation_id=operation_id,
632
- response_model_include=response_model_include,
633
- response_model_exclude=response_model_exclude,
634
- response_model_by_alias=response_model_by_alias,
635
- response_model_exclude_unset=response_model_exclude_unset,
636
- response_model_exclude_defaults=response_model_exclude_defaults,
637
- response_model_exclude_none=response_model_exclude_none,
638
- include_in_schema=include_in_schema and self.include_in_schema,
639
- response_class=current_response_class,
640
- name=name,
641
- dependency_overrides_provider=self.dependency_overrides_provider,
642
- callbacks=current_callbacks,
643
- openapi_extra=openapi_extra,
644
- generate_unique_id_function=current_generate_unique_id,
645
- )
646
- self.routes.append(route)
647
-
648
- def api_route(
649
- self,
650
- path: str,
651
- *,
652
- response_model: Any = Default(None),
653
- status_code: Optional[int] = None,
654
- tags: Optional[List[Union[str, Enum]]] = None,
655
- dependencies: Optional[Sequence[params.Depends]] = None,
656
- summary: Optional[str] = None,
657
- description: Optional[str] = None,
658
- response_description: str = "Successful Response",
659
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
660
- deprecated: Optional[bool] = None,
661
- methods: Optional[List[str]] = None,
662
- operation_id: Optional[str] = None,
663
- response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
664
- response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
665
- response_model_by_alias: bool = True,
666
- response_model_exclude_unset: bool = False,
667
- response_model_exclude_defaults: bool = False,
668
- response_model_exclude_none: bool = False,
669
- include_in_schema: bool = True,
670
- response_class: Type[Response] = Default(JSONResponse),
671
- name: Optional[str] = None,
672
- callbacks: Optional[List[BaseRoute]] = None,
673
- openapi_extra: Optional[Dict[str, Any]] = None,
674
- generate_unique_id_function: Callable[[APIRoute], str] = Default(
675
- generate_unique_id
676
- ),
677
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
678
- def decorator(func: DecoratedCallable) -> DecoratedCallable:
679
- self.add_api_route(
680
- path,
681
- func,
682
- response_model=response_model,
683
- status_code=status_code,
684
- tags=tags,
685
- dependencies=dependencies,
686
- summary=summary,
687
- description=description,
688
- response_description=response_description,
689
- responses=responses,
690
- deprecated=deprecated,
691
- methods=methods,
692
- operation_id=operation_id,
693
- response_model_include=response_model_include,
694
- response_model_exclude=response_model_exclude,
695
- response_model_by_alias=response_model_by_alias,
696
- response_model_exclude_unset=response_model_exclude_unset,
697
- response_model_exclude_defaults=response_model_exclude_defaults,
698
- response_model_exclude_none=response_model_exclude_none,
699
- include_in_schema=include_in_schema,
700
- response_class=response_class,
701
- name=name,
702
- callbacks=callbacks,
703
- openapi_extra=openapi_extra,
704
- generate_unique_id_function=generate_unique_id_function,
705
- )
706
- return func
707
-
708
- return decorator
709
-
710
- def add_api_websocket_route(
711
- self,
712
- path: str,
713
- endpoint: Callable[..., Any],
714
- name: Optional[str] = None,
715
- *,
716
- dependencies: Optional[Sequence[params.Depends]] = None,
717
- ) -> None:
718
- current_dependencies = self.dependencies.copy()
719
- if dependencies:
720
- current_dependencies.extend(dependencies)
721
-
722
- route = APIWebSocketRoute(
723
- self.prefix + path,
724
- endpoint=endpoint,
725
- name=name,
726
- dependencies=current_dependencies,
727
- dependency_overrides_provider=self.dependency_overrides_provider,
728
- )
729
- self.routes.append(route)
730
-
731
- def websocket(
732
- self,
733
- path: str,
734
- name: Optional[str] = None,
735
- *,
736
- dependencies: Optional[Sequence[params.Depends]] = None,
737
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
738
- def decorator(func: DecoratedCallable) -> DecoratedCallable:
739
- self.add_api_websocket_route(
740
- path, func, name=name, dependencies=dependencies
741
- )
742
- return func
743
-
744
- return decorator
745
-
746
- def websocket_route(
747
- self, path: str, name: Union[str, None] = None
748
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
749
- def decorator(func: DecoratedCallable) -> DecoratedCallable:
750
- self.add_websocket_route(path, func, name=name)
751
- return func
752
-
753
- return decorator
754
-
755
- def include_router(
756
- self,
757
- router: "APIRouter",
758
- *,
759
- prefix: str = "",
760
- tags: Optional[List[Union[str, Enum]]] = None,
761
- dependencies: Optional[Sequence[params.Depends]] = None,
762
- default_response_class: Type[Response] = Default(JSONResponse),
763
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
764
- callbacks: Optional[List[BaseRoute]] = None,
765
- deprecated: Optional[bool] = None,
766
- include_in_schema: bool = True,
767
- generate_unique_id_function: Callable[[APIRoute], str] = Default(
768
- generate_unique_id
769
- ),
770
- ) -> None:
771
- if prefix:
772
- assert prefix.startswith("/"), "A path prefix must start with '/'"
773
- assert not prefix.endswith(
774
- "/"
775
- ), "A path prefix must not end with '/', as the routes will start with '/'"
776
- else:
777
- for r in router.routes:
778
- path = getattr(r, "path") # noqa: B009
779
- name = getattr(r, "name", "unknown")
780
- if path is not None and not path:
781
- raise FastAPIError(
782
- f"Prefix and path cannot be both empty (path operation: {name})"
783
- )
784
- if responses is None:
785
- responses = {}
786
- for route in router.routes:
787
- if isinstance(route, APIRoute):
788
- combined_responses = {**responses, **route.responses}
789
- use_response_class = get_value_or_default(
790
- route.response_class,
791
- router.default_response_class,
792
- default_response_class,
793
- self.default_response_class,
794
- )
795
- current_tags = []
796
- if tags:
797
- current_tags.extend(tags)
798
- if route.tags:
799
- current_tags.extend(route.tags)
800
- current_dependencies: List[params.Depends] = []
801
- if dependencies:
802
- current_dependencies.extend(dependencies)
803
- if route.dependencies:
804
- current_dependencies.extend(route.dependencies)
805
- current_callbacks = []
806
- if callbacks:
807
- current_callbacks.extend(callbacks)
808
- if route.callbacks:
809
- current_callbacks.extend(route.callbacks)
810
- current_generate_unique_id = get_value_or_default(
811
- route.generate_unique_id_function,
812
- router.generate_unique_id_function,
813
- generate_unique_id_function,
814
- self.generate_unique_id_function,
815
- )
816
- self.add_api_route(
817
- prefix + route.path,
818
- route.endpoint,
819
- response_model=route.response_model,
820
- status_code=route.status_code,
821
- tags=current_tags,
822
- dependencies=current_dependencies,
823
- summary=route.summary,
824
- description=route.description,
825
- response_description=route.response_description,
826
- responses=combined_responses,
827
- deprecated=route.deprecated or deprecated or self.deprecated,
828
- methods=route.methods,
829
- operation_id=route.operation_id,
830
- response_model_include=route.response_model_include,
831
- response_model_exclude=route.response_model_exclude,
832
- response_model_by_alias=route.response_model_by_alias,
833
- response_model_exclude_unset=route.response_model_exclude_unset,
834
- response_model_exclude_defaults=route.response_model_exclude_defaults,
835
- response_model_exclude_none=route.response_model_exclude_none,
836
- include_in_schema=route.include_in_schema
837
- and self.include_in_schema
838
- and include_in_schema,
839
- response_class=use_response_class,
840
- name=route.name,
841
- route_class_override=type(route),
842
- callbacks=current_callbacks,
843
- openapi_extra=route.openapi_extra,
844
- generate_unique_id_function=current_generate_unique_id,
845
- )
846
- elif isinstance(route, routing.Route):
847
- methods = list(route.methods or [])
848
- self.add_route(
849
- prefix + route.path,
850
- route.endpoint,
851
- methods=methods,
852
- include_in_schema=route.include_in_schema,
853
- name=route.name,
854
- )
855
- elif isinstance(route, APIWebSocketRoute):
856
- current_dependencies = []
857
- if dependencies:
858
- current_dependencies.extend(dependencies)
859
- if route.dependencies:
860
- current_dependencies.extend(route.dependencies)
861
- self.add_api_websocket_route(
862
- prefix + route.path,
863
- route.endpoint,
864
- dependencies=current_dependencies,
865
- name=route.name,
866
- )
867
- elif isinstance(route, routing.WebSocketRoute):
868
- self.add_websocket_route(
869
- prefix + route.path, route.endpoint, name=route.name
870
- )
871
- for handler in router.on_startup:
872
- self.add_event_handler("startup", handler)
873
- for handler in router.on_shutdown:
874
- self.add_event_handler("shutdown", handler)
875
-
876
- def get(
877
- self,
878
- path: str,
879
- *,
880
- response_model: Any = Default(None),
881
- status_code: Optional[int] = None,
882
- tags: Optional[List[Union[str, Enum]]] = None,
883
- dependencies: Optional[Sequence[params.Depends]] = None,
884
- summary: Optional[str] = None,
885
- description: Optional[str] = None,
886
- response_description: str = "Successful Response",
887
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
888
- deprecated: Optional[bool] = None,
889
- operation_id: Optional[str] = None,
890
- response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
891
- response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
892
- response_model_by_alias: bool = True,
893
- response_model_exclude_unset: bool = False,
894
- response_model_exclude_defaults: bool = False,
895
- response_model_exclude_none: bool = False,
896
- include_in_schema: bool = True,
897
- response_class: Type[Response] = Default(JSONResponse),
898
- name: Optional[str] = None,
899
- callbacks: Optional[List[BaseRoute]] = None,
900
- openapi_extra: Optional[Dict[str, Any]] = None,
901
- generate_unique_id_function: Callable[[APIRoute], str] = Default(
902
- generate_unique_id
903
- ),
904
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
905
- return self.api_route(
906
- path=path,
907
- response_model=response_model,
908
- status_code=status_code,
909
- tags=tags,
910
- dependencies=dependencies,
911
- summary=summary,
912
- description=description,
913
- response_description=response_description,
914
- responses=responses,
915
- deprecated=deprecated,
916
- methods=["GET"],
917
- operation_id=operation_id,
918
- response_model_include=response_model_include,
919
- response_model_exclude=response_model_exclude,
920
- response_model_by_alias=response_model_by_alias,
921
- response_model_exclude_unset=response_model_exclude_unset,
922
- response_model_exclude_defaults=response_model_exclude_defaults,
923
- response_model_exclude_none=response_model_exclude_none,
924
- include_in_schema=include_in_schema,
925
- response_class=response_class,
926
- name=name,
927
- callbacks=callbacks,
928
- openapi_extra=openapi_extra,
929
- generate_unique_id_function=generate_unique_id_function,
930
- )
931
-
932
- def put(
933
- self,
934
- path: str,
935
- *,
936
- response_model: Any = Default(None),
937
- status_code: Optional[int] = None,
938
- tags: Optional[List[Union[str, Enum]]] = None,
939
- dependencies: Optional[Sequence[params.Depends]] = None,
940
- summary: Optional[str] = None,
941
- description: Optional[str] = None,
942
- response_description: str = "Successful Response",
943
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
944
- deprecated: Optional[bool] = None,
945
- operation_id: Optional[str] = None,
946
- response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
947
- response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
948
- response_model_by_alias: bool = True,
949
- response_model_exclude_unset: bool = False,
950
- response_model_exclude_defaults: bool = False,
951
- response_model_exclude_none: bool = False,
952
- include_in_schema: bool = True,
953
- response_class: Type[Response] = Default(JSONResponse),
954
- name: Optional[str] = None,
955
- callbacks: Optional[List[BaseRoute]] = None,
956
- openapi_extra: Optional[Dict[str, Any]] = None,
957
- generate_unique_id_function: Callable[[APIRoute], str] = Default(
958
- generate_unique_id
959
- ),
960
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
961
- return self.api_route(
962
- path=path,
963
- response_model=response_model,
964
- status_code=status_code,
965
- tags=tags,
966
- dependencies=dependencies,
967
- summary=summary,
968
- description=description,
969
- response_description=response_description,
970
- responses=responses,
971
- deprecated=deprecated,
972
- methods=["PUT"],
973
- operation_id=operation_id,
974
- response_model_include=response_model_include,
975
- response_model_exclude=response_model_exclude,
976
- response_model_by_alias=response_model_by_alias,
977
- response_model_exclude_unset=response_model_exclude_unset,
978
- response_model_exclude_defaults=response_model_exclude_defaults,
979
- response_model_exclude_none=response_model_exclude_none,
980
- include_in_schema=include_in_schema,
981
- response_class=response_class,
982
- name=name,
983
- callbacks=callbacks,
984
- openapi_extra=openapi_extra,
985
- generate_unique_id_function=generate_unique_id_function,
986
- )
987
-
988
- def post(
989
- self,
990
- path: str,
991
- *,
992
- response_model: Any = Default(None),
993
- status_code: Optional[int] = None,
994
- tags: Optional[List[Union[str, Enum]]] = None,
995
- dependencies: Optional[Sequence[params.Depends]] = None,
996
- summary: Optional[str] = None,
997
- description: Optional[str] = None,
998
- response_description: str = "Successful Response",
999
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
1000
- deprecated: Optional[bool] = None,
1001
- operation_id: Optional[str] = None,
1002
- response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
1003
- response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
1004
- response_model_by_alias: bool = True,
1005
- response_model_exclude_unset: bool = False,
1006
- response_model_exclude_defaults: bool = False,
1007
- response_model_exclude_none: bool = False,
1008
- include_in_schema: bool = True,
1009
- response_class: Type[Response] = Default(JSONResponse),
1010
- name: Optional[str] = None,
1011
- callbacks: Optional[List[BaseRoute]] = None,
1012
- openapi_extra: Optional[Dict[str, Any]] = None,
1013
- generate_unique_id_function: Callable[[APIRoute], str] = Default(
1014
- generate_unique_id
1015
- ),
1016
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
1017
- return self.api_route(
1018
- path=path,
1019
- response_model=response_model,
1020
- status_code=status_code,
1021
- tags=tags,
1022
- dependencies=dependencies,
1023
- summary=summary,
1024
- description=description,
1025
- response_description=response_description,
1026
- responses=responses,
1027
- deprecated=deprecated,
1028
- methods=["POST"],
1029
- operation_id=operation_id,
1030
- response_model_include=response_model_include,
1031
- response_model_exclude=response_model_exclude,
1032
- response_model_by_alias=response_model_by_alias,
1033
- response_model_exclude_unset=response_model_exclude_unset,
1034
- response_model_exclude_defaults=response_model_exclude_defaults,
1035
- response_model_exclude_none=response_model_exclude_none,
1036
- include_in_schema=include_in_schema,
1037
- response_class=response_class,
1038
- name=name,
1039
- callbacks=callbacks,
1040
- openapi_extra=openapi_extra,
1041
- generate_unique_id_function=generate_unique_id_function,
1042
- )
1043
-
1044
- def delete(
1045
- self,
1046
- path: str,
1047
- *,
1048
- response_model: Any = Default(None),
1049
- status_code: Optional[int] = None,
1050
- tags: Optional[List[Union[str, Enum]]] = None,
1051
- dependencies: Optional[Sequence[params.Depends]] = None,
1052
- summary: Optional[str] = None,
1053
- description: Optional[str] = None,
1054
- response_description: str = "Successful Response",
1055
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
1056
- deprecated: Optional[bool] = None,
1057
- operation_id: Optional[str] = None,
1058
- response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
1059
- response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
1060
- response_model_by_alias: bool = True,
1061
- response_model_exclude_unset: bool = False,
1062
- response_model_exclude_defaults: bool = False,
1063
- response_model_exclude_none: bool = False,
1064
- include_in_schema: bool = True,
1065
- response_class: Type[Response] = Default(JSONResponse),
1066
- name: Optional[str] = None,
1067
- callbacks: Optional[List[BaseRoute]] = None,
1068
- openapi_extra: Optional[Dict[str, Any]] = None,
1069
- generate_unique_id_function: Callable[[APIRoute], str] = Default(
1070
- generate_unique_id
1071
- ),
1072
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
1073
- return self.api_route(
1074
- path=path,
1075
- response_model=response_model,
1076
- status_code=status_code,
1077
- tags=tags,
1078
- dependencies=dependencies,
1079
- summary=summary,
1080
- description=description,
1081
- response_description=response_description,
1082
- responses=responses,
1083
- deprecated=deprecated,
1084
- methods=["DELETE"],
1085
- operation_id=operation_id,
1086
- response_model_include=response_model_include,
1087
- response_model_exclude=response_model_exclude,
1088
- response_model_by_alias=response_model_by_alias,
1089
- response_model_exclude_unset=response_model_exclude_unset,
1090
- response_model_exclude_defaults=response_model_exclude_defaults,
1091
- response_model_exclude_none=response_model_exclude_none,
1092
- include_in_schema=include_in_schema,
1093
- response_class=response_class,
1094
- name=name,
1095
- callbacks=callbacks,
1096
- openapi_extra=openapi_extra,
1097
- generate_unique_id_function=generate_unique_id_function,
1098
- )
1099
-
1100
- def options(
1101
- self,
1102
- path: str,
1103
- *,
1104
- response_model: Any = Default(None),
1105
- status_code: Optional[int] = None,
1106
- tags: Optional[List[Union[str, Enum]]] = None,
1107
- dependencies: Optional[Sequence[params.Depends]] = None,
1108
- summary: Optional[str] = None,
1109
- description: Optional[str] = None,
1110
- response_description: str = "Successful Response",
1111
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
1112
- deprecated: Optional[bool] = None,
1113
- operation_id: Optional[str] = None,
1114
- response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
1115
- response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
1116
- response_model_by_alias: bool = True,
1117
- response_model_exclude_unset: bool = False,
1118
- response_model_exclude_defaults: bool = False,
1119
- response_model_exclude_none: bool = False,
1120
- include_in_schema: bool = True,
1121
- response_class: Type[Response] = Default(JSONResponse),
1122
- name: Optional[str] = None,
1123
- callbacks: Optional[List[BaseRoute]] = None,
1124
- openapi_extra: Optional[Dict[str, Any]] = None,
1125
- generate_unique_id_function: Callable[[APIRoute], str] = Default(
1126
- generate_unique_id
1127
- ),
1128
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
1129
- return self.api_route(
1130
- path=path,
1131
- response_model=response_model,
1132
- status_code=status_code,
1133
- tags=tags,
1134
- dependencies=dependencies,
1135
- summary=summary,
1136
- description=description,
1137
- response_description=response_description,
1138
- responses=responses,
1139
- deprecated=deprecated,
1140
- methods=["OPTIONS"],
1141
- operation_id=operation_id,
1142
- response_model_include=response_model_include,
1143
- response_model_exclude=response_model_exclude,
1144
- response_model_by_alias=response_model_by_alias,
1145
- response_model_exclude_unset=response_model_exclude_unset,
1146
- response_model_exclude_defaults=response_model_exclude_defaults,
1147
- response_model_exclude_none=response_model_exclude_none,
1148
- include_in_schema=include_in_schema,
1149
- response_class=response_class,
1150
- name=name,
1151
- callbacks=callbacks,
1152
- openapi_extra=openapi_extra,
1153
- generate_unique_id_function=generate_unique_id_function,
1154
- )
1155
-
1156
- def head(
1157
- self,
1158
- path: str,
1159
- *,
1160
- response_model: Any = Default(None),
1161
- status_code: Optional[int] = None,
1162
- tags: Optional[List[Union[str, Enum]]] = None,
1163
- dependencies: Optional[Sequence[params.Depends]] = None,
1164
- summary: Optional[str] = None,
1165
- description: Optional[str] = None,
1166
- response_description: str = "Successful Response",
1167
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
1168
- deprecated: Optional[bool] = None,
1169
- operation_id: Optional[str] = None,
1170
- response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
1171
- response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
1172
- response_model_by_alias: bool = True,
1173
- response_model_exclude_unset: bool = False,
1174
- response_model_exclude_defaults: bool = False,
1175
- response_model_exclude_none: bool = False,
1176
- include_in_schema: bool = True,
1177
- response_class: Type[Response] = Default(JSONResponse),
1178
- name: Optional[str] = None,
1179
- callbacks: Optional[List[BaseRoute]] = None,
1180
- openapi_extra: Optional[Dict[str, Any]] = None,
1181
- generate_unique_id_function: Callable[[APIRoute], str] = Default(
1182
- generate_unique_id
1183
- ),
1184
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
1185
- return self.api_route(
1186
- path=path,
1187
- response_model=response_model,
1188
- status_code=status_code,
1189
- tags=tags,
1190
- dependencies=dependencies,
1191
- summary=summary,
1192
- description=description,
1193
- response_description=response_description,
1194
- responses=responses,
1195
- deprecated=deprecated,
1196
- methods=["HEAD"],
1197
- operation_id=operation_id,
1198
- response_model_include=response_model_include,
1199
- response_model_exclude=response_model_exclude,
1200
- response_model_by_alias=response_model_by_alias,
1201
- response_model_exclude_unset=response_model_exclude_unset,
1202
- response_model_exclude_defaults=response_model_exclude_defaults,
1203
- response_model_exclude_none=response_model_exclude_none,
1204
- include_in_schema=include_in_schema,
1205
- response_class=response_class,
1206
- name=name,
1207
- callbacks=callbacks,
1208
- openapi_extra=openapi_extra,
1209
- generate_unique_id_function=generate_unique_id_function,
1210
- )
1211
-
1212
- def patch(
1213
- self,
1214
- path: str,
1215
- *,
1216
- response_model: Any = Default(None),
1217
- status_code: Optional[int] = None,
1218
- tags: Optional[List[Union[str, Enum]]] = None,
1219
- dependencies: Optional[Sequence[params.Depends]] = None,
1220
- summary: Optional[str] = None,
1221
- description: Optional[str] = None,
1222
- response_description: str = "Successful Response",
1223
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
1224
- deprecated: Optional[bool] = None,
1225
- operation_id: Optional[str] = None,
1226
- response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
1227
- response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
1228
- response_model_by_alias: bool = True,
1229
- response_model_exclude_unset: bool = False,
1230
- response_model_exclude_defaults: bool = False,
1231
- response_model_exclude_none: bool = False,
1232
- include_in_schema: bool = True,
1233
- response_class: Type[Response] = Default(JSONResponse),
1234
- name: Optional[str] = None,
1235
- callbacks: Optional[List[BaseRoute]] = None,
1236
- openapi_extra: Optional[Dict[str, Any]] = None,
1237
- generate_unique_id_function: Callable[[APIRoute], str] = Default(
1238
- generate_unique_id
1239
- ),
1240
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
1241
- return self.api_route(
1242
- path=path,
1243
- response_model=response_model,
1244
- status_code=status_code,
1245
- tags=tags,
1246
- dependencies=dependencies,
1247
- summary=summary,
1248
- description=description,
1249
- response_description=response_description,
1250
- responses=responses,
1251
- deprecated=deprecated,
1252
- methods=["PATCH"],
1253
- operation_id=operation_id,
1254
- response_model_include=response_model_include,
1255
- response_model_exclude=response_model_exclude,
1256
- response_model_by_alias=response_model_by_alias,
1257
- response_model_exclude_unset=response_model_exclude_unset,
1258
- response_model_exclude_defaults=response_model_exclude_defaults,
1259
- response_model_exclude_none=response_model_exclude_none,
1260
- include_in_schema=include_in_schema,
1261
- response_class=response_class,
1262
- name=name,
1263
- callbacks=callbacks,
1264
- openapi_extra=openapi_extra,
1265
- generate_unique_id_function=generate_unique_id_function,
1266
- )
1267
-
1268
- def trace(
1269
- self,
1270
- path: str,
1271
- *,
1272
- response_model: Any = Default(None),
1273
- status_code: Optional[int] = None,
1274
- tags: Optional[List[Union[str, Enum]]] = None,
1275
- dependencies: Optional[Sequence[params.Depends]] = None,
1276
- summary: Optional[str] = None,
1277
- description: Optional[str] = None,
1278
- response_description: str = "Successful Response",
1279
- responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
1280
- deprecated: Optional[bool] = None,
1281
- operation_id: Optional[str] = None,
1282
- response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
1283
- response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
1284
- response_model_by_alias: bool = True,
1285
- response_model_exclude_unset: bool = False,
1286
- response_model_exclude_defaults: bool = False,
1287
- response_model_exclude_none: bool = False,
1288
- include_in_schema: bool = True,
1289
- response_class: Type[Response] = Default(JSONResponse),
1290
- name: Optional[str] = None,
1291
- callbacks: Optional[List[BaseRoute]] = None,
1292
- openapi_extra: Optional[Dict[str, Any]] = None,
1293
- generate_unique_id_function: Callable[[APIRoute], str] = Default(
1294
- generate_unique_id
1295
- ),
1296
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
1297
- return self.api_route(
1298
- path=path,
1299
- response_model=response_model,
1300
- status_code=status_code,
1301
- tags=tags,
1302
- dependencies=dependencies,
1303
- summary=summary,
1304
- description=description,
1305
- response_description=response_description,
1306
- responses=responses,
1307
- deprecated=deprecated,
1308
- methods=["TRACE"],
1309
- operation_id=operation_id,
1310
- response_model_include=response_model_include,
1311
- response_model_exclude=response_model_exclude,
1312
- response_model_by_alias=response_model_by_alias,
1313
- response_model_exclude_unset=response_model_exclude_unset,
1314
- response_model_exclude_defaults=response_model_exclude_defaults,
1315
- response_model_exclude_none=response_model_exclude_none,
1316
- include_in_schema=include_in_schema,
1317
- response_class=response_class,
1318
- name=name,
1319
- callbacks=callbacks,
1320
- openapi_extra=openapi_extra,
1321
- generate_unique_id_function=generate_unique_id_function,
1322
- )
1323
-
1324
- def on_event(
1325
- self, event_type: str
1326
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
1327
- def decorator(func: DecoratedCallable) -> DecoratedCallable:
1328
- self.add_event_handler(event_type, func)
1329
- return func
1330
-
1331
- return decorator