fastapi 0.117.0__py3-none-any.whl → 0.118.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.

Potentially problematic release.


This version of fastapi might be problematic. Click here for more details.

fastapi/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
2
2
 
3
- __version__ = "0.117.0"
3
+ __version__ = "0.118.0"
4
4
 
5
5
  from starlette import status as status
6
6
 
fastapi/applications.py CHANGED
@@ -22,6 +22,7 @@ from fastapi.exception_handlers import (
22
22
  )
23
23
  from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError
24
24
  from fastapi.logger import logger
25
+ from fastapi.middleware.asyncexitstack import AsyncExitStackMiddleware
25
26
  from fastapi.openapi.docs import (
26
27
  get_redoc_html,
27
28
  get_swagger_ui_html,
@@ -36,10 +37,12 @@ from starlette.datastructures import State
36
37
  from starlette.exceptions import HTTPException
37
38
  from starlette.middleware import Middleware
38
39
  from starlette.middleware.base import BaseHTTPMiddleware
40
+ from starlette.middleware.errors import ServerErrorMiddleware
41
+ from starlette.middleware.exceptions import ExceptionMiddleware
39
42
  from starlette.requests import Request
40
43
  from starlette.responses import HTMLResponse, JSONResponse, Response
41
44
  from starlette.routing import BaseRoute
42
- from starlette.types import ASGIApp, Lifespan, Receive, Scope, Send
45
+ from starlette.types import ASGIApp, ExceptionHandler, Lifespan, Receive, Scope, Send
43
46
  from typing_extensions import Annotated, Doc, deprecated
44
47
 
45
48
  AppType = TypeVar("AppType", bound="FastAPI")
@@ -990,6 +993,54 @@ class FastAPI(Starlette):
990
993
  self.middleware_stack: Union[ASGIApp, None] = None
991
994
  self.setup()
992
995
 
996
+ def build_middleware_stack(self) -> ASGIApp:
997
+ # Duplicate/override from Starlette to add AsyncExitStackMiddleware
998
+ # inside of ExceptionMiddleware, inside of custom user middlewares
999
+ debug = self.debug
1000
+ error_handler = None
1001
+ exception_handlers: dict[Any, ExceptionHandler] = {}
1002
+
1003
+ for key, value in self.exception_handlers.items():
1004
+ if key in (500, Exception):
1005
+ error_handler = value
1006
+ else:
1007
+ exception_handlers[key] = value
1008
+
1009
+ middleware = (
1010
+ [Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)]
1011
+ + self.user_middleware
1012
+ + [
1013
+ Middleware(
1014
+ ExceptionMiddleware, handlers=exception_handlers, debug=debug
1015
+ ),
1016
+ # Add FastAPI-specific AsyncExitStackMiddleware for closing files.
1017
+ # Before this was also used for closing dependencies with yield but
1018
+ # those now have their own AsyncExitStack, to properly support
1019
+ # streaming responses while keeping compatibility with the previous
1020
+ # versions (as of writing 0.117.1) that allowed doing
1021
+ # except HTTPException inside a dependency with yield.
1022
+ # This needs to happen after user middlewares because those create a
1023
+ # new contextvars context copy by using a new AnyIO task group.
1024
+ # This AsyncExitStack preserves the context for contextvars, not
1025
+ # strictly necessary for closing files but it was one of the original
1026
+ # intentions.
1027
+ # If the AsyncExitStack lived outside of the custom middlewares and
1028
+ # contextvars were set, for example in a dependency with 'yield'
1029
+ # in that internal contextvars context, the values would not be
1030
+ # available in the outer context of the AsyncExitStack.
1031
+ # By placing the middleware and the AsyncExitStack here, inside all
1032
+ # user middlewares, the same context is used.
1033
+ # This is currently not needed, only for closing files, but used to be
1034
+ # important when dependencies with yield were closed here.
1035
+ Middleware(AsyncExitStackMiddleware),
1036
+ ]
1037
+ )
1038
+
1039
+ app = self.router
1040
+ for cls, args, kwargs in reversed(middleware):
1041
+ app = cls(app, *args, **kwargs)
1042
+ return app
1043
+
993
1044
  def openapi(self) -> Dict[str, Any]:
994
1045
  """
995
1046
  Generate the OpenAPI schema of the application. This is called by FastAPI
@@ -872,20 +872,19 @@ async def _extract_form_body(
872
872
  received_body: FormData,
873
873
  ) -> Dict[str, Any]:
874
874
  values = {}
875
- first_field = body_fields[0]
876
- first_field_info = first_field.field_info
877
875
 
878
876
  for field in body_fields:
879
877
  value = _get_multidict_value(field, received_body)
878
+ field_info = field.field_info
880
879
  if (
881
- isinstance(first_field_info, params.File)
880
+ isinstance(field_info, params.File)
882
881
  and is_bytes_field(field)
883
882
  and isinstance(value, UploadFile)
884
883
  ):
885
884
  value = await value.read()
886
885
  elif (
887
886
  is_bytes_sequence_field(field)
888
- and isinstance(first_field_info, params.File)
887
+ and isinstance(field_info, params.File)
889
888
  and value_is_sequence(value)
890
889
  ):
891
890
  # For types
@@ -0,0 +1,18 @@
1
+ from contextlib import AsyncExitStack
2
+
3
+ from starlette.types import ASGIApp, Receive, Scope, Send
4
+
5
+
6
+ # Used mainly to close files after the request is done, dependencies are closed
7
+ # in their own AsyncExitStack
8
+ class AsyncExitStackMiddleware:
9
+ def __init__(
10
+ self, app: ASGIApp, context_name: str = "fastapi_middleware_astack"
11
+ ) -> None:
12
+ self.app = app
13
+ self.context_name = context_name
14
+
15
+ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
16
+ async with AsyncExitStack() as stack:
17
+ scope[self.context_name] = stack
18
+ await self.app(scope, receive, send)
fastapi/routing.py CHANGED
@@ -1,5 +1,6 @@
1
1
  import dataclasses
2
2
  import email.message
3
+ import functools
3
4
  import inspect
4
5
  import json
5
6
  import sys
@@ -8,6 +9,7 @@ from enum import Enum, IntEnum
8
9
  from typing import (
9
10
  Any,
10
11
  AsyncIterator,
12
+ Awaitable,
11
13
  Callable,
12
14
  Collection,
13
15
  Coroutine,
@@ -59,6 +61,8 @@ from fastapi.utils import (
59
61
  )
60
62
  from pydantic import BaseModel
61
63
  from starlette import routing
64
+ from starlette._exception_handler import wrap_app_handling_exceptions
65
+ from starlette._utils import is_async_callable
62
66
  from starlette.concurrency import run_in_threadpool
63
67
  from starlette.exceptions import HTTPException
64
68
  from starlette.requests import Request
@@ -68,11 +72,9 @@ from starlette.routing import (
68
72
  Match,
69
73
  compile_path,
70
74
  get_name,
71
- request_response,
72
- websocket_session,
73
75
  )
74
76
  from starlette.routing import Mount as Mount # noqa
75
- from starlette.types import AppType, ASGIApp, Lifespan, Scope
77
+ from starlette.types import AppType, ASGIApp, Lifespan, Receive, Scope, Send
76
78
  from starlette.websockets import WebSocket
77
79
  from typing_extensions import Annotated, Doc, deprecated
78
80
 
@@ -82,6 +84,73 @@ else: # pragma: no cover
82
84
  from asyncio import iscoroutinefunction
83
85
 
84
86
 
87
+ # Copy of starlette.routing.request_response modified to include the
88
+ # dependencies' AsyncExitStack
89
+ def request_response(
90
+ func: Callable[[Request], Union[Awaitable[Response], Response]],
91
+ ) -> ASGIApp:
92
+ """
93
+ Takes a function or coroutine `func(request) -> response`,
94
+ and returns an ASGI application.
95
+ """
96
+ f: Callable[[Request], Awaitable[Response]] = (
97
+ func if is_async_callable(func) else functools.partial(run_in_threadpool, func) # type:ignore
98
+ )
99
+
100
+ async def app(scope: Scope, receive: Receive, send: Send) -> None:
101
+ request = Request(scope, receive, send)
102
+
103
+ async def app(scope: Scope, receive: Receive, send: Send) -> None:
104
+ # Starts customization
105
+ response_awaited = False
106
+ async with AsyncExitStack() as stack:
107
+ scope["fastapi_inner_astack"] = stack
108
+ # Same as in Starlette
109
+ response = await f(request)
110
+ await response(scope, receive, send)
111
+ # Continues customization
112
+ response_awaited = True
113
+ if not response_awaited:
114
+ raise FastAPIError(
115
+ "Response not awaited. There's a high chance that the "
116
+ "application code is raising an exception and a dependency with yield "
117
+ "has a block with a bare except, or a block with except Exception, "
118
+ "and is not raising the exception again. Read more about it in the "
119
+ "docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except"
120
+ )
121
+
122
+ # Same as in Starlette
123
+ await wrap_app_handling_exceptions(app, request)(scope, receive, send)
124
+
125
+ return app
126
+
127
+
128
+ # Copy of starlette.routing.websocket_session modified to include the
129
+ # dependencies' AsyncExitStack
130
+ def websocket_session(
131
+ func: Callable[[WebSocket], Awaitable[None]],
132
+ ) -> ASGIApp:
133
+ """
134
+ Takes a coroutine `func(session)`, and returns an ASGI application.
135
+ """
136
+ # assert asyncio.iscoroutinefunction(func), "WebSocket endpoints must be async"
137
+
138
+ async def app(scope: Scope, receive: Receive, send: Send) -> None:
139
+ session = WebSocket(scope, receive=receive, send=send)
140
+
141
+ async def app(scope: Scope, receive: Receive, send: Send) -> None:
142
+ # Starts customization
143
+ async with AsyncExitStack() as stack:
144
+ scope["fastapi_inner_astack"] = stack
145
+ # Same as in Starlette
146
+ await func(session)
147
+
148
+ # Same as in Starlette
149
+ await wrap_app_handling_exceptions(app, session)(scope, receive, send)
150
+
151
+ return app
152
+
153
+
85
154
  def _prepare_response_content(
86
155
  res: Any,
87
156
  *,
@@ -246,119 +315,120 @@ def get_request_handler(
246
315
 
247
316
  async def app(request: Request) -> Response:
248
317
  response: Union[Response, None] = None
249
- async with AsyncExitStack() as file_stack:
250
- try:
251
- body: Any = None
252
- if body_field:
253
- if is_body_form:
254
- body = await request.form()
255
- file_stack.push_async_callback(body.close)
256
- else:
257
- body_bytes = await request.body()
258
- if body_bytes:
259
- json_body: Any = Undefined
260
- content_type_value = request.headers.get("content-type")
261
- if not content_type_value:
262
- json_body = await request.json()
263
- else:
264
- message = email.message.Message()
265
- message["content-type"] = content_type_value
266
- if message.get_content_maintype() == "application":
267
- subtype = message.get_content_subtype()
268
- if subtype == "json" or subtype.endswith("+json"):
269
- json_body = await request.json()
270
- if json_body != Undefined:
271
- body = json_body
272
- else:
273
- body = body_bytes
274
- except json.JSONDecodeError as e:
275
- validation_error = RequestValidationError(
276
- [
277
- {
278
- "type": "json_invalid",
279
- "loc": ("body", e.pos),
280
- "msg": "JSON decode error",
281
- "input": {},
282
- "ctx": {"error": e.msg},
283
- }
284
- ],
285
- body=e.doc,
286
- )
287
- raise validation_error from e
288
- except HTTPException:
289
- # If a middleware raises an HTTPException, it should be raised again
290
- raise
291
- except Exception as e:
292
- http_error = HTTPException(
293
- status_code=400, detail="There was an error parsing the body"
294
- )
295
- raise http_error from e
296
- errors: List[Any] = []
297
- async with AsyncExitStack() as async_exit_stack:
298
- solved_result = await solve_dependencies(
299
- request=request,
300
- dependant=dependant,
301
- body=body,
302
- dependency_overrides_provider=dependency_overrides_provider,
303
- async_exit_stack=async_exit_stack,
304
- embed_body_fields=embed_body_fields,
318
+ file_stack = request.scope.get("fastapi_middleware_astack")
319
+ assert isinstance(file_stack, AsyncExitStack), (
320
+ "fastapi_middleware_astack not found in request scope"
321
+ )
322
+
323
+ # Read body and auto-close files
324
+ try:
325
+ body: Any = None
326
+ if body_field:
327
+ if is_body_form:
328
+ body = await request.form()
329
+ file_stack.push_async_callback(body.close)
330
+ else:
331
+ body_bytes = await request.body()
332
+ if body_bytes:
333
+ json_body: Any = Undefined
334
+ content_type_value = request.headers.get("content-type")
335
+ if not content_type_value:
336
+ json_body = await request.json()
337
+ else:
338
+ message = email.message.Message()
339
+ message["content-type"] = content_type_value
340
+ if message.get_content_maintype() == "application":
341
+ subtype = message.get_content_subtype()
342
+ if subtype == "json" or subtype.endswith("+json"):
343
+ json_body = await request.json()
344
+ if json_body != Undefined:
345
+ body = json_body
346
+ else:
347
+ body = body_bytes
348
+ except json.JSONDecodeError as e:
349
+ validation_error = RequestValidationError(
350
+ [
351
+ {
352
+ "type": "json_invalid",
353
+ "loc": ("body", e.pos),
354
+ "msg": "JSON decode error",
355
+ "input": {},
356
+ "ctx": {"error": e.msg},
357
+ }
358
+ ],
359
+ body=e.doc,
360
+ )
361
+ raise validation_error from e
362
+ except HTTPException:
363
+ # If a middleware raises an HTTPException, it should be raised again
364
+ raise
365
+ except Exception as e:
366
+ http_error = HTTPException(
367
+ status_code=400, detail="There was an error parsing the body"
368
+ )
369
+ raise http_error from e
370
+
371
+ # Solve dependencies and run path operation function, auto-closing dependencies
372
+ errors: List[Any] = []
373
+ async_exit_stack = request.scope.get("fastapi_inner_astack")
374
+ assert isinstance(async_exit_stack, AsyncExitStack), (
375
+ "fastapi_inner_astack not found in request scope"
376
+ )
377
+ solved_result = await solve_dependencies(
378
+ request=request,
379
+ dependant=dependant,
380
+ body=body,
381
+ dependency_overrides_provider=dependency_overrides_provider,
382
+ async_exit_stack=async_exit_stack,
383
+ embed_body_fields=embed_body_fields,
384
+ )
385
+ errors = solved_result.errors
386
+ if not errors:
387
+ raw_response = await run_endpoint_function(
388
+ dependant=dependant,
389
+ values=solved_result.values,
390
+ is_coroutine=is_coroutine,
391
+ )
392
+ if isinstance(raw_response, Response):
393
+ if raw_response.background is None:
394
+ raw_response.background = solved_result.background_tasks
395
+ response = raw_response
396
+ else:
397
+ response_args: Dict[str, Any] = {
398
+ "background": solved_result.background_tasks
399
+ }
400
+ # If status_code was set, use it, otherwise use the default from the
401
+ # response class, in the case of redirect it's 307
402
+ current_status_code = (
403
+ status_code if status_code else solved_result.response.status_code
305
404
  )
306
- errors = solved_result.errors
307
- if not errors:
308
- raw_response = await run_endpoint_function(
309
- dependant=dependant,
310
- values=solved_result.values,
311
- is_coroutine=is_coroutine,
312
- )
313
- if isinstance(raw_response, Response):
314
- if raw_response.background is None:
315
- raw_response.background = solved_result.background_tasks
316
- response = raw_response
317
- else:
318
- response_args: Dict[str, Any] = {
319
- "background": solved_result.background_tasks
320
- }
321
- # If status_code was set, use it, otherwise use the default from the
322
- # response class, in the case of redirect it's 307
323
- current_status_code = (
324
- status_code
325
- if status_code
326
- else solved_result.response.status_code
327
- )
328
- if current_status_code is not None:
329
- response_args["status_code"] = current_status_code
330
- if solved_result.response.status_code:
331
- response_args["status_code"] = (
332
- solved_result.response.status_code
333
- )
334
- content = await serialize_response(
335
- field=response_field,
336
- response_content=raw_response,
337
- include=response_model_include,
338
- exclude=response_model_exclude,
339
- by_alias=response_model_by_alias,
340
- exclude_unset=response_model_exclude_unset,
341
- exclude_defaults=response_model_exclude_defaults,
342
- exclude_none=response_model_exclude_none,
343
- is_coroutine=is_coroutine,
344
- )
345
- response = actual_response_class(content, **response_args)
346
- if not is_body_allowed_for_status_code(response.status_code):
347
- response.body = b""
348
- response.headers.raw.extend(solved_result.response.headers.raw)
349
- if errors:
350
- validation_error = RequestValidationError(
351
- _normalize_errors(errors), body=body
405
+ if current_status_code is not None:
406
+ response_args["status_code"] = current_status_code
407
+ if solved_result.response.status_code:
408
+ response_args["status_code"] = solved_result.response.status_code
409
+ content = await serialize_response(
410
+ field=response_field,
411
+ response_content=raw_response,
412
+ include=response_model_include,
413
+ exclude=response_model_exclude,
414
+ by_alias=response_model_by_alias,
415
+ exclude_unset=response_model_exclude_unset,
416
+ exclude_defaults=response_model_exclude_defaults,
417
+ exclude_none=response_model_exclude_none,
418
+ is_coroutine=is_coroutine,
352
419
  )
353
- raise validation_error
354
- if response is None:
355
- raise FastAPIError(
356
- "No response object was returned. There's a high chance that the "
357
- "application code is raising an exception and a dependency with yield "
358
- "has a block with a bare except, or a block with except Exception, "
359
- "and is not raising the exception again. Read more about it in the "
360
- "docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except"
420
+ response = actual_response_class(content, **response_args)
421
+ if not is_body_allowed_for_status_code(response.status_code):
422
+ response.body = b""
423
+ response.headers.raw.extend(solved_result.response.headers.raw)
424
+ if errors:
425
+ validation_error = RequestValidationError(
426
+ _normalize_errors(errors), body=body
361
427
  )
428
+ raise validation_error
429
+
430
+ # Return response
431
+ assert response
362
432
  return response
363
433
 
364
434
  return app
@@ -370,24 +440,23 @@ def get_websocket_app(
370
440
  embed_body_fields: bool = False,
371
441
  ) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]:
372
442
  async def app(websocket: WebSocket) -> None:
373
- async with AsyncExitStack() as async_exit_stack:
374
- # TODO: remove this scope later, after a few releases
375
- # This scope fastapi_astack is no longer used by FastAPI, kept for
376
- # compatibility, just in case
377
- websocket.scope["fastapi_astack"] = async_exit_stack
378
- solved_result = await solve_dependencies(
379
- request=websocket,
380
- dependant=dependant,
381
- dependency_overrides_provider=dependency_overrides_provider,
382
- async_exit_stack=async_exit_stack,
383
- embed_body_fields=embed_body_fields,
443
+ async_exit_stack = websocket.scope.get("fastapi_inner_astack")
444
+ assert isinstance(async_exit_stack, AsyncExitStack), (
445
+ "fastapi_inner_astack not found in request scope"
446
+ )
447
+ solved_result = await solve_dependencies(
448
+ request=websocket,
449
+ dependant=dependant,
450
+ dependency_overrides_provider=dependency_overrides_provider,
451
+ async_exit_stack=async_exit_stack,
452
+ embed_body_fields=embed_body_fields,
453
+ )
454
+ if solved_result.errors:
455
+ raise WebSocketRequestValidationError(
456
+ _normalize_errors(solved_result.errors)
384
457
  )
385
- if solved_result.errors:
386
- raise WebSocketRequestValidationError(
387
- _normalize_errors(solved_result.errors)
388
- )
389
- assert dependant.call is not None, "dependant.call must be a function"
390
- await dependant.call(**solved_result.values)
458
+ assert dependant.call is not None, "dependant.call must be a function"
459
+ await dependant.call(**solved_result.values)
391
460
 
392
461
  return app
393
462
 
@@ -89,7 +89,7 @@ class OAuth2PasswordRequestForm:
89
89
  Doc(
90
90
  """
91
91
  `password` string. The OAuth2 spec requires the exact field name
92
- `password".
92
+ `password`.
93
93
  """
94
94
  ),
95
95
  ],
@@ -243,7 +243,7 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm):
243
243
  Doc(
244
244
  """
245
245
  `password` string. The OAuth2 spec requires the exact field name
246
- `password".
246
+ `password`.
247
247
  """
248
248
  ),
249
249
  ],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastapi
3
- Version: 0.117.0
3
+ Version: 0.118.0
4
4
  Summary: FastAPI framework, high performance, easy to learn, fast to code, ready for production
5
5
  Author-Email: =?utf-8?q?Sebasti=C3=A1n_Ram=C3=ADrez?= <tiangolo@gmail.com>
6
6
  Classifier: Intended Audience :: Information Technology
@@ -1,23 +1,24 @@
1
- fastapi-0.117.0.dist-info/METADATA,sha256=a_6-VSmVf3pQTvUR5AD-EYxN8A5jcjUQOXB13_KJk5Q,28135
2
- fastapi-0.117.0.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
- fastapi-0.117.0.dist-info/entry_points.txt,sha256=GCf-WbIZxyGT4MUmrPGj1cOHYZoGsNPHAvNkT6hnGeA,61
4
- fastapi-0.117.0.dist-info/licenses/LICENSE,sha256=Tsif_IFIW5f-xYSy1KlhAy7v_oNEU4lP2cEnSQbMdE4,1086
5
- fastapi/__init__.py,sha256=kABrsOHBxqoWBLvbTjMc2bL6XdMxbLNqWWYfXR7AyMU,1081
1
+ fastapi-0.118.0.dist-info/METADATA,sha256=RU7sXRYZDFARbkSSsO8GPrY7UfY76lmfqw9KZ2vXT6g,28135
2
+ fastapi-0.118.0.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
+ fastapi-0.118.0.dist-info/entry_points.txt,sha256=GCf-WbIZxyGT4MUmrPGj1cOHYZoGsNPHAvNkT6hnGeA,61
4
+ fastapi-0.118.0.dist-info/licenses/LICENSE,sha256=Tsif_IFIW5f-xYSy1KlhAy7v_oNEU4lP2cEnSQbMdE4,1086
5
+ fastapi/__init__.py,sha256=SlrlRcZQncT3o5Yip5GQIOvht2J2uCLN1rY2m_TPfuA,1081
6
6
  fastapi/__main__.py,sha256=bKePXLdO4SsVSM6r9SVoLickJDcR2c0cTOxZRKq26YQ,37
7
7
  fastapi/_compat.py,sha256=EQyNY-qrN3cjwI1r69JVAROc2lQCvi6W1we6_7jx_gc,24274
8
- fastapi/applications.py,sha256=Sr6fkAYFmuyIT4b0Rm33NQzO8oz4-DEc3PLTxp4LJgU,177570
8
+ fastapi/applications.py,sha256=nLbGcVdmCxXsl4aTSuP0WVS_XGY7wXBL3vC7nqlplmA,180276
9
9
  fastapi/background.py,sha256=rouLirxUANrcYC824MSMypXL_Qb2HYg2YZqaiEqbEKI,1768
10
10
  fastapi/cli.py,sha256=OYhZb0NR_deuT5ofyPF2NoNBzZDNOP8Salef2nk-HqA,418
11
11
  fastapi/concurrency.py,sha256=MirfowoSpkMQZ8j_g0ZxaQKpV6eB3G-dB5TgcXCrgEA,1424
12
12
  fastapi/datastructures.py,sha256=b2PEz77XGq-u3Ur1Inwk0AGjOsQZO49yF9C7IPJ15cY,5766
13
13
  fastapi/dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  fastapi/dependencies/models.py,sha256=Pjl6vx-4nZ5Tta9kJa3-RfQKkXtCpS09-FhMgs9eWNs,1507
15
- fastapi/dependencies/utils.py,sha256=zcOLg1Y0AHdoHvVbe6mrelzST8tmjFJeoaoHEK9jlyA,36867
15
+ fastapi/dependencies/utils.py,sha256=WVgX-cF_H318wOlsZSiAP2mX6-puEsx_MAQ6AHSzITE,36814
16
16
  fastapi/encoders.py,sha256=r_fOgMylrlnCDTh3W9u2W0ZsHTJqIhLpU6QipHMy0m8,11119
17
17
  fastapi/exception_handlers.py,sha256=YVcT8Zy021VYYeecgdyh5YEUjEIHKcLspbkSf4OfbJI,1275
18
18
  fastapi/exceptions.py,sha256=taNixuFEXb67lI1bnX1ubq8y8TseJ4yoPlWjyP0fTzk,4969
19
19
  fastapi/logger.py,sha256=I9NNi3ov8AcqbsbC9wl1X-hdItKgYt2XTrx1f99Zpl4,54
20
20
  fastapi/middleware/__init__.py,sha256=oQDxiFVcc1fYJUOIFvphnK7pTT5kktmfL32QXpBFvvo,58
21
+ fastapi/middleware/asyncexitstack.py,sha256=RKGlQpGzg3GLosqVhrxBy_NCZ9qJS7zQeNHt5Y3x-00,637
21
22
  fastapi/middleware/cors.py,sha256=ynwjWQZoc_vbhzZ3_ZXceoaSrslHFHPdoM52rXr0WUU,79
22
23
  fastapi/middleware/gzip.py,sha256=xM5PcsH8QlAimZw4VDvcmTnqQamslThsfe3CVN2voa0,79
23
24
  fastapi/middleware/httpsredirect.py,sha256=rL8eXMnmLijwVkH7_400zHri1AekfeBd6D6qs8ix950,115
@@ -33,12 +34,12 @@ fastapi/params.py,sha256=g450axUBQgQJODdtM7WBxZbQj9Z64inFvadrgHikBbU,28237
33
34
  fastapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
35
  fastapi/requests.py,sha256=zayepKFcienBllv3snmWI20Gk0oHNVLU4DDhqXBb4LU,142
35
36
  fastapi/responses.py,sha256=QNQQlwpKhQoIPZTTWkpc9d_QGeGZ_aVQPaDV3nQ8m7c,1761
36
- fastapi/routing.py,sha256=4zaZIdeq8VtsBLCxmmEgnfHqDD6USTc_l8BxUe1ye4M,176533
37
+ fastapi/routing.py,sha256=tK_d2K_0kP-rcbAmjjlR0mZMR170QkBITvwHWPq7eiQ,178409
37
38
  fastapi/security/__init__.py,sha256=bO8pNmxqVRXUjfl2mOKiVZLn0FpBQ61VUYVjmppnbJw,881
38
39
  fastapi/security/api_key.py,sha256=di-0gQ8MKugi2YfmlMoDHk-QMF_vnLGJRFOA6tcZ7fA,9016
39
40
  fastapi/security/base.py,sha256=dl4pvbC-RxjfbWgPtCWd8MVU-7CB2SZ22rJDXVCXO6c,141
40
41
  fastapi/security/http.py,sha256=rWR2x-5CUsjWmRucYthwRig6MG1o-boyrr4Xo-PuuxU,13606
41
- fastapi/security/oauth2.py,sha256=M1AFIDT7G3oQChq83poI3eg8ZDeibcvnGmya2CTS7JY,22036
42
+ fastapi/security/oauth2.py,sha256=rKHIUHq29367Qpe0Ez5Gcu1yIIM6SMw7nEfh15gBNIQ,22036
42
43
  fastapi/security/open_id_connect_url.py,sha256=8vizZ2tGqEp1ur8SwtVgyHJhGAJ5AqahgcvSpaIioDI,2722
43
44
  fastapi/security/utils.py,sha256=bd8T0YM7UQD5ATKucr1bNtAvz_Y3__dVNAv5UebiPvc,293
44
45
  fastapi/staticfiles.py,sha256=iirGIt3sdY2QZXd36ijs3Cj-T0FuGFda3cd90kM9Ikw,69
@@ -47,4 +48,4 @@ fastapi/testclient.py,sha256=nBvaAmX66YldReJNZXPOk1sfuo2Q6hs8bOvIaCep6LQ,66
47
48
  fastapi/types.py,sha256=nFb36sK3DSoqoyo7Miwy3meKK5UdFBgkAgLSzQlUVyI,383
48
49
  fastapi/utils.py,sha256=S59stPvKPUJ7MSkke3FaegSyig_4Uwhd32jnLiMF1jE,8032
49
50
  fastapi/websockets.py,sha256=419uncYObEKZG0YcrXscfQQYLSWoE10jqxVMetGdR98,222
50
- fastapi-0.117.0.dist-info/RECORD,,
51
+ fastapi-0.118.0.dist-info/RECORD,,