asgiref 3.9.0__tar.gz → 3.9.1__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.
- {asgiref-3.9.0/asgiref.egg-info → asgiref-3.9.1}/PKG-INFO +1 -1
- asgiref-3.9.1/asgiref/__init__.py +1 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref/local.py +14 -15
- {asgiref-3.9.0 → asgiref-3.9.1/asgiref.egg-info}/PKG-INFO +1 -1
- {asgiref-3.9.0 → asgiref-3.9.1}/tests/test_garbage_collection.py +6 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/tests/test_local.py +16 -0
- asgiref-3.9.0/asgiref/__init__.py +0 -1
- {asgiref-3.9.0 → asgiref-3.9.1}/LICENSE +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/MANIFEST.in +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/README.rst +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref/compatibility.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref/current_thread_executor.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref/py.typed +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref/server.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref/sync.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref/testing.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref/timeout.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref/typing.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref/wsgi.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref.egg-info/SOURCES.txt +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref.egg-info/dependency_links.txt +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref.egg-info/not-zip-safe +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref.egg-info/requires.txt +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/asgiref.egg-info/top_level.txt +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/setup.cfg +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/setup.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/tests/test_compatibility.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/tests/test_server.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/tests/test_sync.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/tests/test_sync_contextvars.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/tests/test_testing.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/tests/test_wsgi.py +0 -0
- {asgiref-3.9.0 → asgiref-3.9.1}/tox.ini +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.9.1"
|
|
@@ -2,38 +2,37 @@ import asyncio
|
|
|
2
2
|
import contextlib
|
|
3
3
|
import contextvars
|
|
4
4
|
import threading
|
|
5
|
-
from typing import Any, Union
|
|
5
|
+
from typing import Any, Dict, Union
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class _CVar:
|
|
9
9
|
"""Storage utility for Local."""
|
|
10
10
|
|
|
11
11
|
def __init__(self) -> None:
|
|
12
|
-
self._data:
|
|
12
|
+
self._data: "contextvars.ContextVar[Dict[str, Any]]" = contextvars.ContextVar(
|
|
13
|
+
"asgiref.local"
|
|
14
|
+
)
|
|
13
15
|
|
|
14
|
-
def __getattr__(self, key
|
|
16
|
+
def __getattr__(self, key):
|
|
17
|
+
storage_object = self._data.get({})
|
|
15
18
|
try:
|
|
16
|
-
|
|
19
|
+
return storage_object[key]
|
|
17
20
|
except KeyError:
|
|
18
21
|
raise AttributeError(f"{self!r} object has no attribute {key!r}")
|
|
19
22
|
|
|
20
|
-
try:
|
|
21
|
-
return var.get()
|
|
22
|
-
except LookupError:
|
|
23
|
-
raise AttributeError(f"{self!r} object has no attribute {key!r}")
|
|
24
|
-
|
|
25
23
|
def __setattr__(self, key: str, value: Any) -> None:
|
|
26
24
|
if key == "_data":
|
|
27
25
|
return super().__setattr__(key, value)
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
var.set(value)
|
|
27
|
+
storage_object = self._data.get({}).copy()
|
|
28
|
+
storage_object[key] = value
|
|
29
|
+
self._data.set(storage_object)
|
|
33
30
|
|
|
34
31
|
def __delattr__(self, key: str) -> None:
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
storage_object = self._data.get({}).copy()
|
|
33
|
+
if key in storage_object:
|
|
34
|
+
del storage_object[key]
|
|
35
|
+
self._data.set(storage_object)
|
|
37
36
|
else:
|
|
38
37
|
raise AttributeError(f"{self!r} object has no attribute {key!r}")
|
|
39
38
|
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import gc
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
2
5
|
|
|
3
6
|
from asgiref.local import Local
|
|
4
7
|
|
|
@@ -29,6 +32,9 @@ def clean_up_after_garbage_collection_test() -> None:
|
|
|
29
32
|
gc.enable()
|
|
30
33
|
|
|
31
34
|
|
|
35
|
+
@pytest.mark.skipif(
|
|
36
|
+
sys.implementation.name == "pypy", reason="Test relies on CPython GC internals"
|
|
37
|
+
)
|
|
32
38
|
def test_thread_critical_Local_remove_all_reference_cycles() -> None:
|
|
33
39
|
try:
|
|
34
40
|
# given
|
|
@@ -375,3 +375,19 @@ async def test_visibility_task() -> None:
|
|
|
375
375
|
|
|
376
376
|
# Changes should not leak to the caller
|
|
377
377
|
assert test_local.value == 0
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
@pytest.mark.asyncio
|
|
381
|
+
async def test_deletion() -> None:
|
|
382
|
+
"""Check visibility with asyncio tasks."""
|
|
383
|
+
test_local = Local()
|
|
384
|
+
test_local.value = 123
|
|
385
|
+
|
|
386
|
+
async def _test() -> None:
|
|
387
|
+
# Local is inherited when changing task
|
|
388
|
+
assert test_local.value == 123
|
|
389
|
+
del test_local.value
|
|
390
|
+
assert not hasattr(test_local, "value")
|
|
391
|
+
|
|
392
|
+
await asyncio.create_task(_test())
|
|
393
|
+
assert test_local.value == 123
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "3.9.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|