fastapi-extra 0.2.5__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/PKG-INFO +3 -3
  2. fastapi_extra-0.3.0/fastapi_extra/__init__.py +17 -0
  3. fastapi_extra-0.3.0/fastapi_extra/_patch.py +33 -0
  4. fastapi_extra-0.3.0/fastapi_extra/native/urlparse.pyx +50 -0
  5. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/response.py +15 -1
  6. fastapi_extra-0.3.0/fastapi_extra/urlparse.pyi +11 -0
  7. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra.egg-info/PKG-INFO +3 -3
  8. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra.egg-info/SOURCES.txt +5 -1
  9. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra.egg-info/requires.txt +2 -2
  10. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/pyproject.toml +4 -3
  11. fastapi_extra-0.2.5/fastapi_extra/__init__.py +0 -13
  12. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/LICENSE +0 -0
  13. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/README.rst +0 -0
  14. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/cache/__init__.py +0 -0
  15. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/cache/redis.py +0 -0
  16. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/cursor.pyi +0 -0
  17. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/database/__init__.py +0 -0
  18. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/database/model.py +0 -0
  19. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/database/service.py +0 -0
  20. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/database/session.py +0 -0
  21. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/dependency.py +0 -0
  22. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/form.py +0 -0
  23. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/native/cursor.pyx +0 -0
  24. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/native/routing.pyx +0 -0
  25. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/py.typed +0 -0
  26. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/routing.pyi +0 -0
  27. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/settings.py +0 -0
  28. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/types.py +0 -0
  29. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra/utils.py +0 -0
  30. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra.egg-info/dependency_links.txt +0 -0
  31. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/fastapi_extra.egg-info/top_level.txt +0 -0
  32. {fastapi_extra-0.2.5 → fastapi_extra-0.3.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-extra
3
- Version: 0.2.5
3
+ Version: 0.3.0
4
4
  Summary: extra package for fastapi.
5
5
  Author-email: Ziyan Yin <408856732@qq.com>
6
6
  License: BSD-3-Clause
@@ -18,9 +18,9 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
18
  Requires-Python: >=3.12
19
19
  Description-Content-Type: text/x-rst
20
20
  License-File: LICENSE
21
- Requires-Dist: fastapi<0.116.0,>=0.115.0
21
+ Requires-Dist: fastapi<0.129.0,>=0.128.0
22
22
  Requires-Dist: httpx<0.29.0,>=0.28.0
23
- Requires-Dist: pydantic-settings>=2.7.0
23
+ Requires-Dist: pydantic-settings>=2.12.0
24
24
  Requires-Dist: sqlmodel>=0.0.22
25
25
  Provides-Extra: redis
26
26
  Requires-Dist: redis; extra == "redis"
@@ -0,0 +1,17 @@
1
+ __version__ = "0.3.0"
2
+
3
+
4
+ from fastapi import FastAPI
5
+ from fastapi import routing as origin_routing
6
+ from fastapi.dependencies import utils as origin_utils
7
+
8
+
9
+ def setup(app: FastAPI) -> None:
10
+ try:
11
+ from fastapi_extra import _patch
12
+
13
+ _patch.install_routes(app)
14
+ origin_routing.solve_dependencies.__globals__['is_sequence_field'] = _patch.is_sequence_field # type: ignore
15
+ origin_utils.QueryParams.__init__ = _patch.query_params_init # type: ignore
16
+ except ImportError: # pragma: nocover
17
+ pass
@@ -0,0 +1,33 @@
1
+ __author__ = "ziyan.yin"
2
+ __date__ = "2026-01-13"
3
+
4
+
5
+ from fastapi import FastAPI
6
+ from fastapi._compat import v2
7
+ from starlette import datastructures
8
+
9
+ from fastapi_extra import routing
10
+ from fastapi_extra.urlparse import parse_qsl
11
+
12
+
13
+ def install_routes(app: FastAPI) -> None:
14
+ routing.install(app)
15
+
16
+
17
+ def is_sequence_field(field: v2.ModelField) -> bool:
18
+ if not hasattr(field, "_is_sequence"):
19
+ setattr(field, "_is_sequence", v2.is_sequence_field(field))
20
+ return getattr(field, "_is_sequence")
21
+
22
+
23
+ def query_params_init(obj: datastructures.QueryParams, *args, **kwargs) -> None:
24
+ value = args[0] if args else []
25
+
26
+ if isinstance(value, bytes):
27
+ super(datastructures.QueryParams, obj).__init__(parse_qsl(value, keep_blank_values=True), **kwargs)
28
+ elif isinstance(value, str):
29
+ super(datastructures.QueryParams, obj).__init__(parse_qsl(value.encode("latin-1"), keep_blank_values=True), **kwargs)
30
+ else:
31
+ super(datastructures.QueryParams, obj).__init__(*args, **kwargs) # type: ignore[arg-type]
32
+ obj._list = [(str(k), str(v)) for k, v in obj._list]
33
+ obj._dict = {str(k): str(v) for k, v in obj._dict.items()}
@@ -0,0 +1,50 @@
1
+ __author__ = "ziyan.yin"
2
+ __describe__ = ""
3
+
4
+
5
+ from libc.stdlib cimport strtol
6
+ from libc.string cimport memmove, strlen
7
+
8
+
9
+ cdef inline size_t _unquote(char* c_string, bint change_plus):
10
+ cdef:
11
+ int i = 0
12
+ char[2] quote
13
+ size_t n = strlen(c_string)
14
+
15
+ while i < n:
16
+ if c_string[i] == '+' and change_plus:
17
+ c_string[i] = ' '
18
+ elif c_string[i] == '%':
19
+ quote[0] = c_string[i + 1]
20
+ quote[1] = c_string[i + 2]
21
+ c_string[i] = strtol(quote, NULL, 16)
22
+ memmove(c_string + i + 1, c_string + i + 3, n - i - 2)
23
+ n -= 2
24
+ i += 1
25
+ return n
26
+
27
+
28
+ def unquote(val: bytes, encoding: str = "utf-8") -> str:
29
+ return val[:_unquote(val, 0)].decode(encoding)
30
+
31
+
32
+ def unquote_plus(val: bytes, encoding: str = "utf-8") -> str:
33
+ return val[:_unquote(val, 1)].decode(encoding)
34
+
35
+
36
+ def parse_qsl(qs: bytes, keep_blank_values: bool = False) -> list[tuple[str, str]]:
37
+ query_args = qs.split(b'&') if qs else []
38
+ r = []
39
+ for name_value in query_args:
40
+ if not name_value:
41
+ continue
42
+ nv = name_value.split(b'=')
43
+ if len(nv) < 2:
44
+ if not keep_blank_values:
45
+ continue
46
+ nv.append(b'')
47
+ name = unquote_plus(nv[0])
48
+ value = unquote_plus(nv[1])
49
+ r.append((name, value))
50
+ return r
@@ -3,7 +3,7 @@ __date__ = "2024-12-24"
3
3
 
4
4
 
5
5
  from enum import Enum
6
- from typing import TYPE_CHECKING, Generic
6
+ from typing import TYPE_CHECKING, Generic, Mapping
7
7
 
8
8
  from fastapi.responses import JSONResponse
9
9
  from pydantic import BaseModel, Field
@@ -220,6 +220,20 @@ class APIResponse(JSONResponse):
220
220
  exclude_none=False,
221
221
  exclude_unset=False,
222
222
  )
223
+
224
+ def init_headers(self, headers: Mapping[str, str] | None = None) -> None:
225
+ self.raw_headers = [
226
+ (b"content-length", str(len(self.body)).encode("latin-1")),
227
+ (b"content-type", b"application/json; charset=utf-8"),
228
+ ]
229
+ if headers:
230
+ raw_headers = [
231
+ (k.lower().encode("latin-1"), v.encode("latin-1"))
232
+ for k, v in headers.items() if k not in ("content-length", "content-type")
233
+ ]
234
+ self.raw_headers.extend(raw_headers)
235
+
236
+
223
237
 
224
238
 
225
239
  class APIError(Exception):
@@ -0,0 +1,11 @@
1
+ __author__ = "ziyan.yin"
2
+ __describe__ = ""
3
+
4
+
5
+ def unquote(val: bytes, encoding: str = "utf-8") -> str: ...
6
+
7
+
8
+ def unquote_plus(val: bytes, encoding: str = "utf-8") -> str: ...
9
+
10
+
11
+ def parse_qsl(qs: bytes, keep_blank_values: bool = False) -> list[tuple[str, str]]: ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-extra
3
- Version: 0.2.5
3
+ Version: 0.3.0
4
4
  Summary: extra package for fastapi.
5
5
  Author-email: Ziyan Yin <408856732@qq.com>
6
6
  License: BSD-3-Clause
@@ -18,9 +18,9 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
18
  Requires-Python: >=3.12
19
19
  Description-Content-Type: text/x-rst
20
20
  License-File: LICENSE
21
- Requires-Dist: fastapi<0.116.0,>=0.115.0
21
+ Requires-Dist: fastapi<0.129.0,>=0.128.0
22
22
  Requires-Dist: httpx<0.29.0,>=0.28.0
23
- Requires-Dist: pydantic-settings>=2.7.0
23
+ Requires-Dist: pydantic-settings>=2.12.0
24
24
  Requires-Dist: sqlmodel>=0.0.22
25
25
  Provides-Extra: redis
26
26
  Requires-Dist: redis; extra == "redis"
@@ -2,6 +2,7 @@ LICENSE
2
2
  README.rst
3
3
  pyproject.toml
4
4
  fastapi_extra/__init__.py
5
+ fastapi_extra/_patch.py
5
6
  fastapi_extra/cursor.pyi
6
7
  fastapi_extra/dependency.py
7
8
  fastapi_extra/form.py
@@ -10,6 +11,7 @@ fastapi_extra/response.py
10
11
  fastapi_extra/routing.pyi
11
12
  fastapi_extra/settings.py
12
13
  fastapi_extra/types.py
14
+ fastapi_extra/urlparse.pyi
13
15
  fastapi_extra/utils.py
14
16
  fastapi_extra.egg-info/PKG-INFO
15
17
  fastapi_extra.egg-info/SOURCES.txt
@@ -18,6 +20,7 @@ fastapi_extra.egg-info/requires.txt
18
20
  fastapi_extra.egg-info/top_level.txt
19
21
  fastapi_extra/native/cursor.pyx
20
22
  fastapi_extra/native/routing.pyx
23
+ fastapi_extra/native/urlparse.pyx
21
24
  fastapi_extra/cache/__init__.py
22
25
  fastapi_extra/cache/redis.py
23
26
  fastapi_extra/database/__init__.py
@@ -25,4 +28,5 @@ fastapi_extra/database/model.py
25
28
  fastapi_extra/database/service.py
26
29
  fastapi_extra/database/session.py
27
30
  fastapi_extra/native/cursor.pyx
28
- fastapi_extra/native/routing.pyx
31
+ fastapi_extra/native/routing.pyx
32
+ fastapi_extra/native/urlparse.pyx
@@ -1,6 +1,6 @@
1
- fastapi<0.116.0,>=0.115.0
1
+ fastapi<0.129.0,>=0.128.0
2
2
  httpx<0.29.0,>=0.28.0
3
- pydantic-settings>=2.7.0
3
+ pydantic-settings>=2.12.0
4
4
  sqlmodel>=0.0.22
5
5
 
6
6
  [aiomysql]
@@ -30,9 +30,9 @@ classifiers = [
30
30
  "Topic :: Software Development :: Libraries :: Python Modules"
31
31
  ]
32
32
  dependencies = [
33
- "fastapi>=0.115.0,<0.116.0",
33
+ "fastapi>=0.128.0,<0.129.0",
34
34
  "httpx>=0.28.0,<0.29.0",
35
- "pydantic-settings>=2.7.0",
35
+ "pydantic-settings>=2.12.0",
36
36
  "sqlmodel>=0.0.22",
37
37
  ]
38
38
 
@@ -47,7 +47,8 @@ aiomysql = ["aiomysql"]
47
47
  packages = ["fastapi_extra", "fastapi_extra.database", "fastapi_extra.cache"]
48
48
  ext-modules = [
49
49
  { name = "fastapi_extra.cursor", sources = ["fastapi_extra/native/cursor.pyx"] },
50
- { name = "fastapi_extra.routing", sources = ["fastapi_extra/native/routing.pyx"] }
50
+ { name = "fastapi_extra.routing", sources = ["fastapi_extra/native/routing.pyx"] },
51
+ { name = "fastapi_extra.urlparse", sources = ["fastapi_extra/native/urlparse.pyx"] }
51
52
  ]
52
53
 
53
54
  [tool.setuptools.dynamic]
@@ -1,13 +0,0 @@
1
- __version__ = "0.2.5"
2
-
3
-
4
- from fastapi import FastAPI
5
-
6
-
7
- def setup(app: FastAPI) -> None:
8
- try:
9
- from fastapi_extra import routing as native_routing # type: ignore
10
-
11
- native_routing.install(app)
12
- except ImportError: # pragma: nocover
13
- pass
File without changes
File without changes
File without changes