asgi-tools 1.1.0__cp311-cp311-musllinux_1_2_aarch64.whl → 1.3.1__cp311-cp311-musllinux_1_2_aarch64.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.
asgi_tools/tests.py CHANGED
@@ -22,13 +22,10 @@ from typing import (
22
22
  Callable,
23
23
  Coroutine,
24
24
  Deque,
25
- Optional,
26
- Union,
27
25
  cast,
28
26
  )
29
27
  from urllib.parse import urlencode
30
28
 
31
- from multidict import MultiDict
32
29
  from yarl import URL
33
30
 
34
31
  from ._compat import aio_cancel, aio_sleep, aio_spawn, aio_timeout, aio_wait
@@ -38,6 +35,8 @@ from .response import Response, ResponseJSON, ResponseWebSocket, parse_websocket
38
35
  from .utils import CIMultiDict, parse_headers
39
36
 
40
37
  if TYPE_CHECKING:
38
+ from multidict import MultiDict
39
+
41
40
  from .types import TJSON, TASGIApp, TASGIMessage, TASGIReceive, TASGIScope, TASGISend
42
41
 
43
42
 
@@ -53,7 +52,7 @@ class TestResponse(Response):
53
52
  msg = await self._receive()
54
53
  assert msg.get("type") == "http.response.start", "Invalid Response"
55
54
  self.status_code = int(msg.get("status", 502))
56
- self.headers = cast(MultiDict, parse_headers(msg.get("headers", [])))
55
+ self.headers = cast("MultiDict", parse_headers(msg.get("headers", [])))
57
56
  self.content_type = self.headers.get("content-type")
58
57
  for cookie in self.headers.getall("set-cookie", []):
59
58
  self.cookies.load(cookie)
@@ -123,7 +122,7 @@ class TestWebSocketResponse(ResponseWebSocket):
123
122
 
124
123
 
125
124
  class ASGITestClient:
126
- """The test client allows you to make requests against an ASGI application.
125
+ """Built-in test client for ASGI applications.
127
126
 
128
127
  Features:
129
128
 
@@ -151,10 +150,10 @@ class ASGITestClient:
151
150
  path: str,
152
151
  method: str = "GET",
153
152
  *,
154
- query: Union[str, dict] = "",
155
- headers: Optional[dict[str, str]] = None,
156
- cookies: Optional[dict[str, str]] = None,
157
- data: Union[bytes, str, dict, AsyncGenerator[Any, bytes]] = b"",
153
+ query: str | dict = "",
154
+ headers: dict[str, str] | None = None,
155
+ cookies: dict[str, str] | None = None,
156
+ data: bytes | str | dict | AsyncGenerator[Any, bytes] = b"",
158
157
  json: TJSON = None,
159
158
  follow_redirect: bool = True,
160
159
  timeout: float = 10.0,
@@ -214,9 +213,9 @@ class ASGITestClient:
214
213
  async def websocket(
215
214
  self,
216
215
  path: str,
217
- query: Union[str, dict, None] = None,
218
- headers: Optional[dict] = None,
219
- cookies: Optional[dict] = None,
216
+ query: str | dict | None = None,
217
+ headers: dict | None = None,
218
+ cookies: dict | None = None,
220
219
  ):
221
220
  """Connect to a websocket."""
222
221
  pipe = Pipe()
@@ -250,9 +249,9 @@ class ASGITestClient:
250
249
  def build_scope(
251
250
  self,
252
251
  path: str,
253
- headers: Union[dict, CIMultiDict, None] = None,
254
- query: Union[str, dict, None] = None,
255
- cookies: Optional[dict] = None,
252
+ headers: dict | CIMultiDict | None = None,
253
+ query: str | dict | None = None,
254
+ cookies: dict | None = None,
256
255
  **scope,
257
256
  ) -> TASGIScope:
258
257
  """Prepare a request scope."""
@@ -282,7 +281,7 @@ class ASGITestClient:
282
281
  "query_string": url.raw_query_string.encode(),
283
282
  "raw_path": url.raw_path.encode(),
284
283
  "root_path": "",
285
- "scheme": scope.get("type") == "http" and self.base_url.scheme or "ws",
284
+ "scheme": (scope.get("type") == "http" and self.base_url.scheme) or "ws",
286
285
  "headers": [
287
286
  (key.lower().encode(BASE_ENCODING), str(val).encode(BASE_ENCODING))
288
287
  for key, val in (headers or {}).items()
@@ -321,11 +320,11 @@ def encode_multipart(data: dict) -> tuple[bytes, str]:
321
320
 
322
321
  class Pipe:
323
322
  __slots__ = (
324
- "delay",
325
323
  "app_is_closed",
326
- "client_is_closed",
327
324
  "app_queue",
325
+ "client_is_closed",
328
326
  "client_queue",
327
+ "delay",
329
328
  )
330
329
 
331
330
  def __init__(self, delay: float = 1e-3):
@@ -366,7 +365,7 @@ class Pipe:
366
365
  await aio_sleep(self.delay)
367
366
  return self.app_queue.popleft()
368
367
 
369
- async def stream(self, data: Union[bytes, AsyncGenerator[Any, bytes]]):
368
+ async def stream(self, data: bytes | AsyncGenerator[Any, bytes]):
370
369
  if isinstance(data, bytes):
371
370
  return await self.send_to_app(
372
371
  {"type": "http.request", "body": data, "more_body": False},
@@ -392,7 +391,7 @@ async def manage_lifespan(app, timeout: float = 3e-2):
392
391
  async with aio_spawn(safe_spawn) as task:
393
392
  await pipe.send_to_app({"type": "lifespan.startup"})
394
393
 
395
- with suppress(TimeoutError, asyncio.TimeoutError): # python 39, 310
394
+ with suppress(TimeoutError, asyncio.TimeoutError): # python 310
396
395
  async with aio_timeout(timeout):
397
396
  msg = await pipe.receive_from_client()
398
397
  if msg["type"] == "lifespan.startup.failed":
@@ -401,6 +400,6 @@ async def manage_lifespan(app, timeout: float = 3e-2):
401
400
  yield
402
401
 
403
402
  await pipe.send_to_app({"type": "lifespan.shutdown"})
404
- with suppress(TimeoutError, asyncio.TimeoutError): # python 39, 310
403
+ with suppress(TimeoutError, asyncio.TimeoutError): # python 310
405
404
  async with aio_timeout(timeout):
406
405
  await pipe.receive_from_client()
asgi_tools/view.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import inspect
4
- from typing import TYPE_CHECKING, Final, Optional
4
+ from typing import TYPE_CHECKING, Final
5
5
 
6
6
  if TYPE_CHECKING:
7
7
  from collections.abc import Awaitable
@@ -57,7 +57,7 @@ class HTTPView:
57
57
  return self(request, **opts)
58
58
 
59
59
  @classmethod
60
- def __route__(cls, router: Router, *paths: str, methods: Optional[TMethods] = None, **params):
60
+ def __route__(cls, router: Router, *paths: str, methods: TMethods | None = None, **params):
61
61
  """Bind the class view to the given router."""
62
62
  view_methods = dict(inspect.getmembers(cls, inspect.isfunction))
63
63
  methods = methods or [m for m in HTTP_METHODS if m.lower() in view_methods]
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: asgi-tools
3
- Version: 1.1.0
3
+ Version: 1.3.1
4
4
  Summary: ASGI Toolkit to build web applications
5
5
  Author-email: Kirill Klenov <horneds@gmail.com>
6
6
  License: MIT License
@@ -13,7 +13,6 @@ Classifier: Intended Audience :: Developers
13
13
  Classifier: License :: OSI Approved :: MIT License
14
14
  Classifier: Programming Language :: Python
15
15
  Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.9
17
16
  Classifier: Programming Language :: Python :: 3.10
18
17
  Classifier: Programming Language :: Python :: 3.11
19
18
  Classifier: Programming Language :: Python :: 3.12
@@ -23,41 +22,42 @@ Classifier: Programming Language :: Cython
23
22
  Classifier: Topic :: Internet :: WWW/HTTP
24
23
  Classifier: Framework :: AsyncIO
25
24
  Classifier: Framework :: Trio
26
- Requires-Python: >=3.9
25
+ Requires-Python: >=3.10
27
26
  Description-Content-Type: text/x-rst
28
27
  License-File: LICENSE
29
28
  Requires-Dist: http-router>=4.0.0
30
- Requires-Dist: multidict
29
+ Requires-Dist: multidict>=6.6.3
31
30
  Requires-Dist: sniffio
32
31
  Requires-Dist: yarl>=1.8.2
33
32
  Requires-Dist: async-timeout; python_version < "3.11"
34
- Provides-Extra: dev
35
- Requires-Dist: bump2version; extra == "dev"
36
- Requires-Dist: tox; extra == "dev"
37
- Requires-Dist: cython; extra == "dev"
38
- Requires-Dist: pre-commit; extra == "dev"
39
- Requires-Dist: sphinx; extra == "dev"
40
- Requires-Dist: pydata-sphinx-theme; extra == "dev"
41
- Provides-Extra: examples
42
- Requires-Dist: uvicorn[standard]; extra == "examples"
43
- Requires-Dist: jinja2; extra == "examples"
44
- Requires-Dist: httpx; extra == "examples"
45
- Provides-Extra: orjson
46
- Requires-Dist: orjson; extra == "orjson"
47
33
  Provides-Extra: tests
48
34
  Requires-Dist: aiofile; extra == "tests"
49
35
  Requires-Dist: pytest; extra == "tests"
50
- Requires-Dist: pytest-aio[curio,trio]>=1.1.0; extra == "tests"
36
+ Requires-Dist: pytest-aio[curio,trio]>=1.3.1; extra == "tests"
51
37
  Requires-Dist: pytest-benchmark; extra == "tests"
52
38
  Requires-Dist: PyYAML; extra == "tests"
53
39
  Requires-Dist: ruff; extra == "tests"
54
40
  Requires-Dist: mypy; extra == "tests"
41
+ Requires-Dist: exceptiongroup; python_version < "3.11" and extra == "tests"
55
42
  Requires-Dist: ujson; implementation_name == "cpython" and extra == "tests"
56
43
  Requires-Dist: uvloop; implementation_name == "cpython" and extra == "tests"
57
44
  Requires-Dist: pytest-mypy; implementation_name == "cpython" and extra == "tests"
58
- Requires-Dist: exceptiongroup; python_version < "3.11" and extra == "tests"
59
45
  Provides-Extra: ujson
60
46
  Requires-Dist: ujson; extra == "ujson"
47
+ Provides-Extra: orjson
48
+ Requires-Dist: orjson; extra == "orjson"
49
+ Provides-Extra: examples
50
+ Requires-Dist: uvicorn[standard]; extra == "examples"
51
+ Requires-Dist: jinja2; extra == "examples"
52
+ Requires-Dist: httpx; extra == "examples"
53
+ Provides-Extra: dev
54
+ Requires-Dist: bump2version; extra == "dev"
55
+ Requires-Dist: tox; extra == "dev"
56
+ Requires-Dist: cython; extra == "dev"
57
+ Requires-Dist: pre-commit; extra == "dev"
58
+ Requires-Dist: sphinx; extra == "dev"
59
+ Requires-Dist: pydata-sphinx-theme; extra == "dev"
60
+ Dynamic: license-file
61
61
 
62
62
  .. image:: https://raw.githubusercontent.com/klen/asgi-tools/develop/.github/assets/asgi-tools.png
63
63
  :height: 100
@@ -124,7 +124,7 @@ For instance these middlewares were built with the library:
124
124
  Requirements
125
125
  =============
126
126
 
127
- - python >= 3.9
127
+ - python >= 3.10
128
128
 
129
129
  .. note:: pypy3 is also supported
130
130
 
@@ -145,7 +145,7 @@ A Quick Example
145
145
 
146
146
  You can use any of ASGI-Tools components independently.
147
147
 
148
- Dispite this ASGI-Tools contains App_ helper to quickly build ASGI
148
+ Despite this ASGI-Tools contains App_ helper to quickly build ASGI
149
149
  applications. For instance:
150
150
 
151
151
  Save this to ``app.py``.
@@ -201,7 +201,7 @@ Licensed under a `MIT license`_.
201
201
  .. _klen: https://github.com/klen
202
202
  .. _uvicorn: http://www.uvicorn.org/
203
203
  .. _daphne: https://github.com/django/daphne/
204
- .. _hypercorn: https://pgjones.gitlab.io/hypercorn/
204
+ .. _hypercorn: https://github.com/pgjones/hypercorn/
205
205
 
206
206
  .. _Request: https://klen.github.io/asgi-tools/api.html#request
207
207
  .. _Response: https://klen.github.io/asgi-tools/api.html#responses
@@ -0,0 +1,29 @@
1
+ asgi_tools/__init__.py,sha256=tBnlggb3FJPK8tDrnpC580OfbQ0QpuKFRdyfxmIeu8w,1428
2
+ asgi_tools/_compat.py,sha256=3BTsysYhxa0itJzCWnzpnE-HuYGs7vXzZRgQRei0IW4,7483
3
+ asgi_tools/app.py,sha256=OEkoRszSRJ9bwWQ3SKWm3Pv-R0B8uKcP9ciYsDMyCGg,10790
4
+ asgi_tools/constants.py,sha256=B7fJabLdpSE4COX0vAudyC32xV0dSpLgg0kob-FlCkE,128
5
+ asgi_tools/errors.py,sha256=TTAtJL5w2EVm9dVNK2pqNBRWM1lGJXg7HnJTibjgkes,550
6
+ asgi_tools/forms.c,sha256=v7t7ia5JTU68Eg1weG353v2IKfjQf_jTKUBSDmg8pgQ,826881
7
+ asgi_tools/forms.cpython-311-aarch64-linux-musl.so,sha256=kiLaI2rHxpns6LAEbVwWFVlccnXMpnQ2yvpwhy8Cj_4,1102816
8
+ asgi_tools/forms.py,sha256=ers1A52YEAO1TBYWJP73K6q6jArNU7QbV0LjTlpKdeM,5059
9
+ asgi_tools/forms.pyx,sha256=ol1iEXDwS--9vNIoxFFvcTRvzUF14gQC3SDWW9K5-k8,5340
10
+ asgi_tools/logs.py,sha256=FaXJF5UYClU-JdqLL7VANxQ8O-eYAEemt0Zc_GaEC60,148
11
+ asgi_tools/middleware.py,sha256=_hTALpm3Gv_3ssCyZfInzuFC8onNz2ZFVrDCdgOcnF8,15148
12
+ asgi_tools/multipart.c,sha256=EY4Z9r8PmtB-EuV7mI1evcyEGOFpKZCT-KeE5GPH2II,844007
13
+ asgi_tools/multipart.cpython-311-aarch64-linux-musl.so,sha256=0h38eHERm-bsHQTD5RCEBKcqpI7n8KQF49t4xo25_Vg,875704
14
+ asgi_tools/multipart.pxd,sha256=bPnRLYuBw51OX7v-SZTOgOpb4PxM1MtR5dGWVoymX3A,725
15
+ asgi_tools/multipart.py,sha256=8RkJm9JIjyjR7z2OIhYg8fgLKq21HBWCMEOwbhx-3GA,21707
16
+ asgi_tools/multipart.pyx,sha256=pq-DzmAaRhS0yMJIFPNI-GP7OjJUt4k3Y8vMbXJOpKk,21929
17
+ asgi_tools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ asgi_tools/request.py,sha256=s-CqT9JI-aPZz46YtKyvSDR7CfLxEhPrIuH9OG6npzk,10802
19
+ asgi_tools/response.py,sha256=-oePnVs5_lAjZWBgcVbdnhuStHMJoqnaqYS1Dqw3rFU,18494
20
+ asgi_tools/router.py,sha256=1MCF5QLfYPWZH10AuXMRN0rTMTyQWciDSh3owgsFhk4,440
21
+ asgi_tools/tests.py,sha256=elUGlBE8qklBzKAov1x1i0eVHfkFLzj5Oifd6_JjHv4,12944
22
+ asgi_tools/types.py,sha256=QWmrnhqc_jEUaXUcMm5iMpxpd6vrTcCnlq4O9moKANg,926
23
+ asgi_tools/utils.py,sha256=6qNwZbUsKatg75Gi1ltRsAeJhBaf1gwJkuR0LemitRw,2813
24
+ asgi_tools/view.py,sha256=DO0Lr8euP98kMicDwmZLcbMpJ-Hzbhl3vYFYqAXpisw,1925
25
+ asgi_tools-1.3.1.dist-info/METADATA,sha256=TRU5h3XpsqQiez8jDNuws_Vtwt_HGl9q7fifjNvXHdg,7139
26
+ asgi_tools-1.3.1.dist-info/WHEEL,sha256=LNZuceeFd58B9QVekwESAWqB09LEv_tgGDcYQrpkG9U,113
27
+ asgi_tools-1.3.1.dist-info/top_level.txt,sha256=-6i6ebKuJ0cSaXJ3KWPmJLKUbmBE2UsuA2b7BcZMJSk,11
28
+ asgi_tools-1.3.1.dist-info/RECORD,,
29
+ asgi_tools-1.3.1.dist-info/licenses/LICENSE,sha256=ytogAgYcPT6gWj8aRc-cZwhSq9Y3wOzG-4KteKCyQOw,1070
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp311-cp311-musllinux_1_2_aarch64
5
5
 
@@ -1,29 +0,0 @@
1
- asgi_tools/app.py,sha256=zMg_R3lAnpzWfHzWkByR2msG9wKZAtECxEbtyJR_h8s,8111
2
- asgi_tools/errors.py,sha256=TTAtJL5w2EVm9dVNK2pqNBRWM1lGJXg7HnJTibjgkes,550
3
- asgi_tools/utils.py,sha256=6qNwZbUsKatg75Gi1ltRsAeJhBaf1gwJkuR0LemitRw,2813
4
- asgi_tools/multipart.pyx,sha256=pq-DzmAaRhS0yMJIFPNI-GP7OjJUt4k3Y8vMbXJOpKk,21929
5
- asgi_tools/multipart.pxd,sha256=bPnRLYuBw51OX7v-SZTOgOpb4PxM1MtR5dGWVoymX3A,725
6
- asgi_tools/constants.py,sha256=B7fJabLdpSE4COX0vAudyC32xV0dSpLgg0kob-FlCkE,128
7
- asgi_tools/request.py,sha256=1wJ6wq_lZaVxicu1YDSLwszfuZ4iyYa6z3FV2VLw0eg,10433
8
- asgi_tools/__init__.py,sha256=ULbf6SyqMpqP_eKw8YvY45QjujIdDpSuYtaX8Gi12tU,1413
9
- asgi_tools/forms.c,sha256=0ONEEyzmLpS6MgbeLDz5D4dBEdBSsXpHNcpM8zHW_pU,816245
10
- asgi_tools/multipart.cpython-311-aarch64-linux-musl.so,sha256=BIDX9aROJ5zTAAF29-0h3OYkfIQ9jBdlzAUnELj7Nx4,883656
11
- asgi_tools/multipart.py,sha256=LNQzATAogrLEmr6Iu6ofRPbjoFZbIdyC1WeLyxxcMHA,21730
12
- asgi_tools/forms.py,sha256=r9J0suEl3GEuHX-MJUF-WT3lzyUZ69l3aQZOmbc9e_U,5091
13
- asgi_tools/forms.cpython-311-aarch64-linux-musl.so,sha256=5E-AmihsnaH8EYy0IHQlLkjCLwEmA12OdlfCvnJAnEY,1087096
14
- asgi_tools/types.py,sha256=QWmrnhqc_jEUaXUcMm5iMpxpd6vrTcCnlq4O9moKANg,926
15
- asgi_tools/forms.pyx,sha256=ol1iEXDwS--9vNIoxFFvcTRvzUF14gQC3SDWW9K5-k8,5340
16
- asgi_tools/router.py,sha256=1MCF5QLfYPWZH10AuXMRN0rTMTyQWciDSh3owgsFhk4,440
17
- asgi_tools/tests.py,sha256=xYDwDKooByo2b3DN7J1g4-rwzv9XAQ7hp_Bou-vhHM0,13043
18
- asgi_tools/_compat.py,sha256=VHX73I6sKdhb0LyhShOddDNg5FlUZqODPFsQWlpZvTA,7523
19
- asgi_tools/view.py,sha256=EgCWRjwO5IZ_VAK8s2FAK2yLLaAb9pQ4SNopIdST35U,1938
20
- asgi_tools/response.py,sha256=UnZFWhiWGr5cxDGgu2l65xAez3NITjSOCyir_9gyFoo,18865
21
- asgi_tools/middleware.py,sha256=1gvvV7v4lO6LceqP36bZFpFvb-hEfSAvyH2_IzahKes,15003
22
- asgi_tools/logs.py,sha256=FaXJF5UYClU-JdqLL7VANxQ8O-eYAEemt0Zc_GaEC60,148
23
- asgi_tools/multipart.c,sha256=biO6lYLL8Op7_Nzkg3CVt3Lrz6Bfl5Td5Z-KTMc_tlI,810039
24
- asgi_tools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
- asgi_tools-1.1.0.dist-info/top_level.txt,sha256=-6i6ebKuJ0cSaXJ3KWPmJLKUbmBE2UsuA2b7BcZMJSk,11
26
- asgi_tools-1.1.0.dist-info/RECORD,,
27
- asgi_tools-1.1.0.dist-info/LICENSE,sha256=ytogAgYcPT6gWj8aRc-cZwhSq9Y3wOzG-4KteKCyQOw,1070
28
- asgi_tools-1.1.0.dist-info/METADATA,sha256=3O8KNeCEsQLDBlXEm_3Bc2YQhgGYJ2AKiThvLC_6AXg,7157
29
- asgi_tools-1.1.0.dist-info/WHEEL,sha256=pNINGj68sk8zD_kNxY0_9AsMQ9h5X9DWGoat2OIWBbY,113