Python Simple IoC - Dependency Injection Container

A lightweight, Pythonic dependency injection container inspired by Symfony's DependencyInjection component. This library embraces Python's philosophy of simplicity while providing powerful tools for organizing complex applications.
🎯 Why Use Dependency Injection?
Dependency injection isn't just enterprise complexity - it's a Pythonic pattern that promotes:
- Clear separation of concerns - Each class has a single responsibility
- Testability - Easy to mock dependencies for unit tests
- Flexibility - Change implementations without touching existing code
- Maintainability - Explicit dependencies make code easier to understand
This approach aligns perfectly with Python's zen: "Explicit is better than implicit" and "Readability counts".
🚀 Quick Start
Installation
pip install ioc
Basic Usage
- Define your services in a
services.yml
file:
parameters:
database_url: "sqlite:///app.db"
debug_mode: true
services:
database:
class: myapp.database.Database
arguments: ["%database_url%"]
user_repository:
class: myapp.repositories.UserRepository
arguments: ["@database"]
user_service:
class: myapp.services.UserService
arguments: ["@user_repository"]
calls:
- [set_debug, ["%debug_mode%"]]
- Use the container in your application:
import ioc
container = ioc.build(['services.yml'])
user_service = container.get('user_service')
users = user_service.get_all_users()
🏗️ Perfect for Python Projects
This library follows Python best practices:
- Configuration over code - Define dependencies in YAML, not scattered across your codebase
- Explicit dependencies - See exactly what each service needs at a glance
- No magic - Simple, predictable behavior that follows Python conventions
- Framework agnostic - Works with Flask, Django, FastAPI, or pure Python
📚 Advanced Features
Service Definitions
services:
email_service:
class: myapp.EmailService
arguments: ["@mailer", "%sender_email%"]
logger:
class: logging.Logger
arguments: ["myapp"]
calls:
- [setLevel, ["INFO"]]
- [addHandler, ["@file_handler"]]
cache_service:
class: myapp.CacheService
arguments: ["#@redis_client"]
Parameters and Environment
parameters:
log_file: "/var/log/%app_name%.log"
secret_key: "%env(SECRET_KEY)%"
redis_url: "%env(REDIS_URL):redis://localhost:6379%"
🧪 Testing Made Easy
With dependency injection, testing becomes straightforward:
import unittest
from unittest.mock import Mock
class TestUserService(unittest.TestCase):
def test_create_user(self):
mock_repo = Mock()
mock_repo.save.return_value = True
user_service = UserService(mock_repo)
result = user_service.create_user("john@example.com")
self.assertTrue(result)
mock_repo.save.assert_called_once()
📖 Learn More
🤝 Contributing
Contributions are welcome! This project follows Python community standards:
- PEP 8 code style
- Type hints for better IDE support
- Comprehensive tests
- Clear documentation
📄 License
Licensed under the Apache License 2.0. See LICENSE for details.
"Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex." - The Zen of Python
This library embodies these principles while providing the power and flexibility needed for serious Python applications.