python-injection 0.12.1__py3-none-any.whl → 0.12.2__py3-none-any.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.
injection/_core/module.py CHANGED
@@ -208,18 +208,20 @@ class Updater[T]:
208
208
  return Record(injectable, self.mode)
209
209
 
210
210
 
211
- class LocatorHooks[T](NamedTuple):
212
- on_conflict: Hook[[Record[T], Record[T], InputType[T]], bool]
213
- on_input: Hook[[Iterable[InputType[T]]], Iterable[InputType[T]]]
214
- on_update: Hook[[Updater[T]], Updater[T]]
215
-
216
- @classmethod
217
- def default(cls) -> Self:
218
- return cls(
219
- on_conflict=Hook(),
220
- on_input=Hook(),
221
- on_update=Hook(),
222
- )
211
+ @dataclass(repr=False, eq=False, frozen=True, slots=True)
212
+ class LocatorHooks[T]:
213
+ on_conflict: Hook[[Record[T], Record[T], InputType[T]], bool] = field(
214
+ default_factory=Hook,
215
+ init=False,
216
+ )
217
+ on_input: Hook[[Iterable[InputType[T]]], Iterable[InputType[T]]] = field(
218
+ default_factory=Hook,
219
+ init=False,
220
+ )
221
+ on_update: Hook[[Updater[T]], Updater[T]] = field(
222
+ default_factory=Hook,
223
+ init=False,
224
+ )
223
225
 
224
226
 
225
227
  @dataclass(repr=False, frozen=True, slots=True)
@@ -233,7 +235,7 @@ class Locator(Broker):
233
235
  init=False,
234
236
  )
235
237
 
236
- static_hooks: ClassVar[LocatorHooks[Any]] = LocatorHooks.default()
238
+ static_hooks: ClassVar[LocatorHooks[Any]] = LocatorHooks()
237
239
 
238
240
  def __getitem__[T](self, cls: InputType[T], /) -> Injectable[T]:
239
241
  for input_class in self.__standardize_inputs((cls,)):
@@ -1,11 +0,0 @@
1
- from importlib.util import find_spec
2
- from typing import Literal
3
-
4
- __all__ = ("_is_installed",)
5
-
6
-
7
- def _is_installed(package: str, needed_for: object, /) -> Literal[True]:
8
- if find_spec(package) is None:
9
- raise RuntimeError(f"To use `{needed_for}`, {package} must be installed.")
10
-
11
- return True
@@ -2,15 +2,13 @@ from collections.abc import Awaitable
2
2
  from types import GenericAlias
3
3
  from typing import Any, TypeAliasType
4
4
 
5
+ from fastapi import Depends
6
+
5
7
  from injection import Module, mod
6
8
  from injection.exceptions import InjectionError
7
- from injection.integrations import _is_installed
8
9
 
9
10
  __all__ = ("Inject",)
10
11
 
11
- if _is_installed("fastapi", __name__):
12
- from fastapi import Depends
13
-
14
12
 
15
13
  def Inject[T]( # noqa: N802
16
14
  cls: type[T] | TypeAliasType | GenericAlias,
injection/utils.py CHANGED
@@ -1,13 +1,15 @@
1
- from collections.abc import Callable, Iterator
1
+ from collections.abc import Callable, Iterable, Iterator
2
2
  from contextlib import contextmanager
3
3
  from importlib import import_module
4
+ from importlib.util import find_spec
4
5
  from pkgutil import walk_packages
5
6
  from types import ModuleType as PythonModule
6
7
  from typing import ContextManager
7
8
 
9
+ from injection import __name__ as injection_package_name
8
10
  from injection import mod
9
11
 
10
- __all__ = ("load_packages", "load_profile")
12
+ __all__ = ("load_modules_with_keywords", "load_packages", "load_profile")
11
13
 
12
14
 
13
15
  def load_profile(*names: str) -> ContextManager[None]:
@@ -33,6 +35,36 @@ def load_profile(*names: str) -> ContextManager[None]:
33
35
  return cleaner()
34
36
 
35
37
 
38
+ def load_modules_with_keywords(
39
+ *packages: PythonModule | str,
40
+ keywords: Iterable[str] | None = None,
41
+ ) -> dict[str, PythonModule]:
42
+ """
43
+ Function to import modules from a Python package if one of the keywords is contained in the Python script.
44
+ The default keywords are:
45
+ - `from injection`
46
+ - `import injection`
47
+ """
48
+
49
+ if keywords is None:
50
+ keywords = f"from {injection_package_name}", f"import {injection_package_name}"
51
+
52
+ b_keywords = tuple(keyword.encode() for keyword in keywords)
53
+
54
+ def predicate(module_name: str) -> bool:
55
+ if (spec := find_spec(module_name)) and (module_path := spec.origin):
56
+ with open(module_path, "rb") as script:
57
+ for line in script:
58
+ line = b" ".join(line.split(b" ")).strip()
59
+
60
+ if line and any(keyword in line for keyword in b_keywords):
61
+ return True
62
+
63
+ return False
64
+
65
+ return load_packages(*packages, predicate=predicate)
66
+
67
+
36
68
  def load_packages(
37
69
  *packages: PythonModule | str,
38
70
  predicate: Callable[[str], bool] = lambda module_name: True,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: python-injection
3
- Version: 0.12.1
3
+ Version: 0.12.2
4
4
  Summary: Fast and easy dependency injection framework.
5
5
  Home-page: https://github.com/100nm/python-injection
6
6
  License: MIT
@@ -11,14 +11,14 @@ injection/_core/common/type.py,sha256=c4QfvbkMfYMlNxqt-vq6QJ83ubMnw6AIVI2Rp-tV1P
11
11
  injection/_core/descriptors.py,sha256=y1rFTQdCDIMLVQfuQE8ZkTPlVZKgzvwZ2Y20Si05DwM,662
12
12
  injection/_core/hook.py,sha256=Qv505pr3kjOE6UitftlLh9JKX9OCNqZBRtHbFha1gqM,3130
13
13
  injection/_core/injectables.py,sha256=rBcrTYRpZ69LkHSGm6bve6TGPwf66XkuK2XVACwcRNc,2427
14
- injection/_core/module.py,sha256=xUgveXJS5PXd3DtfLBH7InafEtSShGND4ccYkCIfGqk,28611
14
+ injection/_core/module.py,sha256=H6seGNW482IEBNGGDxT9Lkv84TYQwWnoYYPcbzdF7YI,28675
15
15
  injection/exceptions.py,sha256=-5Shs7R5rctQXhpMLfcjiMBCzrtFWxC88qETUIHz57s,692
16
- injection/integrations/__init__.py,sha256=NYLcstr4ESdLj326LlDub143z6JGM1z1pCOVWhBXK10,304
17
- injection/integrations/fastapi.py,sha256=OZyZNxqJvOr-c5Ee0G1-oHhGF7067Ugjl_qDnIiAC1I,1760
16
+ injection/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ injection/integrations/fastapi.py,sha256=tI9ohXOm_WucqkS-DZJceIVb_mE9LOY_UpIcr6hfRVM,1668
18
18
  injection/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  injection/testing/__init__.py,sha256=Wd9sq43CJCV7GjYFSIaikIf4hJ5lfVNS7GP3iI8a1X8,719
20
20
  injection/testing/__init__.pyi,sha256=Dyf1LjSj3LrjghXjM2xkMiINg-OPWQMtjCEnnfWzaDY,372
21
- injection/utils.py,sha256=79VoIgxO1MNb_FlfRRbzfx3RXX3DPDtoxMgngfmNF-Q,1920
22
- python_injection-0.12.1.dist-info/METADATA,sha256=2TdNJGHf1TIvBrbRkVjfimNJR7frm4HDoKDnAYiop98,2958
23
- python_injection-0.12.1.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
24
- python_injection-0.12.1.dist-info/RECORD,,
21
+ injection/utils.py,sha256=a9y95B08Fr9IgDiBffeQdcawQcvAs5gwBDt9cCYX0uE,3061
22
+ python_injection-0.12.2.dist-info/METADATA,sha256=z_ybsuZ__2e8nCbkaT9tYjGsywJ6BzdrsBcima0bq20,2958
23
+ python_injection-0.12.2.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
24
+ python_injection-0.12.2.dist-info/RECORD,,