core.container.providers¶
src.core.container.providers
¶
Provider dependency factory (Registry-driven).
Factory for creating financial provider adapters based on slug. Single factory (get_provider) with capability checking (is_oauth_provider).
Registry-Driven Pattern (F8.1): - Provider metadata stored in domain/providers/registry.py - Container uses registry for lookup and validation - Zero drift: Can't forget to add provider to OAuth list - Self-enforcing: Tests fail if registry/factory mismatch
Usage
- get_provider(): Returns any provider by slug (auth-agnostic)
- is_oauth_provider(): TypeGuard for OAuth capability checking
Pattern
For sync handlers (all providers)¶
provider = get_provider("schwab") result = await provider.fetch_accounts(credentials)
For OAuth callbacks (OAuth providers only)¶
provider = get_provider("schwab") if is_oauth_provider(provider): tokens = await provider.exchange_code_for_tokens(code)
Reference
See docs/architecture/provider-registry-architecture.md for registry pattern. See docs/architecture/provider-integration-architecture.md for integration.
Attributes¶
Classes¶
Functions¶
get_provider
¶
Get financial provider adapter by slug (registry-driven).
Factory function that returns the correct provider implementation based on the provider slug from registry. Follows Composition Root pattern.
Registry-Driven (F8.1): - Looks up provider metadata from PROVIDER_REGISTRY - Validates required settings via metadata.required_settings - Ensures zero drift between registry and factory
This returns providers typed as ProviderProtocol (auth-agnostic). For OAuth-specific operations, use is_oauth_provider() to check capability.
Currently supported providers (from registry): - 'schwab': Charles Schwab (OAuth, brokerage) - 'alpaca': Alpaca Markets (API Key, brokerage) - 'chase_file': Chase Bank (File Import, bank)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slug
|
str
|
Provider identifier (e.g., 'schwab', 'alpaca'). |
required |
Returns:
| Type | Description |
|---|---|
ProviderProtocol
|
Provider adapter implementing ProviderProtocol. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If provider slug is unknown or provider not configured. |
Usage
Sync handlers (auth-agnostic - works for all providers)¶
from src.core.container import get_provider provider = get_provider("schwab") result = await provider.fetch_accounts(credentials)
OAuth callbacks (check capability first)¶
provider = get_provider("schwab") if is_oauth_provider(provider): tokens = await provider.exchange_code_for_tokens(code)
Reference
- docs/architecture/provider-registry-architecture.md
- docs/architecture/provider-integration-architecture.md
Source code in src/core/container/providers.py
is_oauth_provider
¶
Check if provider supports OAuth authentication (registry-driven).
TypeGuard function that performs runtime check and narrows type. After this returns True, the provider is typed as OAuthProviderProtocol.
Registry-Driven (F8.1): - Uses get_oauth_providers() from registry - Zero drift: OAuth list always in sync with registry - Self-enforcing: Tests verify OAuth providers match reality
Use this to check provider capabilities before calling OAuth methods
- exchange_code_for_tokens()
- refresh_access_token()
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
provider
|
ProviderProtocol
|
Any provider instance. |
required |
Returns:
| Type | Description |
|---|---|
TypeGuard[OAuthProviderProtocol]
|
True if provider supports OAuth (has exchange_code_for_tokens method). |
TypeGuard[OAuthProviderProtocol]
|
Type is narrowed to OAuthProviderProtocol when True. |
Usage
In OAuth callback handler:¶
provider = get_provider(slug) if is_oauth_provider(provider): # Type is now OAuthProviderProtocol tokens = await provider.exchange_code_for_tokens(code) else: raise ValueError(f"Provider {slug} doesn't support OAuth")
In token refresh handler:¶
provider = get_provider(connection.provider_slug) if is_oauth_provider(provider): result = await provider.refresh_access_token(refresh_token) else: # API Key providers don't need token refresh return Success("No refresh needed")
Reference
- docs/architecture/provider-registry-architecture.md
- docs/architecture/provider-integration-architecture.md