Skip to content

Commit 9ff142d

Browse files
authored
refactoring: ♻️ Default parameter added to Inject and LazyInstance
1 parent 8b48cf9 commit 9ff142d

7 files changed

Lines changed: 148 additions & 147 deletions

File tree

injection/__init__.pyi

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,13 @@ class Injectable[T](Protocol):
4646
def get_instance(self) -> T: ...
4747

4848
class LazyInstance[T]:
49-
def __init__(self, cls: _InputType[T], module: Module = ...) -> None: ...
49+
def __init__(
50+
self,
51+
cls: _InputType[T],
52+
/,
53+
default: T = ...,
54+
module: Module = ...,
55+
) -> None: ...
5056
@overload
5157
def __get__(self, instance: object, owner: type | None = ...) -> T: ...
5258
@overload

injection/_core/descriptors.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,15 @@ class LazyInstance[T]:
1010

1111
__value: Invertible[T]
1212

13-
def __init__(self, cls: InputType[T], module: Module | None = None) -> None:
13+
def __init__(
14+
self,
15+
cls: InputType[T],
16+
/,
17+
default: T = NotImplemented,
18+
module: Module | None = None,
19+
) -> None:
1420
module = module or mod()
15-
self.__value = module.get_lazy_instance(cls, default=NotImplemented)
21+
self.__value = module.get_lazy_instance(cls, default)
1622

1723
def __get__(
1824
self,

injection/_core/module.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ def scoped[**P, T](
445445
mode: Mode | ModeStr = Mode.get_default(),
446446
) -> Any:
447447
def decorator(
448-
wp: Callable[P, T]
448+
wrapped: Callable[P, T]
449449
| Callable[P, Awaitable[T]]
450450
| Callable[P, Iterator[T]]
451451
| Callable[P, AsyncIterator[T]],
@@ -463,19 +463,19 @@ def decorator(
463463
| Callable[P, AsyncContextManager[T]]
464464
)
465465

466-
if isasyncgenfunction(wp):
467-
hint = get_yield_hint(wp)
466+
if isasyncgenfunction(wrapped):
467+
hint = get_yield_hint(wrapped)
468468
injectable_class = AsyncCMScopedInjectable
469-
wrapper = asynccontextmanager(wp)
469+
wrapper = asynccontextmanager(wrapped)
470470

471-
elif isgeneratorfunction(wp):
472-
hint = get_yield_hint(wp)
471+
elif isgeneratorfunction(wrapped):
472+
hint = get_yield_hint(wrapped)
473473
injectable_class = CMScopedInjectable
474-
wrapper = contextmanager(wp)
474+
wrapper = contextmanager(wrapped)
475475

476476
else:
477477
injectable_class = SimpleScopedInjectable
478-
hint = wrapper = wp # type: ignore[assignment]
478+
hint = wrapper = wrapped # type: ignore[assignment]
479479

480480
hints = on if hint is None else (hint, on)
481481
self.injectable(
@@ -486,7 +486,7 @@ def decorator(
486486
on=hints,
487487
mode=mode,
488488
)
489-
return wp
489+
return wrapped
490490

491491
return decorator
492492

injection/_core/scope.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,7 @@
33
from abc import ABC, abstractmethod
44
from collections import defaultdict
55
from collections.abc import AsyncIterator, Iterator, MutableMapping
6-
from contextlib import (
7-
AsyncContextDecorator,
8-
AsyncExitStack,
9-
ContextDecorator,
10-
ExitStack,
11-
asynccontextmanager,
12-
contextmanager,
13-
)
6+
from contextlib import AsyncExitStack, ExitStack, asynccontextmanager, contextmanager
147
from contextvars import ContextVar
158
from dataclasses import dataclass, field
169
from types import TracebackType
@@ -19,6 +12,7 @@
1912
AsyncContextManager,
2013
ContextManager,
2114
Final,
15+
NoReturn,
2216
Protocol,
2317
Self,
2418
runtime_checkable,
@@ -163,7 +157,7 @@ class BaseScope[T](Scope, ABC):
163157
)
164158

165159

166-
class AsyncScope(AsyncContextDecorator, BaseScope[AsyncExitStack]):
160+
class AsyncScope(BaseScope[AsyncExitStack]):
167161
__slots__ = ()
168162

169163
def __init__(self) -> None:
@@ -188,7 +182,7 @@ def enter[T](self, context_manager: ContextManager[T]) -> T:
188182
return self.delegate.enter_context(context_manager)
189183

190184

191-
class SyncScope(ContextDecorator, BaseScope[ExitStack]):
185+
class SyncScope(BaseScope[ExitStack]):
192186
__slots__ = ()
193187

194188
def __init__(self) -> None:
@@ -206,7 +200,7 @@ def __exit__(
206200
) -> Any:
207201
return self.delegate.__exit__(exc_type, exc_value, traceback)
208202

209-
async def aenter[T](self, context_manager: AsyncContextManager[T]) -> T:
203+
async def aenter[T](self, context_manager: AsyncContextManager[T]) -> NoReturn:
210204
raise ScopeError(
211205
"Synchronous scope doesn't support asynchronous context manager."
212206
)

injection/integrations/fastapi.py

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from collections.abc import Awaitable
21
from types import GenericAlias
32
from typing import Any, TypeAliasType
43

@@ -12,27 +11,17 @@
1211
def Inject[T]( # noqa: N802
1312
cls: type[T] | TypeAliasType | GenericAlias,
1413
/,
14+
default: T = NotImplemented,
1515
module: Module | None = None,
1616
) -> Any:
1717
"""
1818
Declare a FastAPI dependency with `python-injection`.
1919
"""
2020

21-
dependency: InjectionDependency[T] = InjectionDependency(cls, module or mod())
22-
return Depends(dependency, use_cache=False)
21+
module = module or mod()
22+
lazy_instance = module.aget_lazy_instance(cls, default)
2323

24+
async def getter() -> T:
25+
return await lazy_instance
2426

25-
class InjectionDependency[T]:
26-
__slots__ = ("__awaitable",)
27-
28-
__awaitable: Awaitable[T]
29-
30-
def __init__(
31-
self,
32-
cls: type[T] | TypeAliasType | GenericAlias,
33-
module: Module,
34-
) -> None:
35-
self.__awaitable = module.aget_lazy_instance(cls, default=NotImplemented)
36-
37-
async def __call__(self) -> T:
38-
return await self.__awaitable
27+
return Depends(getter, use_cache=False)

pyproject.toml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ exclude_lines = [
6161
[tool.coverage.run]
6262
omit = ["bench.py"]
6363

64+
[tool.hatch.build]
65+
skip-excluded-dirs = true
66+
67+
[tool.hatch.build.targets.sdist]
68+
include = ["injection"]
69+
70+
[tool.hatch.build.targets.wheel]
71+
packages = ["injection"]
72+
6473
[tool.mypy]
6574
check_untyped_defs = true
6675
disallow_any_generics = true
@@ -77,15 +86,6 @@ plugins = ["pydantic.mypy"]
7786
warn_redundant_casts = true
7887
warn_unused_ignores = true
7988

80-
[tool.hatch.build]
81-
skip-excluded-dirs = true
82-
83-
[tool.hatch.build.targets.sdist]
84-
include = ["injection"]
85-
86-
[tool.hatch.build.targets.wheel]
87-
packages = ["injection"]
88-
8989
[tool.pydantic-mypy]
9090
init_forbid_extra = true
9191
init_typed = true

0 commit comments

Comments
 (0)