
Research
Security News
The Growing Risk of Malicious Browser Extensions
Socket researchers uncover how browser extensions in trusted stores are used to hijack sessions, redirect traffic, and manipulate user behavior.
Performant, concise and type-safe Dependency Injection for Python 3.8+
[!NOTE]
Wireup 1.0 has been released, featuring support for scoped lifetimes, a simplified API, enhanced type safety, and improved documentation. Refer to the Upgrading Guide for instructions on upgrading from version 0.x to 1.0.
Dependency Injection (DI) is a design pattern where dependencies are provided externally rather than created within objects. Wireup automates dependency management using Python's type system, with support for async, generators and modern Python features.
Inject services and configuration using a clean and intuitive syntax.
@service
class Database:
pass
@service
class UserService:
def __init__(self, db: Database) -> None:
self.db = db
container = wireup.create_sync_container(services=[Database, UserService])
user_service = container.get(UserService) # โ
Dependencies resolved.
@service
class Database:
def __init__(self, db_url: Annotated[str, Inject(param="db_url")]) -> None:
self.db_url = db_url
container = wireup.create_sync_container(
services=[Database],
parameters={"db_url": os.environ["APP_DB_URL"]}
)
database = container.get(Database) # โ
Dependencies resolved.
Inject dependencies directly into functions with a simple decorator.
@inject_from_container(container)
def process_users(service: Injected[UserService]):
# โ
UserService injected.
pass
Define abstract types and have the container automatically inject the implementation.
@abstract
class Notifier(abc.ABC):
pass
@service
class SlackNotifier(Notifier):
pass
notifier = container.get(Notifier)
# โ
SlackNotifier instance.
Declare dependencies as singletons, scoped, or transient to control whether to inject a fresh copy or reuse existing instances.
# Singleton: One instance per application. `@service(lifetime="singleton")` is the default.
@service
class Database:
pass
# Scoped: One instance per scope/request, shared within that scope/request.
@service(lifetime="scoped")
class RequestContext:
def __init__(self) -> None:
self.request_id = uuid4()
# Transient: When full isolation and clean state is required.
# Every request to create transient services results in a new instance.
@service(lifetime="transient")
class OrderProcessor:
pass
Defer instantiation to specialized factories when complex initialization or cleanup is required. Full support for async and generators. Wireup handles cleanup at the correct time depending on the service lifetime.
Synchronous
class WeatherClient:
def __init__(self, client: requests.Session) -> None:
self.client = client
@service
def weather_client_factory() -> Iterator[WeatherClient]:
with requests.Session() as session:
yield WeatherClient(client=session)
Async
class WeatherClient:
def __init__(self, client: aiohttp.ClientSession) -> None:
self.client = client
@service
async def weather_client_factory() -> AsyncIterator[WeatherClient]:
async with aiohttp.ClientSession() as session:
yield WeatherClient(client=session)
Wireup is mypy strict compliant and will not introduce type errors in your code. It will also warn you at the earliest possible stage about configuration errors to avoid surprises.
Container Creation
The container will raise errors at creation time about missing dependencies or other issues.
@service
class Foo:
def __init__(self, unknown: NotManagedByWireup) -> None:
pass
container = wireup.create_sync_container(services=[Foo])
# โ Parameter 'unknown' of 'Foo' depends on an unknown service 'NotManagedByWireup'.
Function Injection
Injected functions will raise errors at module import time rather than when called.
@inject_from_container(container)
def my_function(oops: Injected[NotManagedByWireup]):
pass
# โ Parameter 'oops' of 'my_function' depends on an unknown service 'NotManagedByWireup'.
Integrations
Wireup integrations assert that requested injections in the framework are valid.
@app.get("/")
def home(foo: Injected[NotManagedByWireup]):
pass
wireup.integration.flask.setup(container, app)
# โ Parameter 'foo' of 'home' depends on an unknown service 'NotManagedByWireup'.
Wireup provides its own Dependency Injection mechanism and is not tied to specific frameworks. Use it anywhere you like.
Share the service layer between your web application and its accompanying CLI using Wireup.
Integrate with popular frameworks for a smoother developer experience. Integrations manage request scopes, injection in endpoints, and lifecycle of services.
app = FastAPI()
container = wireup.create_async_container(services=[UserService, Database])
@app.get("/")
def users_list(user_service: Injected[UserService]):
pass
wireup.integration.fastapi.setup(container, app)
Wireup does not patch your services and lets you test them in isolation.
If you need to use the container in your tests, you can have it create parts of your services or perform dependency substitution.
with container.override.service(target=Database, new=in_memory_database):
# The /users endpoint depends on Database.
# During the lifetime of this context manager, requests to inject `Database`
# will result in `in_memory_database` being injected instead.
response = client.get("/users")
For more information check out the documentation
A demo flask application is available at maldoinc/wireup-demo
FAQs
Python Dependency Injection Library
We found that wireup demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.ย It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover how browser extensions in trusted stores are used to hijack sessions, redirect traffic, and manipulate user behavior.
Research
Security News
An in-depth analysis of credential stealers, crypto drainers, cryptojackers, and clipboard hijackers abusing open source package registries to compromise Web3 development environments.
Security News
pnpm 10.12.1 introduces a global virtual store for faster installs and new options for managing dependencies with version catalogs.