Spring style dependency injection for python
Project description
AppCtx
Spring-style dependency injection for Python
Overview
AppCtx is a lightweight dependency injection container inspired by the Spring Framework, providing a clean and elegant dependency management solution for Python applications. It makes it easy to manage dependencies and create maintainable, testable code.
Version: 0.1.0
Python Requirements: 3.8+
License: MIT
Features
- 🚀 Easy to Use - Register and inject dependencies with simple decorators
- 🔄 Auto-wiring - Automatic dependency resolution based on type annotations
- 🏗️ Flexible Configuration - Support for both function and class bean definitions
- 📦 Lightweight - Minimal dependencies, focused on core functionality
- 🐍 Pythonic - API design that follows Python conventions
- 🔧 Python 3.8+ - Compatible with Python 3.8, 3.9, 3.10, and 3.11
- 🎯 Decorator-based bean registration - Simple
@beandecorator for registration - 🔍 Circular dependency detection - Detects and reports circular dependencies
Installation
pip install appctx
Development Installation
For development, clone the repository and install with development dependencies:
git clone https://github.com/wssccc/appctx.git
cd appctx
pip install -e .[dev]
This will install the following development tools:
pytest>=7.0- Testing frameworkpytest-cov>=4.0- Coverage reportingblack>=22.0- Code formattingflake8>=5.0- Lintingmypy>=1.0- Type checkingisort>=5.0- Import sorting
Basic Concepts
AppCtx provides a simple way to manage dependencies in your Python applications:
- Beans: Objects managed by the container
- Container: The
ApplicationContextthat manages beans - Dependency Injection: Automatic wiring of dependencies based on type annotations
Quick Start
Basic Usage
from appctx import bean, get_bean, refresh
# Define service classes
class DatabaseService:
def __init__(self, connection_string: str = "sqlite:///default.db"):
self.connection_string = connection_string
def connect(self):
return f"Connected to {self.connection_string}"
class UserService:
def __init__(self, db: DatabaseService):
self.db = db
def get_user(self, user_id: int):
connection = self.db.connect()
return f"User {user_id} from {connection}"
# Register beans using decorators
@bean
def database_service():
return DatabaseService("postgresql://localhost/myapp")
@bean
def user_service(db: DatabaseService): # Auto-inject DatabaseService
return UserService(db)
# Initialize the container
refresh()
# Get and use beans
user_svc = get_bean(UserService)
print(user_svc.get_user(123))
Class Decorator Usage
from appctx import bean, get_bean, refresh
@bean
class EmailService:
def __init__(self):
self.server = "smtp.example.com"
def send_email(self, to: str, subject: str):
return f"Email sent to {to} via {self.server}"
@bean
class NotificationService:
def __init__(self, email: EmailService):
self.email = email
def notify(self, user: str, message: str):
return self.email.send_email(user, "Notification", message)
refresh()
notification_svc = get_bean(NotificationService)
print(notification_svc.notify("user@example.com", "Hello World!"))
How It Works
- Bean Registration: Use the
@beandecorator to register functions that create beans - Type Annotations: Use type annotations to declare dependencies
- Container Initialization: Call
refresh()to initialize the container and resolve dependencies - Bean Retrieval: Use
get_bean()to retrieve beans by type or name
Advanced Usage
Custom Application Context
from appctx import ApplicationContext
# Create custom context
ctx = ApplicationContext()
@ctx.bean
def my_service():
return MyService()
ctx.refresh()
service = ctx.get_bean(MyService)
Multiple Beans of Same Type
@bean
def primary_db():
return DatabaseService("primary://db")
@bean
def secondary_db():
return DatabaseService("secondary://db")
refresh()
# Get all database services
dbs = get_beans(DatabaseService)
print(f"Found {len(dbs)} database services")
# Get all beans of a specific type
databases = get_beans(DatabaseService)
print(len(databases)) # 2
Named Bean Retrieval
@bean
def database_service():
return DatabaseService("app.db")
refresh()
# Get bean by name (function name)
db = get_bean("database_service")
API Reference
Core Decorators
@bean
Register a function or class as a bean.
@bean
def my_service():
return MyService()
@bean
class MyComponent:
def __init__(self, dependency: SomeDependency):
self.dependency = dependency
Container Operations
refresh()
Initialize the container and instantiate all beans. Must be called before getting beans.
refresh()
get_bean(key)
Get a bean by type or name.
# Get by type
service = get_bean(MyService)
# Get by name
service = get_bean("my_service")
get_beans(type)
Get all beans of a specific type.
services = get_beans(MyService)
Dependency Resolution
AppCtx uses the following rules to resolve dependencies:
- Type Annotation Priority - If a parameter has type annotation, find bean by type
- Name Matching - If no type annotation, find bean by parameter name
- Auto-wiring - Container automatically resolves and injects dependencies
- Circular Dependency Detection - Detects and reports circular dependency issues
Error Handling
Common Errors
# Bean not found
try:
service = get_bean(UnknownService)
except KeyError as e:
print(f"Bean not found: {e}")
# Multiple beans of same type conflict
try:
refresh()
except RuntimeError as e:
print(f"Bean instantiation failed: {e}")
# Circular dependency
try:
refresh()
except RuntimeError as e:
print(f"Circular dependency detected: {e}")
Best Practices
- Use Type Annotations - Specify dependency types clearly for better code readability
- Single Responsibility - Each bean should have a clear responsibility
- Interface Abstraction - Use abstract base classes to define service interfaces
- Configuration Separation - Centralize bean configuration management
- Test-Friendly - Design beans that are easy to test
Development
Requirements
- Python 3.8 or higher
- pip
Running Tests
pytest tests/
Running Tests with Coverage
pytest --cov=src/appctx tests/
Code Formatting
Format code with Black (line length: 88):
black src/ tests/
Import Sorting
Sort imports with isort (Black profile):
isort src/ tests/
Linting
Check code quality with flake8:
flake8 src/ tests/
Type Checking
Run type checking with mypy:
mypy src/
Run All Quality Checks
# Format code
black src/ tests/
isort src/ tests/
# Run linting and type checking
flake8 src/ tests/
mypy src/
# Run tests with coverage
pytest --cov=src/appctx tests/
License
This project is licensed under the MIT License - see the LICENSE file for details.
Contributing
We welcome contributions! Please see our contributing guidelines below.
Development Setup
- Fork the project
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Create a Pull Request
Running Tests
# Run all tests
pytest
# Run tests with coverage
pytest --cov=appctx
# Run linting
black --check src/ tests/
flake8 src/ tests/
mypy src/
Release Process
For maintainers, see RELEASE.md for detailed release instructions.
Links
- Homepage: https://github.com/wssccc/appctx
- Repository: https://github.com/wssccc/appctx
- PyPI: https://pypi.org/project/appctx/
- Issues: https://github.com/wssccc/appctx/issues
Changelog
v0.1.0
- Initial release
- Basic dependency injection functionality
- Decorator API
- Auto-wiring support
- Python 3.8+ support
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file appctx-0.1.0.tar.gz.
File metadata
- Download URL: appctx-0.1.0.tar.gz
- Upload date:
- Size: 10.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b75b51f1b2dcd8779bee88b33dd18e8fa64bf7a9bb0ac586abb0e19593e9b809
|
|
| MD5 |
cdfa33314757b7fcc81fcd9c18d451ca
|
|
| BLAKE2b-256 |
86a720d520b6489bf1a3a8dec3588c2608505fe88b913b43f454ede42a82ddf4
|
Provenance
The following attestation bundles were made for appctx-0.1.0.tar.gz:
Publisher:
publish.yml on wssccc/appctx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
appctx-0.1.0.tar.gz -
Subject digest:
b75b51f1b2dcd8779bee88b33dd18e8fa64bf7a9bb0ac586abb0e19593e9b809 - Sigstore transparency entry: 536087036
- Sigstore integration time:
-
Permalink:
wssccc/appctx@5180f65fa7f38bd9ba73e49e7174670921fa931e -
Branch / Tag:
refs/tags/0.1.0-rc1 - Owner: https://github.com/wssccc
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5180f65fa7f38bd9ba73e49e7174670921fa931e -
Trigger Event:
release
-
Statement type:
File details
Details for the file appctx-0.1.0-py3-none-any.whl.
File metadata
- Download URL: appctx-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4ea22e38ecce4f3f867ebfbf76346536e6f4d9a0cf3dd65ef7a694c7a6554e9
|
|
| MD5 |
08ac9330eac4bddd322dfeb1a752b4e7
|
|
| BLAKE2b-256 |
b146cde37be4d3a95c85acb6b475547f936aaa175cf821a1936516802eebef4b
|
Provenance
The following attestation bundles were made for appctx-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on wssccc/appctx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
appctx-0.1.0-py3-none-any.whl -
Subject digest:
d4ea22e38ecce4f3f867ebfbf76346536e6f4d9a0cf3dd65ef7a694c7a6554e9 - Sigstore transparency entry: 536087051
- Sigstore integration time:
-
Permalink:
wssccc/appctx@5180f65fa7f38bd9ba73e49e7174670921fa931e -
Branch / Tag:
refs/tags/0.1.0-rc1 - Owner: https://github.com/wssccc
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5180f65fa7f38bd9ba73e49e7174670921fa931e -
Trigger Event:
release
-
Statement type: