https://github.com/frostime/simple-inject-py
A lightweight dependency injection library for Python
https://github.com/frostime/simple-inject-py
dependency-injection inversion-of-control pip provide-inject python
Last synced: 4 months ago
JSON representation
A lightweight dependency injection library for Python
- Host: GitHub
- URL: https://github.com/frostime/simple-inject-py
- Owner: frostime
- License: mit
- Created: 2024-09-13T13:41:12.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2025-08-12T11:28:40.000Z (10 months ago)
- Last Synced: 2025-09-01T01:03:50.535Z (10 months ago)
- Topics: dependency-injection, inversion-of-control, pip, provide-inject, python
- Language: Python
- Homepage: https://pypi.org/project/py-simple-inject/
- Size: 51.8 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Simple Inject
[中文 README](README_zh.md)
Simple Inject is a lightweight Python dependency injection library. It provides an easy-to-use interface for managing dependencies across different namespaces and scopes.
## Features
- Simple and intuitive dependency injection API
- Supports multiple namespaces to isolate dependencies
- Implements scoped dependencies using context managers or decorators
- Supports nested scopes for fine-grained control
- Supports automatic dependency injection through parameters
- Easy integration with existing projects
- Minimal overhead and dependencies
## Installation
You can install Simple Inject using pip:
```
pip install py-simple-inject
```
## Quick Start
### Basic Usage
Here is a simple example demonstrating basic dependency injection and scope management:
```python
from simple_inject import provide, inject, create_scope
# Provide a dependency
provide('config', {'debug': True})
# Inject a dependency
config = inject('config')
print(config['debug']) # Output: True
```
### Using Namespaces
```py
from simple_inject import provide, inject, create_scope
provide('key', 'value1', namespace='ns1')
provide('key', 'value2', namespace='ns2')
print(inject('key', namespace='ns1')) # Output: value1
print(inject('key', namespace='ns2')) # Output: value2
```
### Using Scopes
```py
provide('config', {'debug': True})
# Use scopes to manage dependencies
with create_scope():
provide('config', {'debug': False})
config = inject('config')
print(config['debug']) # Output: False
# Outside the scope, the original value is preserved
config = inject('config')
print(config['debug']) # Output: True
```
Scopes can also be used with the `scoped` decorator:
```py
@scoped()
def scoped_function():
provide('key', 'scoped_value')
return inject('key')
provide('key', 'outer_value')
print(inject('key')) # Output: outer_value
print(scoped_function()) # Output: scoped_value
print(inject('key')) # Output: outer_value
```
### Nested Scopes
Scoped scopes can be nested, and dependencies in inner scopes will override those in outer scopes.
```python
provide('key', 'outer')
with create_scope():
provide('key', 'inner')
print(inject('key')) # Output: inner
with create_scope() as inner_scope:
provide('key', 'innermost')
print(inject('key')) # Output: innermost
print(inject('key')) # Output: inner
print(inject('key')) # Output: outer
```
### Accessing Scoped State
You can access the state of dependencies within a scope after it exits using the `scoped_state` method:
```python
provide('config', {'debug': True})
with create_scope() as scope:
provide('config', {'debug': False})
provide('new_setting', 'scoped_value')
# Get only the dependencies that were added or modified in the scope
provided_state = scope.scoped_state('Provided') # Default policy
print(provided_state)
# Output: {'default': {'config': {'debug': False}, 'new_setting': 'scoped_value'}}
# Get the complete state within the scope
all_state = scope.scoped_state('All')
print(all_state)
# Output: {'default': {'config': {'debug': False}, 'new_setting': 'scoped_value'}}
# Get state for a specific namespace
with create_scope() as scope:
provide('key1', 'value1', namespace='ns1')
provide('key2', 'value2', namespace='ns2')
ns1_state = scope.scoped_state('Provided', 'ns1')
print(ns1_state) # Output: {'key1': 'value1'}
```
The `scoped_state` method supports two policies:
- `'Provided'` (default): Returns only dependencies that were added or modified within the scope
- `'All'`: Returns the complete state within the scope
### Automatic Injection via Function Parameters
Simple Inject also supports automatic injection via function parameters. The following example demonstrates how to use this advanced feature:
```python
from simple_inject import provide, inject, create_scope, auto_inject, Inject
class Engine:
def start(self):
print("Engine started")
# Provide a dependency
provide('engine', Engine())
# Manually inject a dependency
engine = inject('engine')
engine.start() # Output: Engine started
# Use automatic injection
@auto_inject()
def drive(car: str, engine: Engine = Inject('engine')):
print(f"Driving {car}")
engine.start()
drive("Tesla") # Output: Driving Tesla and Engine started
# Use scopes to manage dependencies
with create_scope():
provide('engine', Engine()) # Provide a new Engine instance
drive("BMW") # Output: Driving BMW and Engine started
# Outside the scope, the original value is preserved
drive("Toyota") # Output: Driving Toyota and Engine started
```
## API Reference
### `provide(key: str, value: Any, namespace: str = 'default')`
Provides a dependency in the current context.
### `inject(key: str, namespace: str = 'default') -> Any`
Injects a dependency from the current context.
### `create_scope()`
Creates a new dependency scope. Used with the `with` statement.
### `scoped()`
Decorator to create a new dependency scope for a function.
### `auto_inject()`
Decorator to automatically inject parameters marked with `Inject`.
### `Inject(key: str, namespace: str = 'default')`
Class to mark a parameter for automatic injection.
### `purge(namespace: Optional[str] = None)`
Clears dependencies, either for a specific namespace or for all namespaces.
## Contributing
Contributions are welcome! Feel free to submit a Pull Request.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.