Add and share a provider

Register a provider, export it, and consume it from another module.

Register it#

@Module(controllers=[TaskController], providers=[TaskService])
class TaskModule:
    pass

Share it with another module#

Providers are private by default. Export to share:

@Module(
    controllers=[TaskController],
    providers=[TaskService],
    exports=[TaskService],
)
class TaskModule:
    pass
@Module(imports=[TaskModule], controllers=[ReportController])
class ReportModule:
    pass

Provide a value or a factory#

from bustan import Module, Provider

def make_client(settings: Settings) -> ApiClient:
    return ApiClient(base_url=settings.api_url, timeout=5.0)

@Module(
    providers=[
        Provider(token="SETTINGS", value=Settings()),
        Provider(provide=ApiClient, factory=make_client, inject=[Settings]),
    ],
    exports=[ApiClient],
)
class ClientModule:
    pass

Async factories#

New in 0.0.2 — a factory may be a coroutine, awaited once during startup:

async def make_pool(settings: Settings) -> Pool:
    return await create_pool(settings.database_url)

Provider(provide=Pool, factory=make_pool, inject=[Settings])

Scopes#

By default a provider is a singleton. To get one per request:

Provider(provide=RequestContext, factory=make_context, scope="request")

Use request scope sparingly. A request-scoped provider cannot be injected into a singleton — the container rejects it at startup, because the singleton would capture the first request's instance forever.

Common error#

BustanResolutionError: TaskService is not available to ReportController.
  ReportModule imports [TaskModule]
  TaskModule exports []
  hint: add TaskService to TaskModule's exports