fastapi-injected 0.1.2__tar.gz → 0.1.3__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.
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/PKG-INFO +1 -1
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/fastapi_injected/__init__.py +4 -2
- fastapi_injected-0.1.3/fastapi_injected/_fastapi_lifecycle.py +62 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/fastapi_injected/deps.py +4 -42
- fastapi_injected-0.1.2/fastapi_injected/solve.py → fastapi_injected-0.1.3/fastapi_injected/resolve.py +2 -2
- fastapi_injected-0.1.3/fastapi_injected/scope.py +108 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/pyproject.toml +2 -1
- fastapi_injected-0.1.3/tests/test_fastapi.py +35 -0
- fastapi_injected-0.1.2/tests/test_solve.py → fastapi_injected-0.1.3/tests/test_resolve.py +6 -6
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/tests/test_typing.py +3 -3
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/uv.lock +3 -1
- fastapi_injected-0.1.2/fastapi_injected/scope.py +0 -75
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/.github/dependabot.yml +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/.github/workflows/automerge.yml +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/.github/workflows/lint.yml +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/.github/workflows/publish.yml +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/.github/workflows/test.yml +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/.gitignore +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/.pre-commit-config.yaml +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/LICENSE +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/README.md +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/fastapi_injected/inject.py +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/fastapi_injected/sign.py +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/fastapi_injected/types.py +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/tests/__init__.py +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/tests/deps.py +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/tests/ext/__init__.py +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/tests/ext/test_pydantic_ai.py +0 -0
- {fastapi_injected-0.1.2 → fastapi_injected-0.1.3}/tests/test_inject.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-injected
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Yet another library to reuse fastapi dependency injection
|
|
5
5
|
Project-URL: Repository, https://github.com/uriyyo/fastapi-injected
|
|
6
6
|
Author-email: Yurii Karabas <1998uriyyo@gmail.com>
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
from ._fastapi_lifecycle import init_inject_scope
|
|
1
2
|
from .inject import inject
|
|
3
|
+
from .resolve import resolve
|
|
2
4
|
from .scope import push_inject_scope
|
|
3
|
-
from .solve import solve
|
|
4
5
|
from .types import Dep, DepFactory, Injected
|
|
5
6
|
|
|
6
7
|
__all__ = [
|
|
7
8
|
"Dep",
|
|
8
9
|
"DepFactory",
|
|
9
10
|
"Injected",
|
|
11
|
+
"init_inject_scope",
|
|
10
12
|
"inject",
|
|
11
13
|
"push_inject_scope",
|
|
12
|
-
"
|
|
14
|
+
"resolve",
|
|
13
15
|
]
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from collections.abc import AsyncIterable
|
|
2
|
+
from functools import wraps
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from fastapi import Request, WebSocket, routing
|
|
6
|
+
from fastapi.dependencies import utils
|
|
7
|
+
|
|
8
|
+
from .scope import push_inject_scope
|
|
9
|
+
from .types import DependencyCache
|
|
10
|
+
|
|
11
|
+
_DEPENDENCY_CACHE_KEY = "__fastapi_injected_dependency_cache__"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class MissingDependencyCacheError(Exception):
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
if not TYPE_CHECKING:
|
|
19
|
+
_base_solve_dependencies = utils.solve_dependencies
|
|
20
|
+
|
|
21
|
+
@wraps(_base_solve_dependencies)
|
|
22
|
+
async def _solve_dependencies(
|
|
23
|
+
*,
|
|
24
|
+
request: Request | WebSocket,
|
|
25
|
+
dependency_cache: DependencyCache | None = None,
|
|
26
|
+
**kwargs: Any,
|
|
27
|
+
) -> utils.SolvedDependency:
|
|
28
|
+
if (current_cache := request.scope.get(_DEPENDENCY_CACHE_KEY)) is not None:
|
|
29
|
+
dependency_cache = current_cache
|
|
30
|
+
elif dependency_cache is None:
|
|
31
|
+
dependency_cache = {}
|
|
32
|
+
|
|
33
|
+
request.scope[_DEPENDENCY_CACHE_KEY] = dependency_cache
|
|
34
|
+
|
|
35
|
+
return await _base_solve_dependencies(
|
|
36
|
+
request=request,
|
|
37
|
+
dependency_cache=dependency_cache,
|
|
38
|
+
**kwargs,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
utils.solve_dependencies = _solve_dependencies
|
|
42
|
+
routing.solve_dependencies = _solve_dependencies
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _get_dependency_cache(request: Request) -> DependencyCache:
|
|
46
|
+
try:
|
|
47
|
+
return request.scope[_DEPENDENCY_CACHE_KEY]
|
|
48
|
+
except KeyError:
|
|
49
|
+
raise MissingDependencyCacheError("Dependency cache not found") from None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
async def init_inject_scope(request: Request) -> AsyncIterable[None]:
|
|
53
|
+
async with push_inject_scope(
|
|
54
|
+
dependency_cache=_get_dependency_cache(request),
|
|
55
|
+
request=request,
|
|
56
|
+
):
|
|
57
|
+
yield
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
__all__ = [
|
|
61
|
+
"init_inject_scope",
|
|
62
|
+
]
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import inspect
|
|
2
2
|
from collections.abc import Callable
|
|
3
|
+
from contextlib import AsyncExitStack
|
|
3
4
|
from contextvars import ContextVar
|
|
4
5
|
from copy import copy
|
|
5
6
|
from functools import lru_cache, wraps
|
|
@@ -9,47 +10,12 @@ from fastapi import Depends
|
|
|
9
10
|
from fastapi.dependencies.models import Dependant
|
|
10
11
|
from fastapi.dependencies.utils import get_dependant, get_typed_signature
|
|
11
12
|
from fastapi.dependencies.utils import solve_dependencies as _solve_dependencies
|
|
12
|
-
from starlette.requests import Request
|
|
13
|
-
from starlette.types import Message, Scope
|
|
14
13
|
|
|
15
14
|
from .scope import InjectScope
|
|
16
15
|
from .sign import prepare_sign, update_func_sign
|
|
17
16
|
from .types import Coro, HasSignature
|
|
18
17
|
|
|
19
18
|
|
|
20
|
-
def _dummy_scope() -> Scope:
|
|
21
|
-
return {
|
|
22
|
-
"type": "http",
|
|
23
|
-
"http_version": "1.1",
|
|
24
|
-
"query_string": b"",
|
|
25
|
-
"headers": [],
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def _dummy_request(
|
|
30
|
-
*,
|
|
31
|
-
extra_scope: Scope | None = None,
|
|
32
|
-
) -> Request:
|
|
33
|
-
async def _dummy_receive() -> Message:
|
|
34
|
-
return {
|
|
35
|
-
"type": "http.request",
|
|
36
|
-
"body": b"",
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async def _dummy_send(_: Message, /) -> None:
|
|
40
|
-
pass
|
|
41
|
-
|
|
42
|
-
scope = _dummy_scope()
|
|
43
|
-
if extra_scope:
|
|
44
|
-
scope.update(extra_scope)
|
|
45
|
-
|
|
46
|
-
return Request(
|
|
47
|
-
scope,
|
|
48
|
-
receive=_dummy_receive,
|
|
49
|
-
send=_dummy_send,
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
|
|
53
19
|
@lru_cache(maxsize=1024)
|
|
54
20
|
def create_dependant[**P, R](func: Callable[P, Coro[R]], /) -> Dependant:
|
|
55
21
|
@wraps(func)
|
|
@@ -114,16 +80,12 @@ async def solve_dependencies(
|
|
|
114
80
|
single: bool = False,
|
|
115
81
|
) -> dict[str, Any]:
|
|
116
82
|
solved = await _solve_dependencies(
|
|
117
|
-
request=
|
|
118
|
-
extra_scope={
|
|
119
|
-
"fastapi_inner_astack": scope.request_astack,
|
|
120
|
-
"fastapi_function_astack": scope.func_astack,
|
|
121
|
-
},
|
|
122
|
-
),
|
|
83
|
+
request=scope.request,
|
|
123
84
|
dependant=dependant,
|
|
124
|
-
async_exit_stack=scope.request_astack,
|
|
125
85
|
dependency_cache=copy(scope.dependency_cache),
|
|
126
86
|
dependency_overrides_provider=_dependency_override_provider.get(),
|
|
87
|
+
# this parameter is deprecated and not used
|
|
88
|
+
async_exit_stack=cast(AsyncExitStack, None),
|
|
127
89
|
embed_body_fields=False,
|
|
128
90
|
)
|
|
129
91
|
|
|
@@ -4,7 +4,7 @@ from .deps import create_single_dependant, solve_dependencies
|
|
|
4
4
|
from .scope import inside_inject_scope
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
async def
|
|
7
|
+
async def resolve[R](
|
|
8
8
|
tp: TypeForm[R],
|
|
9
9
|
*,
|
|
10
10
|
new_scope: bool = False,
|
|
@@ -22,5 +22,5 @@ async def solve[R](
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
__all__ = [
|
|
25
|
-
"
|
|
25
|
+
"resolve",
|
|
26
26
|
]
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
from collections.abc import AsyncIterator
|
|
2
|
+
from contextlib import (
|
|
3
|
+
AsyncExitStack,
|
|
4
|
+
asynccontextmanager,
|
|
5
|
+
)
|
|
6
|
+
from contextvars import ContextVar
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
|
|
9
|
+
from fastapi import Request
|
|
10
|
+
from starlette.types import Message, Scope
|
|
11
|
+
|
|
12
|
+
from .types import DependencyCache
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _dummy_scope() -> Scope:
|
|
16
|
+
return {
|
|
17
|
+
"type": "http",
|
|
18
|
+
"http_version": "1.1",
|
|
19
|
+
"query_string": b"",
|
|
20
|
+
"headers": [],
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _dummy_request(
|
|
25
|
+
*,
|
|
26
|
+
extra_scope: Scope | None = None,
|
|
27
|
+
) -> Request:
|
|
28
|
+
async def _dummy_receive() -> Message:
|
|
29
|
+
return {
|
|
30
|
+
"type": "http.request",
|
|
31
|
+
"body": b"",
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async def _dummy_send(_: Message, /) -> None:
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
scope = _dummy_scope()
|
|
38
|
+
if extra_scope:
|
|
39
|
+
scope.update(extra_scope)
|
|
40
|
+
|
|
41
|
+
return Request(
|
|
42
|
+
scope,
|
|
43
|
+
receive=_dummy_receive,
|
|
44
|
+
send=_dummy_send,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass
|
|
49
|
+
class InjectScope:
|
|
50
|
+
dependency_cache: DependencyCache
|
|
51
|
+
request: Request
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
_inject_scope: ContextVar[InjectScope | None] = ContextVar(
|
|
55
|
+
"_inject_scope",
|
|
56
|
+
default=None,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@asynccontextmanager
|
|
61
|
+
async def push_inject_scope(
|
|
62
|
+
*,
|
|
63
|
+
dependency_cache: DependencyCache | None = None,
|
|
64
|
+
request: Request | None = None,
|
|
65
|
+
) -> AsyncIterator[InjectScope]:
|
|
66
|
+
if dependency_cache is None:
|
|
67
|
+
dependency_cache = {}
|
|
68
|
+
|
|
69
|
+
async with AsyncExitStack() as stack:
|
|
70
|
+
request = request or _dummy_request(
|
|
71
|
+
extra_scope={
|
|
72
|
+
"fastapi_inner_astack": stack,
|
|
73
|
+
"fastapi_function_astack": stack,
|
|
74
|
+
},
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
scope = InjectScope(dependency_cache, request)
|
|
78
|
+
token = _inject_scope.set(scope)
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
yield scope
|
|
82
|
+
finally:
|
|
83
|
+
_inject_scope.reset(token)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def current_inject_scope() -> InjectScope | None:
|
|
87
|
+
return _inject_scope.get()
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@asynccontextmanager
|
|
91
|
+
async def inside_inject_scope(
|
|
92
|
+
*,
|
|
93
|
+
new_scope: bool = False,
|
|
94
|
+
) -> AsyncIterator[InjectScope]:
|
|
95
|
+
scope = current_inject_scope()
|
|
96
|
+
|
|
97
|
+
async with AsyncExitStack() as stack:
|
|
98
|
+
if scope is None or new_scope:
|
|
99
|
+
scope = await stack.enter_async_context(push_inject_scope())
|
|
100
|
+
|
|
101
|
+
yield scope
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
__all__ = [
|
|
105
|
+
"InjectScope",
|
|
106
|
+
"current_inject_scope",
|
|
107
|
+
"inside_inject_scope",
|
|
108
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "fastapi-injected"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.3"
|
|
4
4
|
description = "Yet another library to reuse fastapi dependency injection"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Yurii Karabas", email = "1998uriyyo@gmail.com" },
|
|
@@ -30,6 +30,7 @@ dev = [
|
|
|
30
30
|
"ty>=0.0.62",
|
|
31
31
|
"pre-commit>=4.6.1",
|
|
32
32
|
"pydantic-ai-slim>=2.15.0",
|
|
33
|
+
"httpx>=0.28.1",
|
|
33
34
|
]
|
|
34
35
|
|
|
35
36
|
[project.urls]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from fastapi import Depends, FastAPI, status
|
|
2
|
+
from fastapi.testclient import TestClient
|
|
3
|
+
|
|
4
|
+
from fastapi_injected import Dep, Injected, init_inject_scope, inject, resolve
|
|
5
|
+
|
|
6
|
+
from .deps import Container
|
|
7
|
+
|
|
8
|
+
app = FastAPI(
|
|
9
|
+
dependencies=[
|
|
10
|
+
Depends(init_inject_scope),
|
|
11
|
+
],
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
client = TestClient(app)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@inject
|
|
18
|
+
async def _func(
|
|
19
|
+
*,
|
|
20
|
+
container: Dep[Container] = Injected,
|
|
21
|
+
) -> Container:
|
|
22
|
+
return container
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@app.get("/")
|
|
26
|
+
async def route(container: Dep[Container]) -> str:
|
|
27
|
+
assert await resolve(Container) is container
|
|
28
|
+
assert await _func() is container
|
|
29
|
+
|
|
30
|
+
return ""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_cache_is_working() -> None:
|
|
34
|
+
result = client.get("/")
|
|
35
|
+
assert result.status_code == status.HTTP_200_OK
|
|
@@ -2,7 +2,7 @@ from dataclasses import dataclass
|
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
|
-
from fastapi_injected import Dep, push_inject_scope,
|
|
5
|
+
from fastapi_injected import Dep, push_inject_scope, resolve
|
|
6
6
|
|
|
7
7
|
pytestmark = pytest.mark.asyncio
|
|
8
8
|
|
|
@@ -17,16 +17,16 @@ class Bar:
|
|
|
17
17
|
foo: Dep[Foo]
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
async def
|
|
21
|
-
bar = await
|
|
20
|
+
async def test_resolve():
|
|
21
|
+
bar = await resolve(Bar)
|
|
22
22
|
|
|
23
23
|
assert isinstance(bar, Bar)
|
|
24
24
|
assert isinstance(bar.foo, Foo)
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
async def
|
|
27
|
+
async def test_resolve_reuse_cache():
|
|
28
28
|
async with push_inject_scope():
|
|
29
|
-
b1 = await
|
|
30
|
-
b2 = await
|
|
29
|
+
b1 = await resolve(Bar)
|
|
30
|
+
b2 = await resolve(Bar)
|
|
31
31
|
|
|
32
32
|
assert b1 is b2
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
|
-
from fastapi_injected import Dep, DepFactory, Injected, inject,
|
|
3
|
+
from fastapi_injected import Dep, DepFactory, Injected, inject, resolve
|
|
4
4
|
|
|
5
5
|
from .deps import Child, Container, ContextState, ctx_dep
|
|
6
6
|
|
|
@@ -22,8 +22,8 @@ async def func(
|
|
|
22
22
|
return a + 10
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
async def
|
|
26
|
-
container = await
|
|
25
|
+
async def resolve_test() -> None:
|
|
26
|
+
container = await resolve(Container)
|
|
27
27
|
|
|
28
28
|
static_assert(is_equivalent_to(TypeOf[container], Container))
|
|
29
29
|
|
|
@@ -160,7 +160,7 @@ wheels = [
|
|
|
160
160
|
|
|
161
161
|
[[package]]
|
|
162
162
|
name = "fastapi-injected"
|
|
163
|
-
version = "0.1.
|
|
163
|
+
version = "0.1.3"
|
|
164
164
|
source = { editable = "." }
|
|
165
165
|
dependencies = [
|
|
166
166
|
{ name = "fastapi" },
|
|
@@ -168,6 +168,7 @@ dependencies = [
|
|
|
168
168
|
|
|
169
169
|
[package.dev-dependencies]
|
|
170
170
|
dev = [
|
|
171
|
+
{ name = "httpx" },
|
|
171
172
|
{ name = "pre-commit" },
|
|
172
173
|
{ name = "pydantic-ai-slim" },
|
|
173
174
|
{ name = "pytest" },
|
|
@@ -182,6 +183,7 @@ requires-dist = [{ name = "fastapi", specifier = ">=0.139.2" }]
|
|
|
182
183
|
|
|
183
184
|
[package.metadata.requires-dev]
|
|
184
185
|
dev = [
|
|
186
|
+
{ name = "httpx", specifier = ">=0.28.1" },
|
|
185
187
|
{ name = "pre-commit", specifier = ">=4.6.1" },
|
|
186
188
|
{ name = "pydantic-ai-slim", specifier = ">=2.15.0" },
|
|
187
189
|
{ name = "pytest", specifier = ">=9.1.1" },
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
from collections.abc import AsyncIterator
|
|
2
|
-
from contextlib import (
|
|
3
|
-
AbstractAsyncContextManager,
|
|
4
|
-
AsyncExitStack,
|
|
5
|
-
asynccontextmanager,
|
|
6
|
-
nullcontext,
|
|
7
|
-
)
|
|
8
|
-
from contextvars import ContextVar
|
|
9
|
-
from dataclasses import dataclass
|
|
10
|
-
from typing import Any
|
|
11
|
-
|
|
12
|
-
from .types import DependencyCache
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@dataclass
|
|
16
|
-
class InjectScope:
|
|
17
|
-
dependency_cache: DependencyCache
|
|
18
|
-
func_astack: AsyncExitStack
|
|
19
|
-
request_astack: AsyncExitStack
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
_inject_scope: ContextVar[InjectScope | None] = ContextVar(
|
|
23
|
-
"_inject_scope",
|
|
24
|
-
default=None,
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
@asynccontextmanager
|
|
29
|
-
async def push_inject_scope(
|
|
30
|
-
dependency_cache: DependencyCache | None = None,
|
|
31
|
-
) -> AsyncIterator[InjectScope]:
|
|
32
|
-
async with AsyncExitStack() as stack:
|
|
33
|
-
scope = InjectScope(
|
|
34
|
-
dependency_cache or {},
|
|
35
|
-
stack,
|
|
36
|
-
stack,
|
|
37
|
-
)
|
|
38
|
-
token = _inject_scope.set(scope)
|
|
39
|
-
|
|
40
|
-
try:
|
|
41
|
-
yield scope
|
|
42
|
-
finally:
|
|
43
|
-
_inject_scope.reset(token)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def current_inject_scope() -> InjectScope | None:
|
|
47
|
-
return _inject_scope.get()
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
@asynccontextmanager
|
|
51
|
-
async def inside_inject_scope(
|
|
52
|
-
*,
|
|
53
|
-
new_scope: bool = False,
|
|
54
|
-
) -> AsyncIterator[InjectScope]:
|
|
55
|
-
scope = current_inject_scope()
|
|
56
|
-
|
|
57
|
-
_ctx: AbstractAsyncContextManager[Any]
|
|
58
|
-
|
|
59
|
-
if scope is None or new_scope:
|
|
60
|
-
stack = AsyncExitStack()
|
|
61
|
-
scope = await stack.enter_async_context(push_inject_scope())
|
|
62
|
-
|
|
63
|
-
_ctx = stack
|
|
64
|
-
else:
|
|
65
|
-
_ctx = nullcontext()
|
|
66
|
-
|
|
67
|
-
async with _ctx:
|
|
68
|
-
yield scope
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
__all__ = [
|
|
72
|
-
"InjectScope",
|
|
73
|
-
"current_inject_scope",
|
|
74
|
-
"inside_inject_scope",
|
|
75
|
-
]
|
|
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
|