Injectables
An injectable is any class or function that you register with the container, making it available to be requested as a dependency. Once registered, Wireup can instantiate it, resolve its own dependencies, and inject it wherever needed.
The @injectable Decorator¶
The @injectable decorator marks a class or function for registration with the container.
from wireup import injectable
@injectable
class UserRepository: ...
from wireup import injectable
@injectable
def db_connection() -> DatabaseConnection: ...
Arguments¶
You can customize how an injectable is registered by passing arguments to the decorator:
| Argument | Description | Default |
|---|---|---|
lifetime |
Controls how long the object lives (e.g., "singleton", "scoped"). See Lifetimes. |
"singleton" |
qualifier |
A unique identifier, useful when you have multiple implementations of the same type. See Interfaces. | None |
as_type |
Register the object as a different type (like a Protocol or Base Class). See Interfaces. | None |
from wireup import injectable
@injectable(lifetime="scoped", qualifier="readonly")
class DbSession: ...
Defining Dependencies¶
Wireup resolves dependencies using Type Hints. It inspects the types you declare and automatically finds the matching injectable.
Classes¶
Standard Python classes with type-hinted __init__ methods are automatically wired. No extra configuration is needed.
from wireup import injectable
@injectable
class UserService:
# UserRepository will be injected automatically
def __init__(self, repo: UserRepository) -> None:
self.repo = repo
Factories¶
Functions can be registered as factories. This is standard for creating 3rd-party objects, when complex setup is required or for enforcing clean architecture.
See Factories and Resource Management.
import boto3
from wireup import injectable, Inject
from typing import Annotated
@injectable
def create_s3_client(
region: Annotated[str, Inject(config="aws_region")],
) -> boto3.client:
return boto3.client("s3", region_name=region)
Dataclasses¶
You can combine @injectable with @dataclass to eliminate __init__ boilerplate.
@injectable
class OrderProcessor:
def __init__(
self,
payment_gateway: PaymentGateway,
inventory_service: InventoryService,
):
self.payment_gateway = payment_gateway
self.inventory_service = inventory_service
from dataclasses import dataclass
@injectable
@dataclass
class OrderProcessor:
payment_gateway: PaymentGateway
inventory_service: InventoryService
Counter-example
Mix with caution if your class has many non-dependency fields.
@injectable
@dataclass
class Foo:
FOO_CONST = 1 # Not added to __init__ by @dataclass.
logger = logging.getLogger(__name__) # Not added to __init__ by @dataclass.
# These will be added to __init__ by @dataclass
# and marked as dependencies by Wireup.
payment_gateway: PaymentGateway
inventory_service: InventoryService
order_repository: OrderRepository
In this example, due to how the @dataclass decorator works, combining the two leads to code that's more difficult to
read, since it's not immediately obvious what are dependencies and what are class fields.
Dependencies with Default Values¶
When Wireup encounters a dependency it doesn't recognize, it normally raises an error. However, if that parameter has a default value, Wireup will skip it and let Python use the default instead.
This is useful when integrating with libraries that add their own __init__ parameters, such as Pydantic Settings:
from pydantic_settings import BaseSettings
from wireup import injectable
@injectable
class Settings(BaseSettings):
app_name: str = "myapp"
debug: bool = False
In this example, Pydantic's BaseSettings adds parameters that Wireup doesn't manage. Since they have defaults, Wireup
allows the class to be registered without errors.
Note
This only applies to parameters with explicit default values. Parameters without defaults that reference unknown types will still raise an error to catch configuration mistakes early.
Next Steps¶
- Configuration - Inject configuration values.
- Lifetimes & Scopes - Control how long objects live.
- Factories - Advanced creation logic.