fastapi-deferred-init 0.3.0__tar.gz → 0.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastapi-deferred-init
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: Faster FastAPI start-up time for Projects with many nested routers
5
5
  Keywords: fastapi,speed,router,startup,optimization
6
6
  Author-Email: Jan Vollmer <jan@vllmr.dev>
@@ -18,7 +18,7 @@ Classifier: Typing :: Typed
18
18
  Project-URL: Source, https://github.com/jvllmr/fastapi-deferred-init
19
19
  Project-URL: Changelog, https://github.com/jvllmr/fastapi-deferred-init/releases
20
20
  Requires-Python: >=3.10
21
- Requires-Dist: fastapi>=0.137.2
21
+ Requires-Dist: fastapi>=0.140.7
22
22
  Description-Content-Type: text/markdown
23
23
 
24
24
  # fastapi-deferred-init
@@ -12,7 +12,7 @@ authors = [
12
12
  { name = "Jan Vollmer", email = "jan@vllmr.dev" },
13
13
  ]
14
14
  dependencies = [
15
- "fastapi>=0.137.2",
15
+ "fastapi>=0.140.7",
16
16
  ]
17
17
  requires-python = ">=3.10"
18
18
  readme = "README.md"
@@ -29,7 +29,7 @@ classifiers = [
29
29
  "Typing :: Typed",
30
30
  ]
31
31
  dynamic = []
32
- version = "0.3.0"
32
+ version = "0.3.2"
33
33
 
34
34
  [project.license]
35
35
  text = "MIT"
@@ -85,13 +85,13 @@ all = true
85
85
 
86
86
  [dependency-groups]
87
87
  dev = [
88
- "pytest>=9.1.0",
89
- "ruff>=0.15.17",
88
+ "pytest>=9.1.1",
89
+ "ruff>=0.15.20",
90
90
  "pre-commit>=4.3.0",
91
- "mypy>=1.20.2",
91
+ "mypy>=2.1.0",
92
92
  "tuna>=0.5.15",
93
- "httpx>=0.28.1",
94
93
  "pytest-benchmark>=5.2.3",
95
94
  "pip>=26.1.2",
96
- "inline-snapshot>=0.34.1",
95
+ "inline-snapshot>=0.34.2",
96
+ "httpx2>=2.9.1",
97
97
  ]
@@ -7,4 +7,8 @@ def apply_patch() -> None:
7
7
 
8
8
  routing._populate_api_route_state = _populate_api_route_state # ty:ignore[invalid-assignment]
9
9
  routing.APIRoute = DeferringAPIRoute # ty:ignore[invalid-assignment]
10
- routing.APIRouter = DeferringAPIRouter
10
+ routing.APIRouter = DeferringAPIRouter # ty:ignore[invalid-assignment]
11
+
12
+ import fastapi
13
+
14
+ fastapi.APIRouter = DeferringAPIRouter # type:ignore[attr-defined] # ty:ignore[invalid-assignment]
@@ -10,17 +10,18 @@ from fastapi.sse import (
10
10
  EventSourceResponse,
11
11
  ServerSentEvent,
12
12
  )
13
+ from fastapi.routing import _is_async_gen_callable, _is_gen_callable
13
14
  from fastapi import params, routing # type: ignore[attr-defined]
14
15
  from fastapi._compat import ModelField, lenient_issubclass
15
16
  from fastapi.datastructures import Default, DefaultPlaceholder
16
17
  from fastapi.dependencies.utils import (
17
18
  _should_embed_body_fields,
18
- get_body_field,
19
+ _get_body_field,
19
20
  get_dependant,
20
- get_flat_dependant,
21
21
  get_parameterless_sub_dependant,
22
22
  get_typed_return_annotation,
23
23
  get_stream_item_type,
24
+ _get_flat_body_params,
24
25
  )
25
26
  from fastapi.responses import JSONResponse, Response
26
27
  from fastapi.types import IncEx
@@ -35,11 +36,13 @@ def _add_cache_attribute(
35
36
  instance: routing._APIRouteLike, name: str, func: Callable[[Any], Any]
36
37
  ) -> None:
37
38
  cls = type(instance)
38
- if hasattr(instance, name) and (
39
- (val := getattr(instance, name)) is None or val is False
39
+
40
+ if name in instance.__dict__ and (
41
+ (val := instance.__dict__[name]) is None or val is False
40
42
  ):
41
43
  delattr(instance, name)
42
44
 
45
+ # replace attribute with cached_property
43
46
  if not hasattr(cls, name) or not isinstance(getattr(cls, name), cached_property):
44
47
  prop = cached_property(func)
45
48
  setattr(cls, name, prop)
@@ -212,20 +215,20 @@ def _populate_api_route_state(
212
215
 
213
216
  _add_cache_attribute(route, "dependant", _get_dependant)
214
217
 
215
- def _get_flat_dependant(self) -> Dependant:
216
- return get_flat_dependant(self.dependant)
218
+ def _flat_body_params(self) -> list[ModelField]:
219
+ return _get_flat_body_params(self.dependant)
217
220
 
218
- _add_cache_attribute(route, "_flat_dependant", _get_flat_dependant)
221
+ _add_cache_attribute(route, "_flat_body_params", _flat_body_params)
219
222
 
220
223
  def _embed_body_fields(self):
221
- return _should_embed_body_fields(self._flat_dependant.body_params)
224
+ return _should_embed_body_fields(self._flat_body_params)
222
225
 
223
226
  _add_cache_attribute(route, "_embed_body_fields", _embed_body_fields)
224
227
 
225
228
  def _body_field(self):
226
- return get_body_field(
227
- flat_dependant=self._flat_dependant,
229
+ return _get_body_field(
228
230
  name=self.unique_id,
231
+ body_params=self._flat_body_params,
229
232
  embed_body_fields=self._embed_body_fields,
230
233
  )
231
234
 
@@ -233,7 +236,9 @@ def _populate_api_route_state(
233
236
 
234
237
  # Detect generator endpoints that should stream as JSONL or SSE
235
238
  def _is_generator(self) -> bool:
236
- return self.dependant.is_async_gen_callable or self.dependant.is_gen_callable
239
+ return _is_async_gen_callable(self.dependant.call) or _is_gen_callable(
240
+ self.dependant.call
241
+ )
237
242
 
238
243
  _add_cache_attribute(route, "is_generator", _is_generator)
239
244
 
@@ -3,7 +3,7 @@ import os
3
3
  import pytest
4
4
  from pydantic import BaseModel
5
5
 
6
- from fastapi import FastAPI
6
+ from fastapi import FastAPI, APIRouter
7
7
  from fastapi import routing
8
8
  from fastapi.testclient import TestClient
9
9
  from fastapi_deferred_init.routing import (
@@ -27,9 +27,7 @@ def apply_monkeypatch(monkeypatch):
27
27
  )
28
28
  monkeypatch.setattr("fastapi.routing.APIRoute", DeferringAPIRoute)
29
29
  monkeypatch.setattr("fastapi.routing.APIRouter", DeferringAPIRouter)
30
- # monkeypatch.setattr(
31
- # "fastapi.APIRouter", DeferringAPIRouter
32
- # )
30
+ monkeypatch.setattr("fastapi.APIRouter", DeferringAPIRouter)
33
31
 
34
32
 
35
33
  @pytest.mark.parametrize(["use_lib"], [(True,), (False,)])
@@ -42,7 +40,7 @@ def test_basic(use_lib: bool, benchmark, monkeypatch):
42
40
  )
43
41
 
44
42
  generated_code = benchmark(load_code)
45
-
43
+ assert generated_code.APIRouter is (DeferringAPIRouter if use_lib else APIRouter)
46
44
  app = FastAPI()
47
45
  router = generated_code.router
48
46