Tips & Tricks
Reduce init boilerplate¶
Consider an order processing service that requires multiple dependencies. Here's how it looks with traditional initialization:
services/order_processor.py
@service
class OrderProcessor:
def __init__(
self,
payment_gateway: PaymentGateway,
inventory_service: InventoryService,
order_repository: OrderRepository,
):
self.payment_gateway = payment_gateway
self.inventory_service = inventory_service
self.order_repository = order_repository
Wireup lets you combine the @service
decorator with dataclasses for a more concise syntax.
services/order_processor.py
from dataclasses import dataclass
@service
@dataclass
class OrderProcessor:
payment_gateway: PaymentGateway
inventory_service: InventoryService
order_repository: OrderRepository
Using dataclasses eliminates the need to write the __init__
method and manually assign each dependency, while maintaining
type hints and making the code more maintainable.
Aliased parameters¶
If you don't like having string parameters in your service objects you can alias them instead.
def awesome_function(env: Annotated[str, Inject(param="env")]) -> None: ...
def other_awesome_function(env: Annotated[str, Inject(param="env")]) -> None: ...
Using type aliases
EnvParameter = Annotated[str, Inject(param="env")]
def awesome_function(env: EnvParameter) -> None: ...
def other_awesome_function(env: EnvParameter) -> None: ...