dioxide 0.1.0__cp311-abi3-macosx_11_0_arm64.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.
Potentially problematic release.
This version of dioxide might be problematic. Click here for more details.
- dioxide/__init__.py +14 -0
- dioxide/_dioxide_core.abi3.so +0 -0
- dioxide/_rivet_core.pyi +17 -0
- dioxide/container.py +171 -0
- dioxide/decorators.py +61 -0
- dioxide/py.typed +0 -0
- dioxide/scope.py +10 -0
- dioxide-0.1.0.dist-info/METADATA +243 -0
- dioxide-0.1.0.dist-info/RECORD +11 -0
- dioxide-0.1.0.dist-info/WHEEL +4 -0
- dioxide-0.1.0.dist-info/licenses/LICENSE +21 -0
dioxide/__init__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""dioxide: Fast, Rust-backed declarative dependency injection for Python."""
|
|
2
|
+
|
|
3
|
+
from .container import Container
|
|
4
|
+
from .decorators import _clear_registry, _get_registered_components, component
|
|
5
|
+
from .scope import Scope
|
|
6
|
+
|
|
7
|
+
__version__ = '0.1.0'
|
|
8
|
+
__all__ = [
|
|
9
|
+
'Container',
|
|
10
|
+
'Scope',
|
|
11
|
+
'_clear_registry',
|
|
12
|
+
'_get_registered_components',
|
|
13
|
+
'component',
|
|
14
|
+
]
|
|
Binary file
|
dioxide/_rivet_core.pyi
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Type stubs for Rust core module."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
from typing import TypeVar
|
|
5
|
+
|
|
6
|
+
T = TypeVar('T')
|
|
7
|
+
|
|
8
|
+
class Container:
|
|
9
|
+
"""Rust-backed container implementation."""
|
|
10
|
+
|
|
11
|
+
def __init__(self) -> None: ...
|
|
12
|
+
def register_instance(self, py_type: type[T], instance: T) -> None: ...
|
|
13
|
+
def register_class(self, py_type: type[T], implementation: type[T]) -> None: ...
|
|
14
|
+
def register_factory(self, py_type: type[T], factory: Callable[[], T]) -> None: ...
|
|
15
|
+
def resolve(self, py_type: type[T]) -> T: ...
|
|
16
|
+
def is_empty(self) -> bool: ...
|
|
17
|
+
def __len__(self) -> int: ...
|
dioxide/container.py
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""Dependency injection container."""
|
|
2
|
+
|
|
3
|
+
import inspect
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from typing import Any, TypeVar, get_type_hints
|
|
6
|
+
|
|
7
|
+
from dioxide._dioxide_core import Container as RustContainer
|
|
8
|
+
|
|
9
|
+
T = TypeVar('T')
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Container:
|
|
13
|
+
"""
|
|
14
|
+
Dependency injection container.
|
|
15
|
+
|
|
16
|
+
The container builds a dependency graph from registered components
|
|
17
|
+
and resolves dependencies using the Rust-backed core.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self) -> None:
|
|
21
|
+
"""Initialize the container."""
|
|
22
|
+
self._rust_core = RustContainer()
|
|
23
|
+
|
|
24
|
+
def register_instance(self, component_type: type[T], instance: T) -> None:
|
|
25
|
+
"""
|
|
26
|
+
Register a pre-created instance for a given type.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
component_type: Type to register
|
|
30
|
+
instance: Pre-created instance to return for this type
|
|
31
|
+
|
|
32
|
+
Raises:
|
|
33
|
+
KeyError: If type is already registered
|
|
34
|
+
"""
|
|
35
|
+
self._rust_core.register_instance(component_type, instance)
|
|
36
|
+
|
|
37
|
+
def register_class(self, component_type: type[T], implementation: type[T]) -> None:
|
|
38
|
+
"""
|
|
39
|
+
Register a class to instantiate for a given type.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
component_type: Type to register
|
|
43
|
+
implementation: Class to instantiate (calls __init__ with no args)
|
|
44
|
+
|
|
45
|
+
Raises:
|
|
46
|
+
KeyError: If type is already registered
|
|
47
|
+
"""
|
|
48
|
+
self._rust_core.register_class(component_type, implementation)
|
|
49
|
+
|
|
50
|
+
def register_factory(self, component_type: type[T], factory: Callable[[], T]) -> None:
|
|
51
|
+
"""
|
|
52
|
+
Register a factory function for a given type.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
component_type: Type to register
|
|
56
|
+
factory: Callable that returns an instance (called with no args)
|
|
57
|
+
|
|
58
|
+
Raises:
|
|
59
|
+
KeyError: If type is already registered
|
|
60
|
+
"""
|
|
61
|
+
self._rust_core.register_factory(component_type, factory)
|
|
62
|
+
|
|
63
|
+
def resolve(self, component_type: type[T]) -> T:
|
|
64
|
+
"""
|
|
65
|
+
Resolve a component instance.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
component_type: Type to resolve
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Instance of the requested type
|
|
72
|
+
|
|
73
|
+
Raises:
|
|
74
|
+
KeyError: If type is not registered
|
|
75
|
+
"""
|
|
76
|
+
return self._rust_core.resolve(component_type)
|
|
77
|
+
|
|
78
|
+
def is_empty(self) -> bool:
|
|
79
|
+
"""
|
|
80
|
+
Check if container has no registered providers.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
True if container is empty, False otherwise
|
|
84
|
+
"""
|
|
85
|
+
return self._rust_core.is_empty()
|
|
86
|
+
|
|
87
|
+
def __len__(self) -> int:
|
|
88
|
+
"""
|
|
89
|
+
Get count of registered providers.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Number of registered providers
|
|
93
|
+
"""
|
|
94
|
+
return len(self._rust_core)
|
|
95
|
+
|
|
96
|
+
def scan(self) -> None:
|
|
97
|
+
"""
|
|
98
|
+
Discover and register all @component decorated classes.
|
|
99
|
+
|
|
100
|
+
This method finds all classes marked with the @component decorator
|
|
101
|
+
and registers them with the container, automatically setting up
|
|
102
|
+
dependency injection based on type hints.
|
|
103
|
+
|
|
104
|
+
Components are registered as singletons by default.
|
|
105
|
+
"""
|
|
106
|
+
from dioxide.decorators import _get_registered_components
|
|
107
|
+
from dioxide.scope import Scope
|
|
108
|
+
|
|
109
|
+
for component_class in _get_registered_components():
|
|
110
|
+
# Create a factory that auto-injects dependencies
|
|
111
|
+
factory = self._create_auto_injecting_factory(component_class)
|
|
112
|
+
|
|
113
|
+
# Check the scope
|
|
114
|
+
scope = getattr(component_class, '__rivet_scope__', Scope.SINGLETON)
|
|
115
|
+
|
|
116
|
+
if scope == Scope.SINGLETON:
|
|
117
|
+
# Wrap the factory in a singleton wrapper
|
|
118
|
+
singleton_factory = self._create_singleton_factory(factory)
|
|
119
|
+
self.register_factory(component_class, singleton_factory)
|
|
120
|
+
else:
|
|
121
|
+
# For non-singletons, just register the factory
|
|
122
|
+
self.register_factory(component_class, factory)
|
|
123
|
+
|
|
124
|
+
def _create_singleton_factory(self, factory: Callable[[], T]) -> Callable[[], T]:
|
|
125
|
+
"""
|
|
126
|
+
Wrap a factory function to return the same instance each time.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
factory: The factory function to wrap
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
A factory that caches the first instance and returns it on subsequent calls
|
|
133
|
+
"""
|
|
134
|
+
instance_holder: list[T] = [] # Use list to avoid closure issues
|
|
135
|
+
|
|
136
|
+
def singleton_wrapper() -> T:
|
|
137
|
+
if not instance_holder:
|
|
138
|
+
instance_holder.append(factory())
|
|
139
|
+
return instance_holder[0]
|
|
140
|
+
|
|
141
|
+
return singleton_wrapper
|
|
142
|
+
|
|
143
|
+
def _create_auto_injecting_factory(self, cls: type[T]) -> Callable[[], T]:
|
|
144
|
+
"""
|
|
145
|
+
Create a factory function that auto-injects dependencies from type hints.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
cls: The class to create a factory for
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
A factory function that resolves dependencies and instantiates the class
|
|
152
|
+
"""
|
|
153
|
+
try:
|
|
154
|
+
init_signature = inspect.signature(cls.__init__)
|
|
155
|
+
type_hints = get_type_hints(cls.__init__)
|
|
156
|
+
except (ValueError, AttributeError):
|
|
157
|
+
# No __init__ or no type hints - just instantiate directly
|
|
158
|
+
return cls
|
|
159
|
+
|
|
160
|
+
# Build factory that resolves dependencies
|
|
161
|
+
def factory() -> T:
|
|
162
|
+
kwargs: dict[str, Any] = {}
|
|
163
|
+
for param_name in init_signature.parameters:
|
|
164
|
+
if param_name == 'self':
|
|
165
|
+
continue
|
|
166
|
+
if param_name in type_hints:
|
|
167
|
+
dependency_type = type_hints[param_name]
|
|
168
|
+
kwargs[param_name] = self.resolve(dependency_type)
|
|
169
|
+
return cls(**kwargs)
|
|
170
|
+
|
|
171
|
+
return factory
|
dioxide/decorators.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Decorator for marking classes as DI components."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, TypeVar
|
|
4
|
+
|
|
5
|
+
from dioxide.scope import Scope
|
|
6
|
+
|
|
7
|
+
T = TypeVar('T')
|
|
8
|
+
|
|
9
|
+
# Global registry for @component decorated classes
|
|
10
|
+
_component_registry: set[type[Any]] = set()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def component(
|
|
14
|
+
cls: type[T] | None = None,
|
|
15
|
+
*,
|
|
16
|
+
scope: Scope = Scope.SINGLETON,
|
|
17
|
+
) -> type[T] | Any:
|
|
18
|
+
"""
|
|
19
|
+
Mark a class as a dependency injection component.
|
|
20
|
+
|
|
21
|
+
Can be used with or without arguments:
|
|
22
|
+
@component
|
|
23
|
+
class Service:
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
@component(scope=Scope.FACTORY)
|
|
27
|
+
class Factory:
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
cls: The class being decorated (when used without parentheses)
|
|
32
|
+
scope: Lifecycle scope (SINGLETON or FACTORY), defaults to SINGLETON
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Decorated class with DI metadata
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def decorator(target_cls: type[T]) -> type[T]:
|
|
39
|
+
# Store DI metadata on the class
|
|
40
|
+
target_cls.__rivet_scope__ = scope # type: ignore[attr-defined]
|
|
41
|
+
# Add to global registry for auto-discovery
|
|
42
|
+
_component_registry.add(target_cls)
|
|
43
|
+
return target_cls
|
|
44
|
+
|
|
45
|
+
# Support both @component and @component()
|
|
46
|
+
if cls is None:
|
|
47
|
+
# Called with arguments: @component(scope=...)
|
|
48
|
+
return decorator
|
|
49
|
+
else:
|
|
50
|
+
# Called without arguments: @component
|
|
51
|
+
return decorator(cls)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _get_registered_components() -> set[type[Any]]:
|
|
55
|
+
"""Internal: Get all registered component classes."""
|
|
56
|
+
return _component_registry.copy()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _clear_registry() -> None:
|
|
60
|
+
"""Internal: Clear the component registry (for testing)."""
|
|
61
|
+
_component_registry.clear()
|
dioxide/py.typed
ADDED
|
File without changes
|
dioxide/scope.py
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dioxide
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Classifier: Development Status :: 3 - Alpha
|
|
5
|
+
Classifier: Intended Audience :: Developers
|
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Classifier: Programming Language :: Rust
|
|
12
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
13
|
+
Classifier: Typing :: Typed
|
|
14
|
+
Requires-Dist: pytest>=8.0 ; extra == 'dev'
|
|
15
|
+
Requires-Dist: pytest-cov>=4.1 ; extra == 'dev'
|
|
16
|
+
Requires-Dist: behave>=1.2.6 ; extra == 'dev'
|
|
17
|
+
Requires-Dist: mypy>=1.8 ; extra == 'dev'
|
|
18
|
+
Requires-Dist: ruff>=0.1 ; extra == 'dev'
|
|
19
|
+
Requires-Dist: isort>=5.13 ; extra == 'dev'
|
|
20
|
+
Requires-Dist: tox>=4.0 ; extra == 'dev'
|
|
21
|
+
Requires-Dist: pre-commit>=3.0 ; extra == 'dev'
|
|
22
|
+
Requires-Dist: mutmut>=2.4 ; extra == 'dev'
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Summary: Fast, Rust-backed declarative dependency injection for Python
|
|
26
|
+
Keywords: dependency-injection,di,ioc,rust,container
|
|
27
|
+
Author-email: Mike Lane <mikelane@gmail.com>
|
|
28
|
+
License: MIT
|
|
29
|
+
Requires-Python: >=3.11
|
|
30
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
31
|
+
Project-URL: Homepage, https://github.com/mikelane/dioxide
|
|
32
|
+
Project-URL: Repository, https://github.com/mikelane/dioxide
|
|
33
|
+
Project-URL: Issues, https://github.com/mikelane/dioxide/issues
|
|
34
|
+
|
|
35
|
+
# dioxide
|
|
36
|
+
|
|
37
|
+
**Fast, Rust-backed declarative dependency injection for Python**
|
|
38
|
+
|
|
39
|
+
[](https://github.com/mikelane/dioxide/actions)
|
|
40
|
+
[](https://pypi.org/project/dioxide/)
|
|
41
|
+
[](https://opensource.org/licenses/MIT)
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Overview
|
|
46
|
+
|
|
47
|
+
`dioxide` is a dependency injection framework for Python that combines:
|
|
48
|
+
|
|
49
|
+
- **Declarative Python API** - Simple decorators and type hints
|
|
50
|
+
- **Rust-backed performance** - Fast graph construction and resolution via PyO3
|
|
51
|
+
- **Type safety** - Full support for mypy and type checkers
|
|
52
|
+
- **Clean architecture** - Encourages loose coupling and testability
|
|
53
|
+
|
|
54
|
+
## Status
|
|
55
|
+
|
|
56
|
+
🚧 **Work in Progress** - Currently implementing the v0.1 Walking Skeleton.
|
|
57
|
+
|
|
58
|
+
See [Issues](https://github.com/mikelane/dioxide/issues) and [Milestones](https://github.com/mikelane/dioxide/milestones) for current progress.
|
|
59
|
+
|
|
60
|
+
## Vision
|
|
61
|
+
|
|
62
|
+
Traditional Python DI frameworks like `dependency-injector` are feature-rich but can be slow with large dependency graphs. `dioxide` aims to provide:
|
|
63
|
+
|
|
64
|
+
1. **Fast graph construction** using Rust's `petgraph`
|
|
65
|
+
2. **Type-based resolution** via Python's `__annotations__`
|
|
66
|
+
3. **Lifecycle management** with proper shutdown ordering
|
|
67
|
+
4. **Clear error messages** for missing dependencies and cycles
|
|
68
|
+
|
|
69
|
+
## Quick Start (Planned API)
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from dioxide import Container, Scope, component
|
|
73
|
+
|
|
74
|
+
@component(scope=Scope.SINGLETON)
|
|
75
|
+
class DatabaseConnection:
|
|
76
|
+
def __init__(self, connection_string: str):
|
|
77
|
+
self.connection_string = connection_string
|
|
78
|
+
|
|
79
|
+
@component(scope=Scope.SINGLETON)
|
|
80
|
+
class UserRepository:
|
|
81
|
+
def __init__(self, db: DatabaseConnection):
|
|
82
|
+
self.db = db
|
|
83
|
+
|
|
84
|
+
# Create container and register components
|
|
85
|
+
container = Container()
|
|
86
|
+
container.register_value('connection_string', 'postgresql://localhost/mydb')
|
|
87
|
+
container.register(DatabaseConnection)
|
|
88
|
+
container.register(UserRepository)
|
|
89
|
+
|
|
90
|
+
# Resolve dependencies
|
|
91
|
+
repo = container.resolve(UserRepository)
|
|
92
|
+
# repo.db is automatically injected
|
|
93
|
+
|
|
94
|
+
# Clean shutdown
|
|
95
|
+
container.shutdown()
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Features
|
|
99
|
+
|
|
100
|
+
### v0.1 Walking Skeleton (In Progress)
|
|
101
|
+
- [x] Basic project structure
|
|
102
|
+
- [ ] Type-based dependency resolution
|
|
103
|
+
- [ ] Singleton and factory scopes
|
|
104
|
+
- [ ] Value injection by parameter name
|
|
105
|
+
- [ ] Duplicate registration prevention
|
|
106
|
+
- [ ] Clear error messages
|
|
107
|
+
|
|
108
|
+
### v0.2 Core Features (Planned)
|
|
109
|
+
- [ ] Named tokens for disambiguation
|
|
110
|
+
- [ ] Circular dependency detection
|
|
111
|
+
- [ ] Graceful shutdown with reverse ordering
|
|
112
|
+
- [ ] Comprehensive test coverage (>95%)
|
|
113
|
+
- [ ] Mutation testing with `mutmut`
|
|
114
|
+
|
|
115
|
+
### Future Enhancements (Backlog)
|
|
116
|
+
- [ ] Conditional registration
|
|
117
|
+
- [ ] Provider functions
|
|
118
|
+
- [ ] Property injection
|
|
119
|
+
- [ ] Performance benchmarks vs. `dependency-injector`
|
|
120
|
+
- [ ] Documentation site
|
|
121
|
+
|
|
122
|
+
## Development
|
|
123
|
+
|
|
124
|
+
### Prerequisites
|
|
125
|
+
|
|
126
|
+
- Python 3.11+
|
|
127
|
+
- Rust 1.70+
|
|
128
|
+
- [uv](https://github.com/astral-sh/uv) for Python package management
|
|
129
|
+
- [maturin](https://github.com/PyO3/maturin) for building Rust extensions
|
|
130
|
+
|
|
131
|
+
### Setup
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# Clone the repository
|
|
135
|
+
git clone https://github.com/mikelane/dioxide.git
|
|
136
|
+
cd dioxide
|
|
137
|
+
|
|
138
|
+
# Install dependencies with uv
|
|
139
|
+
uv venv
|
|
140
|
+
source .venv/bin/activate # or `.venv\Scripts\activate` on Windows
|
|
141
|
+
uv pip install -e ".[dev]"
|
|
142
|
+
|
|
143
|
+
# Build the Rust extension
|
|
144
|
+
maturin develop
|
|
145
|
+
|
|
146
|
+
# Run tests
|
|
147
|
+
pytest
|
|
148
|
+
|
|
149
|
+
# Run all quality checks
|
|
150
|
+
tox
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Development Workflow
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Format code
|
|
157
|
+
tox -e format
|
|
158
|
+
|
|
159
|
+
# Lint
|
|
160
|
+
tox -e lint
|
|
161
|
+
|
|
162
|
+
# Type check
|
|
163
|
+
tox -e type
|
|
164
|
+
|
|
165
|
+
# Run tests for all Python versions
|
|
166
|
+
tox
|
|
167
|
+
|
|
168
|
+
# Run tests with coverage
|
|
169
|
+
tox -e cov
|
|
170
|
+
|
|
171
|
+
# Mutation testing
|
|
172
|
+
tox -e mutate
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Pre-commit Hooks
|
|
176
|
+
|
|
177
|
+
Install pre-commit hooks to ensure code quality:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
pre-commit install
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Architecture
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
dioxide/
|
|
187
|
+
├── python/dioxide/ # Python API
|
|
188
|
+
│ ├── __init__.py
|
|
189
|
+
│ ├── container.py # Main Container class
|
|
190
|
+
│ ├── decorators.py # @component decorator
|
|
191
|
+
│ └── scope.py # Scope enum
|
|
192
|
+
├── rust/src/ # Rust core
|
|
193
|
+
│ └── lib.rs # PyO3 bindings and graph logic
|
|
194
|
+
├── tests/ # Python tests
|
|
195
|
+
└── pyproject.toml # Project configuration
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Key Design Decisions
|
|
199
|
+
|
|
200
|
+
1. **Rust for graph operations** - Dependency graphs can get complex; Rust's performance and safety help scale
|
|
201
|
+
2. **Python-first API** - Developers work in pure Python; Rust is an implementation detail
|
|
202
|
+
3. **Type hints as the contract** - Leverage Python's type system for DI metadata
|
|
203
|
+
4. **Explicit over implicit** - Registration is manual to avoid surprises
|
|
204
|
+
5. **Test-driven development** - Every feature starts with failing tests
|
|
205
|
+
|
|
206
|
+
## Comparison to Other Frameworks
|
|
207
|
+
|
|
208
|
+
| Feature | dioxide | dependency-injector | injector |
|
|
209
|
+
|---------|----------|---------------------|----------|
|
|
210
|
+
| Type-based DI | ✅ | ✅ | ✅ |
|
|
211
|
+
| Rust-backed | ✅ | ❌ | ❌ |
|
|
212
|
+
| Scopes | ✅ | ✅ | ✅ |
|
|
213
|
+
| Lifecycle | ✅ | ✅ | ❌ |
|
|
214
|
+
| Cycle detection | ✅ (planned) | ❌ | ❌ |
|
|
215
|
+
| Performance* | 🚀 (goal) | ⚡ | ⚡ |
|
|
216
|
+
|
|
217
|
+
*Benchmarks coming in v0.2
|
|
218
|
+
|
|
219
|
+
## Contributing
|
|
220
|
+
|
|
221
|
+
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
222
|
+
|
|
223
|
+
### Roadmap
|
|
224
|
+
|
|
225
|
+
- v0.1: Walking skeleton with basic DI
|
|
226
|
+
- v0.2: Production-ready core features
|
|
227
|
+
- v0.3: Performance optimization and benchmarks
|
|
228
|
+
- v1.0: Stable API
|
|
229
|
+
|
|
230
|
+
## License
|
|
231
|
+
|
|
232
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
233
|
+
|
|
234
|
+
## Acknowledgments
|
|
235
|
+
|
|
236
|
+
- Inspired by [dependency-injector](https://github.com/ets-labs/python-dependency-injector) and Spring Framework
|
|
237
|
+
- Built with [PyO3](https://github.com/PyO3/pyo3) and [maturin](https://github.com/PyO3/maturin)
|
|
238
|
+
- Graph algorithms powered by [petgraph](https://github.com/petgraph/petgraph)
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
**Note**: This project is under active development. APIs may change before v1.0.
|
|
243
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
dioxide-0.1.0.dist-info/METADATA,sha256=udsDz2a8K_cgarNh_Txl_u1jm_wiU_xXf-K258wPctI,7212
|
|
2
|
+
dioxide-0.1.0.dist-info/WHEEL,sha256=kelVgS1CONjYuT6OEIC92ofaP9Aiw74EQCpLzMjs2Gg,103
|
|
3
|
+
dioxide-0.1.0.dist-info/licenses/LICENSE,sha256=JpEmJvRYOTIUt0UjgvpDrd3U94Wnbt_Grr5z-xU2jtk,1066
|
|
4
|
+
dioxide/__init__.py,sha256=YULuPVqRmnBmFFRx9vMM7MAV4LKJmertLobbhFc7utA,357
|
|
5
|
+
dioxide/_dioxide_core.abi3.so,sha256=treUgOU1PvwrtEHBdMRNz-wsk6DOvnEwYsjbdHA4Nd0,472912
|
|
6
|
+
dioxide/_rivet_core.pyi,sha256=duJvzENpwRtl9HZIjLYrVIbCkMZscCKeVvIgEaAgnQk,594
|
|
7
|
+
dioxide/container.py,sha256=dU3d0nhjiHTPT08z0kYkNujEcLq2WvO9-Gqjdzr8xh0,5549
|
|
8
|
+
dioxide/decorators.py,sha256=EAxMn_HbudrH6V1bREb-dFOzkcRMBK9MlLPww9uALT4,1616
|
|
9
|
+
dioxide/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
dioxide/scope.py,sha256=C6pAAVwNu04CSwUyIphCwOlec9DPAMWT8Q4Js48HGkE,174
|
|
11
|
+
dioxide-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Mike Lane
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|