svcs-di 0.2.0__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.
svcs_di-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.3
2
+ Name: svcs-di
3
+ Version: 0.2.0
4
+ Summary: Dependency injection using svcs
5
+ Classifier: Development Status :: 3 - Alpha
6
+ Classifier: Intended Audience :: Developers
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.14
9
+ Classifier: Programming Language :: Python :: 3 :: Only
10
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
11
+ Classifier: Typing :: Typed
12
+ Requires-Dist: svcs
13
+ Requires-Python: >=3.14
@@ -0,0 +1,57 @@
1
+ [project]
2
+ name = "svcs-di"
3
+ version = "0.2.0"
4
+ description = "Dependency injection using svcs"
5
+ requires-python = ">=3.14"
6
+ dependencies = [
7
+ "svcs"
8
+ ]
9
+ classifiers = [
10
+ "Development Status :: 3 - Alpha",
11
+ "Intended Audience :: Developers",
12
+ "Programming Language :: Python :: 3",
13
+ "Programming Language :: Python :: 3.14",
14
+ "Programming Language :: Python :: 3 :: Only",
15
+ "Topic :: Software Development :: Libraries :: Python Modules",
16
+ "Typing :: Typed",
17
+ ]
18
+
19
+ [dependency-groups]
20
+ dev = [
21
+ "coverage>=7.13.0",
22
+ "furo>=2025.12.19",
23
+ "linkify-it-py>=2.0.3",
24
+ "myst-parser",
25
+ "pyrefly>=0.46.1",
26
+ "pyright>=1.1.407",
27
+ "pytest>=8.4.2",
28
+ "pytest-cov>=4.1.0",
29
+ "pytest-run-parallel>=0.8.1",
30
+ "pytest-timeout>=2.4.0",
31
+ "pytest-xdist>=3.8.0",
32
+ "ruff>=0.14.10",
33
+ "sphinx>=8",
34
+ "sphinx-autobuild>=2025.8.25",
35
+ "sybil[pytest]>=8.4.2",
36
+ "ty>=0.0.6",
37
+ ]
38
+
39
+ [tool.pytest.ini_options]
40
+ testpaths = ["tests", "src"]
41
+ python_files = ["test_*.py"]
42
+ addopts = "-p no:doctest -m \"not slow\""
43
+ pythonpath = ["examples"]
44
+ markers = [
45
+ "slow: marks tests as slow (deselect with '-m \"not slow\"')",
46
+ "freethreaded: marks tests that verify free-threading compatibility",
47
+ ]
48
+ # Free-threading safety: timeout tests to detect hangs/deadlocks
49
+ timeout = 60
50
+ faulthandler_timeout = 120
51
+
52
+ [tool.ty.environment]
53
+ extra-paths = ["examples/scanning"]
54
+
55
+ [build-system]
56
+ requires = ["uv_build>=0.8.17,<0.9.0"]
57
+ build-backend = "uv_build"
@@ -0,0 +1,44 @@
1
+ """
2
+ svcs-di: Minimal automatic dependency injection helper for svcs.
3
+
4
+ This package provides a thin layer on top of svcs for automatic dependency
5
+ resolution based on type hints, with explicit opt-in via the Inject[T] marker.
6
+
7
+ Key exports:
8
+ - auto: Factory function generator for automatic dependency injection
9
+ - auto_async: Async factory function generator for async dependencies
10
+ - Inject: Type marker for parameters that should be injected from container
11
+ - Resource: Type marker for resource injection from HopscotchContainer
12
+ - Injector: Protocol defining the injector interface
13
+ - AsyncInjector: Protocol defining the async injector interface
14
+ - DefaultInjector: Default synchronous injector implementation
15
+ - DefaultAsyncInjector: Default asynchronous injector implementation
16
+ - InjectionTarget: Type alias for class or callable targets (type[T] | Callable[..., T])
17
+ - AsyncInjectionTarget: Type alias for async targets (type[T] | Callable[..., Awaitable[T]])
18
+ """
19
+
20
+ from svcs_di.auto import (
21
+ AsyncInjectionTarget,
22
+ AsyncInjector,
23
+ DefaultAsyncInjector,
24
+ DefaultInjector,
25
+ Inject,
26
+ InjectionTarget,
27
+ Injector,
28
+ Resource,
29
+ auto,
30
+ auto_async,
31
+ )
32
+
33
+ __all__ = [
34
+ "auto",
35
+ "auto_async",
36
+ "Inject",
37
+ "Resource",
38
+ "Injector",
39
+ "AsyncInjector",
40
+ "DefaultInjector",
41
+ "DefaultAsyncInjector",
42
+ "InjectionTarget",
43
+ "AsyncInjectionTarget",
44
+ ]
@@ -0,0 +1,77 @@
1
+ """
2
+ Mixin providing shared inject/ainject methods for container classes.
3
+
4
+ This module contains InjectorMixin which provides the core implementation
5
+ for inject() and ainject() methods used by InjectorContainer and HopscotchContainer.
6
+ """
7
+
8
+ from typing import Any
9
+
10
+ from svcs_di.auto import AsyncInjector, Injector
11
+
12
+
13
+ class InjectorMixin:
14
+ """
15
+ Mixin providing inject/ainject methods for containers.
16
+
17
+ This mixin provides _do_inject and _do_ainject methods that implement
18
+ the core injection logic. Subclasses should define their own inject()
19
+ and ainject() methods that delegate to these with appropriate injector_kwargs.
20
+
21
+ Attributes:
22
+ injector: The synchronous injector class to use.
23
+ async_injector: The asynchronous injector class to use.
24
+ """
25
+
26
+ injector: type[Injector] | None
27
+ async_injector: type[AsyncInjector] | None
28
+
29
+ def _do_inject[T](
30
+ self,
31
+ svc_type: type[T],
32
+ injector_kwargs: dict[str, Any],
33
+ **kwargs: Any,
34
+ ) -> T:
35
+ """
36
+ Core sync injection implementation.
37
+
38
+ Args:
39
+ svc_type: The service type to resolve.
40
+ injector_kwargs: Kwargs to pass to injector constructor (e.g., resource).
41
+ **kwargs: Kwargs to pass through to the target callable.
42
+
43
+ Returns:
44
+ The resolved service instance.
45
+
46
+ Raises:
47
+ ValueError: If no injector is configured.
48
+ """
49
+ if self.injector is None:
50
+ raise ValueError("Cannot inject without an injector configured")
51
+ return self.injector(container=self, **injector_kwargs)(svc_type, **kwargs)
52
+
53
+ async def _do_ainject[T](
54
+ self,
55
+ svc_type: type[T],
56
+ injector_kwargs: dict[str, Any],
57
+ **kwargs: Any,
58
+ ) -> T:
59
+ """
60
+ Core async injection implementation.
61
+
62
+ Args:
63
+ svc_type: The service type to resolve.
64
+ injector_kwargs: Kwargs to pass to injector constructor (e.g., resource).
65
+ **kwargs: Kwargs to pass through to the target callable.
66
+
67
+ Returns:
68
+ The resolved service instance.
69
+
70
+ Raises:
71
+ ValueError: If no async injector is configured.
72
+ """
73
+ if self.async_injector is None:
74
+ raise ValueError("Cannot inject without an async injector configured")
75
+ return await self.async_injector(container=self, **injector_kwargs)(
76
+ svc_type, **kwargs
77
+ )