fin-infra 0.1.62__tar.gz → 0.1.63__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fin_infra-0.1.62 → fin_infra-0.1.63}/PKG-INFO +1 -1
- {fin_infra-0.1.62 → fin_infra-0.1.63}/pyproject.toml +1 -1
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/banking/__init__.py +2 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/categorization/llm_layer.py +2 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/compliance/__init__.py +4 -3
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/credit/add.py +3 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/credit/experian/auth.py +3 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/credit/experian/client.py +2 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/credit/experian/provider.py +2 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/goals/add.py +2 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/goals/management.py +3 -3
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/goals/milestones.py +2 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/providers/plaid.py +2 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/providers/snaptrade.py +2 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/normalization/providers/exchangerate.py +3 -3
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/banking/plaid_client.py +4 -3
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/banking/teller_client.py +6 -6
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/brokerage/alpaca.py +5 -5
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/market/ccxt_crypto.py +5 -3
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/recurring/detectors_llm.py +2 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/recurring/insights.py +2 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/recurring/normalizer.py +2 -1
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/recurring/normalizers.py +2 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/security/encryption.py +2 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/security/pii_patterns.py +1 -1
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/utils/http.py +3 -2
- {fin_infra-0.1.62 → fin_infra-0.1.63}/LICENSE +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/README.md +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/__main__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/analytics/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/analytics/add.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/analytics/cash_flow.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/analytics/ease.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/analytics/models.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/analytics/portfolio.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/analytics/projections.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/analytics/rebalancing.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/analytics/savings.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/analytics/scenarios.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/analytics/spending.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/banking/history.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/banking/utils.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/brokerage/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/add.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/alerts.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/ease.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/models.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/scaffold_templates/README.md +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/scaffold_templates/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/scaffold_templates/models.py.tmpl +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/scaffold_templates/repository.py.tmpl +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/scaffold_templates/schemas.py.tmpl +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/templates.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/tracker.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/cashflows/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/cashflows/core.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/categorization/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/categorization/add.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/categorization/ease.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/categorization/engine.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/categorization/models.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/categorization/rules.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/categorization/taxonomy.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/chat/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/chat/ease.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/chat/planning.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/cli/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/cli/cmds/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/cli/cmds/scaffold_cmds.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/clients/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/clients/base.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/clients/plaid.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/credit/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/credit/experian/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/credit/experian/parser.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/credit/mock.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/crypto/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/crypto/insights.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/documents/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/documents/add.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/documents/analysis.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/documents/ease.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/documents/models.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/documents/ocr.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/documents/storage.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/exceptions.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/goals/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/goals/funding.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/goals/models.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/goals/scaffold_templates/README.md +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/goals/scaffold_templates/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/goals/scaffold_templates/models.py.tmpl +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/goals/scaffold_templates/repository.py.tmpl +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/goals/scaffold_templates/schemas.py.tmpl +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/insights/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/insights/aggregator.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/insights/models.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/add.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/ease.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/models.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/providers/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/providers/base.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/scaffold_templates/README.md +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/scaffold_templates/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/scaffold_templates/models.py.tmpl +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/scaffold_templates/repository.py.tmpl +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/scaffold_templates/schemas.py.tmpl +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/markets/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/models/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/models/accounts.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/models/brokerage.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/models/candle.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/models/credit.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/models/money.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/models/quotes.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/models/tax.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/models/transactions.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/add.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/aggregator.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/calculator.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/ease.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/goals.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/insights.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/models.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/scaffold_templates/README.md +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/scaffold_templates/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/scaffold_templates/models.py.tmpl +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/scaffold_templates/repository.py.tmpl +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/scaffold_templates/schemas.py.tmpl +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/normalization/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/normalization/currency_converter.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/normalization/models.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/normalization/providers/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/normalization/providers/static_mappings.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/normalization/symbol_resolver.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/obs/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/obs/classifier.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/banking/base.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/base.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/brokerage/base.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/credit/experian.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/identity/stripe_identity.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/market/alphavantage.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/market/base.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/market/coingecko.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/market/yahoo.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/registry.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/tax/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/tax/irs.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/tax/mock.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/providers/tax/taxbit.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/py.typed +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/recurring/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/recurring/add.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/recurring/detector.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/recurring/ease.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/recurring/models.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/recurring/summary.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/scaffold/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/scaffold/budgets.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/scaffold/goals.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/security/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/security/add.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/security/audit.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/security/models.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/security/pii_filter.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/security/token_store.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/settings.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/tax/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/tax/add.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/tax/tlh.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/utils/__init__.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/utils/retry.py +0 -0
- {fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: fin-infra
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.63
|
|
4
4
|
Summary: Financial infrastructure toolkit: banking connections, market data, credit, cashflows, and brokerage integrations
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: finance,banking,plaid,brokerage,markets,credit,tax,cashflow,fintech,infra
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "fin-infra"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.63"
|
|
4
4
|
description = "Financial infrastructure toolkit: banking connections, market data, credit, cashflows, and brokerage integrations"
|
|
5
5
|
authors = ["Ali Khatami <aliikhatami94@gmail.com>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -45,7 +45,7 @@ from __future__ import annotations
|
|
|
45
45
|
|
|
46
46
|
import os
|
|
47
47
|
from datetime import date
|
|
48
|
-
from typing import TYPE_CHECKING, Optional
|
|
48
|
+
from typing import TYPE_CHECKING, Optional, cast
|
|
49
49
|
|
|
50
50
|
from pydantic import BaseModel, Field
|
|
51
51
|
|
|
@@ -199,7 +199,7 @@ def easy_banking(provider: str = "teller", **config) -> BankingProvider:
|
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
# Use provider registry to dynamically load and configure provider
|
|
202
|
-
return resolve("banking", provider, **config)
|
|
202
|
+
return cast(BankingProvider, resolve("banking", provider, **config))
|
|
203
203
|
|
|
204
204
|
|
|
205
205
|
def add_banking(
|
|
@@ -15,7 +15,7 @@ Expected performance:
|
|
|
15
15
|
|
|
16
16
|
import hashlib
|
|
17
17
|
import logging
|
|
18
|
-
from typing import Optional, List, Tuple
|
|
18
|
+
from typing import Optional, List, Tuple, cast
|
|
19
19
|
from pydantic import BaseModel, Field
|
|
20
20
|
|
|
21
21
|
# ai-infra imports
|
|
@@ -245,7 +245,7 @@ class LLMCategorizer:
|
|
|
245
245
|
f"Must be one of {len(valid_categories)} valid categories."
|
|
246
246
|
)
|
|
247
247
|
|
|
248
|
-
return response
|
|
248
|
+
return cast(CategoryPrediction, response)
|
|
249
249
|
|
|
250
250
|
def _build_system_prompt(self) -> str:
|
|
251
251
|
"""Build system prompt with few-shot examples (reused across all requests)."""
|
|
@@ -21,7 +21,7 @@ from __future__ import annotations
|
|
|
21
21
|
|
|
22
22
|
import logging
|
|
23
23
|
from datetime import datetime
|
|
24
|
-
from typing import Any, Callable, TYPE_CHECKING
|
|
24
|
+
from typing import Any, Callable, TYPE_CHECKING, cast
|
|
25
25
|
|
|
26
26
|
if TYPE_CHECKING:
|
|
27
27
|
from fastapi import FastAPI, Request, Response
|
|
@@ -118,7 +118,8 @@ def add_compliance_tracking(
|
|
|
118
118
|
|
|
119
119
|
# Track only GET requests (data access)
|
|
120
120
|
if method != "GET":
|
|
121
|
-
|
|
121
|
+
from starlette.responses import Response as StarletteResponse
|
|
122
|
+
return cast("Response", await call_next(request))
|
|
122
123
|
|
|
123
124
|
# Determine if path is a compliance-tracked endpoint
|
|
124
125
|
event = None
|
|
@@ -148,7 +149,7 @@ def add_compliance_tracking(
|
|
|
148
149
|
if on_event:
|
|
149
150
|
on_event(event, context)
|
|
150
151
|
|
|
151
|
-
return response
|
|
152
|
+
return cast("Response", response)
|
|
152
153
|
|
|
153
154
|
logger.info(
|
|
154
155
|
"Compliance tracking enabled",
|
|
@@ -23,6 +23,7 @@ Example:
|
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
25
|
import logging
|
|
26
|
+
from typing import cast
|
|
26
27
|
|
|
27
28
|
from fastapi import FastAPI, Depends, HTTPException, status
|
|
28
29
|
|
|
@@ -175,7 +176,7 @@ def add_credit(
|
|
|
175
176
|
# Don't fail request if webhook publishing fails
|
|
176
177
|
logger.warning(f"Failed to publish credit.score_changed webhook: {e}")
|
|
177
178
|
|
|
178
|
-
return score
|
|
179
|
+
return cast(CreditScore, score)
|
|
179
180
|
|
|
180
181
|
@router.post("/report", response_model=CreditReport)
|
|
181
182
|
@credit_resource.cache_read(ttl=cache_ttl, suffix="report")
|
|
@@ -219,7 +220,7 @@ def add_credit(
|
|
|
219
220
|
detail="Credit bureau service unavailable",
|
|
220
221
|
)
|
|
221
222
|
|
|
222
|
-
return report
|
|
223
|
+
return cast(CreditReport, report)
|
|
223
224
|
|
|
224
225
|
# Mount router with dual routes (with/without trailing slash)
|
|
225
226
|
app.include_router(router, include_in_schema=True)
|
|
@@ -24,6 +24,7 @@ Example:
|
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
26
|
import base64
|
|
27
|
+
from typing import cast
|
|
27
28
|
|
|
28
29
|
import httpx
|
|
29
30
|
from svc_infra.cache import cache_read
|
|
@@ -85,7 +86,7 @@ class ExperianAuthManager:
|
|
|
85
86
|
>>> headers = {"Authorization": f"Bearer {token}"}
|
|
86
87
|
"""
|
|
87
88
|
# Call the cached implementation with client_id for cache key
|
|
88
|
-
return await self._get_token_cached(client_id=self.client_id)
|
|
89
|
+
return cast(str, await self._get_token_cached(client_id=self.client_id))
|
|
89
90
|
|
|
90
91
|
@cache_read(
|
|
91
92
|
key="oauth_token:experian:{client_id}", # Use client_id for uniqueness
|
|
@@ -140,7 +141,7 @@ class ExperianAuthManager:
|
|
|
140
141
|
|
|
141
142
|
# Parse and return token
|
|
142
143
|
data = response.json()
|
|
143
|
-
return data["access_token"]
|
|
144
|
+
return cast(str, data["access_token"])
|
|
144
145
|
|
|
145
146
|
async def invalidate(self) -> None:
|
|
146
147
|
"""Invalidate cached token for THIS client (force refresh on next get_token call).
|
|
@@ -14,7 +14,7 @@ Example:
|
|
|
14
14
|
>>> data = await client.get_credit_score("user123")
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
|
-
from typing import Any
|
|
17
|
+
from typing import Any, cast
|
|
18
18
|
|
|
19
19
|
import httpx
|
|
20
20
|
from tenacity import (
|
|
@@ -155,7 +155,7 @@ class ExperianClient:
|
|
|
155
155
|
**kwargs,
|
|
156
156
|
)
|
|
157
157
|
response.raise_for_status()
|
|
158
|
-
return response.json()
|
|
158
|
+
return cast(dict[str, Any], response.json())
|
|
159
159
|
|
|
160
160
|
except httpx.HTTPStatusError as e:
|
|
161
161
|
# Parse error response
|
|
@@ -31,7 +31,7 @@ Example:
|
|
|
31
31
|
|
|
32
32
|
import logging
|
|
33
33
|
from datetime import datetime, timezone
|
|
34
|
-
from typing import Literal
|
|
34
|
+
from typing import Literal, cast
|
|
35
35
|
|
|
36
36
|
from fin_infra.credit.experian.auth import ExperianAuthManager
|
|
37
37
|
from fin_infra.credit.experian.client import ExperianClient
|
|
@@ -360,4 +360,4 @@ class ExperianProvider(CreditProvider):
|
|
|
360
360
|
signature_key=signature_key,
|
|
361
361
|
)
|
|
362
362
|
|
|
363
|
-
return data.get("subscriptionId", "unknown")
|
|
363
|
+
return cast(str, data.get("subscriptionId", "unknown"))
|
|
@@ -29,7 +29,7 @@ add_goals(app)
|
|
|
29
29
|
|
|
30
30
|
import logging
|
|
31
31
|
from datetime import datetime
|
|
32
|
-
from typing import List, Optional
|
|
32
|
+
from typing import Any, List, Optional, cast
|
|
33
33
|
|
|
34
34
|
from fastapi import FastAPI, HTTPException, status, Query, Body
|
|
35
35
|
from pydantic import BaseModel, Field
|
|
@@ -469,7 +469,7 @@ def add_goals(
|
|
|
469
469
|
# Get all milestones from the goal (check_milestones only returns newly reached ones)
|
|
470
470
|
goal = get_goal(goal_id)
|
|
471
471
|
milestones = goal.get("milestones", [])
|
|
472
|
-
return milestones
|
|
472
|
+
return cast(list[dict[Any, Any]], milestones)
|
|
473
473
|
except KeyError:
|
|
474
474
|
raise HTTPException(
|
|
475
475
|
status_code=status.HTTP_404_NOT_FOUND, detail=f"Goal {goal_id} not found"
|
|
@@ -41,7 +41,7 @@ Example:
|
|
|
41
41
|
"""
|
|
42
42
|
|
|
43
43
|
from datetime import datetime
|
|
44
|
-
from typing import Any
|
|
44
|
+
from typing import Any, cast
|
|
45
45
|
|
|
46
46
|
from pydantic import BaseModel, Field
|
|
47
47
|
|
|
@@ -839,7 +839,7 @@ def get_goal(goal_id: str) -> dict[str, Any]:
|
|
|
839
839
|
if goal_id not in _GOALS_STORE:
|
|
840
840
|
raise KeyError(f"Goal not found: {goal_id}")
|
|
841
841
|
|
|
842
|
-
return _GOALS_STORE[goal_id]
|
|
842
|
+
return cast(dict[str, Any], _GOALS_STORE[goal_id])
|
|
843
843
|
|
|
844
844
|
|
|
845
845
|
def update_goal(
|
|
@@ -885,7 +885,7 @@ def update_goal(
|
|
|
885
885
|
|
|
886
886
|
Goal(**goal) # Will raise ValidationError if invalid
|
|
887
887
|
|
|
888
|
-
return goal
|
|
888
|
+
return cast(dict[str, Any], goal)
|
|
889
889
|
|
|
890
890
|
|
|
891
891
|
def delete_goal(goal_id: str) -> None:
|
|
@@ -26,7 +26,7 @@ Example:
|
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
28
|
from datetime import datetime
|
|
29
|
-
from typing import Any
|
|
29
|
+
from typing import Any, cast
|
|
30
30
|
|
|
31
31
|
from fin_infra.goals.management import get_goal, update_goal
|
|
32
32
|
from fin_infra.goals.models import Milestone
|
|
@@ -229,7 +229,7 @@ def get_next_milestone(goal_id: str) -> dict[str, Any] | None:
|
|
|
229
229
|
# Find first unreached milestone (sorted by amount)
|
|
230
230
|
for milestone in milestones:
|
|
231
231
|
if not milestone.get("reached", False):
|
|
232
|
-
return milestone
|
|
232
|
+
return cast(dict[str, Any], milestone)
|
|
233
233
|
|
|
234
234
|
return None
|
|
235
235
|
|
|
@@ -10,7 +10,7 @@ from __future__ import annotations
|
|
|
10
10
|
|
|
11
11
|
from datetime import date
|
|
12
12
|
from decimal import Decimal
|
|
13
|
-
from typing import Any, Dict, List, Optional
|
|
13
|
+
from typing import Any, Dict, List, Optional, cast
|
|
14
14
|
|
|
15
15
|
from plaid.api import plaid_api
|
|
16
16
|
from plaid.model.investments_holdings_get_request import InvestmentsHoldingsGetRequest
|
|
@@ -103,7 +103,7 @@ class PlaidInvestmentProvider(InvestmentProvider):
|
|
|
103
103
|
"development": plaid.Environment.Sandbox, # Map development to sandbox
|
|
104
104
|
"production": plaid.Environment.Production,
|
|
105
105
|
}
|
|
106
|
-
return hosts.get(environment.lower(), plaid.Environment.Sandbox)
|
|
106
|
+
return cast(str, hosts.get(environment.lower(), plaid.Environment.Sandbox))
|
|
107
107
|
|
|
108
108
|
async def get_holdings(
|
|
109
109
|
self, access_token: str, account_ids: Optional[List[str]] = None
|
|
@@ -11,7 +11,7 @@ from __future__ import annotations
|
|
|
11
11
|
|
|
12
12
|
from datetime import date
|
|
13
13
|
from decimal import Decimal
|
|
14
|
-
from typing import Any, Dict, List, Optional
|
|
14
|
+
from typing import Any, Dict, List, Optional, cast
|
|
15
15
|
|
|
16
16
|
import httpx
|
|
17
17
|
|
|
@@ -393,7 +393,7 @@ class SnapTradeInvestmentProvider(InvestmentProvider):
|
|
|
393
393
|
url = f"{self.base_url}/connections"
|
|
394
394
|
response = await self.client.get(url, headers=auth_headers)
|
|
395
395
|
response.raise_for_status()
|
|
396
|
-
return await response.json()
|
|
396
|
+
return cast(list[dict[str, Any]], await response.json())
|
|
397
397
|
|
|
398
398
|
except httpx.HTTPStatusError as e:
|
|
399
399
|
raise self._transform_error(e)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
from datetime import date as DateType
|
|
5
|
-
from typing import Optional
|
|
5
|
+
from typing import Optional, cast
|
|
6
6
|
|
|
7
7
|
import httpx
|
|
8
8
|
|
|
@@ -66,10 +66,10 @@ class ExchangeRateClient:
|
|
|
66
66
|
raise ExchangeRateAPIError(
|
|
67
67
|
f"API returned error: {data.get('error-type', 'unknown')}"
|
|
68
68
|
)
|
|
69
|
-
return data["conversion_rates"]
|
|
69
|
+
return cast(dict[str, float], data["conversion_rates"])
|
|
70
70
|
else:
|
|
71
71
|
# Free tier response format
|
|
72
|
-
return data["rates"]
|
|
72
|
+
return cast(dict[str, float], data["rates"])
|
|
73
73
|
|
|
74
74
|
except httpx.HTTPError as e:
|
|
75
75
|
raise ExchangeRateAPIError(f"HTTP error fetching rates: {e}")
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from datetime import date, datetime, timedelta
|
|
4
|
+
from typing import Any, cast
|
|
4
5
|
|
|
5
6
|
# Plaid SDK v25+ uses new API structure
|
|
6
7
|
try:
|
|
@@ -96,7 +97,7 @@ class PlaidClient(BankingProvider):
|
|
|
96
97
|
language="en",
|
|
97
98
|
)
|
|
98
99
|
response = self.client.link_token_create(request)
|
|
99
|
-
return response["link_token"]
|
|
100
|
+
return cast(str, response["link_token"])
|
|
100
101
|
|
|
101
102
|
def exchange_public_token(self, public_token: str) -> dict:
|
|
102
103
|
request = ItemPublicTokenExchangeRequest(public_token=public_token)
|
|
@@ -146,8 +147,8 @@ class PlaidClient(BankingProvider):
|
|
|
146
147
|
# Return all balances
|
|
147
148
|
return {"balances": [acc.get("balances", {}) for acc in accounts]}
|
|
148
149
|
|
|
149
|
-
def identity(self, access_token: str) -> dict:
|
|
150
|
+
def identity(self, access_token: str) -> dict[Any, Any]:
|
|
150
151
|
"""Fetch identity/account holder information."""
|
|
151
152
|
request = IdentityGetRequest(access_token=access_token)
|
|
152
153
|
response = self.client.identity_get(request)
|
|
153
|
-
return response.to_dict()
|
|
154
|
+
return cast(dict[Any, Any], response.to_dict())
|
|
@@ -24,7 +24,7 @@ from __future__ import annotations
|
|
|
24
24
|
|
|
25
25
|
import ssl
|
|
26
26
|
import httpx
|
|
27
|
-
from typing import Any
|
|
27
|
+
from typing import Any, cast
|
|
28
28
|
|
|
29
29
|
from ..base import BankingProvider
|
|
30
30
|
|
|
@@ -139,7 +139,7 @@ class TellerClient(BankingProvider):
|
|
|
139
139
|
"products": ["accounts", "transactions", "balances", "identity"],
|
|
140
140
|
},
|
|
141
141
|
)
|
|
142
|
-
return response.get("enrollment_id", "")
|
|
142
|
+
return cast(str, response.get("enrollment_id", ""))
|
|
143
143
|
|
|
144
144
|
def exchange_public_token(self, public_token: str) -> dict:
|
|
145
145
|
"""Exchange public token for access token.
|
|
@@ -186,7 +186,7 @@ class TellerClient(BankingProvider):
|
|
|
186
186
|
auth=(access_token, ""),
|
|
187
187
|
)
|
|
188
188
|
response.raise_for_status()
|
|
189
|
-
return response.json()
|
|
189
|
+
return cast(list[dict[Any, Any]], response.json())
|
|
190
190
|
|
|
191
191
|
def transactions(
|
|
192
192
|
self,
|
|
@@ -229,7 +229,7 @@ class TellerClient(BankingProvider):
|
|
|
229
229
|
params=params,
|
|
230
230
|
)
|
|
231
231
|
response.raise_for_status()
|
|
232
|
-
return response.json()
|
|
232
|
+
return cast(list[dict[Any, Any]], response.json())
|
|
233
233
|
|
|
234
234
|
def balances(self, access_token: str, account_id: str | None = None) -> dict:
|
|
235
235
|
"""Fetch current balances.
|
|
@@ -261,7 +261,7 @@ class TellerClient(BankingProvider):
|
|
|
261
261
|
)
|
|
262
262
|
|
|
263
263
|
response.raise_for_status()
|
|
264
|
-
return response.json()
|
|
264
|
+
return cast(dict[Any, Any], response.json())
|
|
265
265
|
|
|
266
266
|
def identity(self, access_token: str) -> dict:
|
|
267
267
|
"""Fetch identity/account holder information.
|
|
@@ -285,7 +285,7 @@ class TellerClient(BankingProvider):
|
|
|
285
285
|
auth=(access_token, ""),
|
|
286
286
|
)
|
|
287
287
|
response.raise_for_status()
|
|
288
|
-
return response.json()
|
|
288
|
+
return cast(dict[Any, Any], response.json())
|
|
289
289
|
|
|
290
290
|
def __del__(self) -> None:
|
|
291
291
|
"""Close HTTP client on cleanup."""
|
|
@@ -7,7 +7,7 @@ mode for development and testing. Live trading requires explicit opt-in.
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
import os
|
|
10
|
-
from typing import Literal
|
|
10
|
+
from typing import Any, Literal, cast
|
|
11
11
|
|
|
12
12
|
try:
|
|
13
13
|
from alpaca_trade_api import REST
|
|
@@ -308,14 +308,14 @@ class AlpacaBrokerage(BrokerageProvider):
|
|
|
308
308
|
return self._extract_raw(watchlist)
|
|
309
309
|
|
|
310
310
|
@staticmethod
|
|
311
|
-
def _extract_raw(obj) -> dict:
|
|
311
|
+
def _extract_raw(obj: Any) -> dict[Any, Any]:
|
|
312
312
|
"""Extract raw dict from Alpaca entity object.
|
|
313
313
|
|
|
314
314
|
Alpaca entities have a _raw attribute with the API response data.
|
|
315
315
|
"""
|
|
316
316
|
if hasattr(obj, "_raw"):
|
|
317
|
-
return obj._raw
|
|
317
|
+
return cast(dict[Any, Any], obj._raw)
|
|
318
318
|
elif hasattr(obj, "__dict__"):
|
|
319
|
-
return obj.__dict__
|
|
319
|
+
return cast(dict[Any, Any], obj.__dict__)
|
|
320
320
|
else:
|
|
321
|
-
return obj
|
|
321
|
+
return cast(dict[Any, Any], obj)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from typing import Any, cast
|
|
4
|
+
|
|
3
5
|
import ccxt
|
|
4
6
|
|
|
5
7
|
from ..base import CryptoDataProvider
|
|
@@ -15,14 +17,14 @@ class CCXTCryptoData(CryptoDataProvider):
|
|
|
15
17
|
# Defer load_markets to first call to avoid network on construction
|
|
16
18
|
self._markets_loaded = False
|
|
17
19
|
|
|
18
|
-
def ticker(self, symbol_pair: str) -> dict:
|
|
20
|
+
def ticker(self, symbol_pair: str) -> dict[Any, Any]:
|
|
19
21
|
if not self._markets_loaded:
|
|
20
22
|
self.exchange.load_markets()
|
|
21
23
|
self._markets_loaded = True
|
|
22
|
-
return self.exchange.fetch_ticker(symbol_pair)
|
|
24
|
+
return cast(dict[Any, Any], self.exchange.fetch_ticker(symbol_pair))
|
|
23
25
|
|
|
24
26
|
def ohlcv(self, symbol_pair: str, timeframe: str = "1d", limit: int = 100) -> list[list[float]]:
|
|
25
27
|
if not self._markets_loaded:
|
|
26
28
|
self.exchange.load_markets()
|
|
27
29
|
self._markets_loaded = True
|
|
28
|
-
return self.exchange.fetch_ohlcv(symbol_pair, timeframe=timeframe, limit=limit)
|
|
30
|
+
return cast(list[list[float]], self.exchange.fetch_ohlcv(symbol_pair, timeframe=timeframe, limit=limit))
|
|
@@ -14,7 +14,7 @@ Only called for ambiguous patterns (20-40% variance, ~10% of patterns).
|
|
|
14
14
|
from __future__ import annotations
|
|
15
15
|
|
|
16
16
|
import logging
|
|
17
|
-
from typing import Any, Optional
|
|
17
|
+
from typing import Any, Optional, cast
|
|
18
18
|
|
|
19
19
|
from pydantic import BaseModel, ConfigDict, Field
|
|
20
20
|
|
|
@@ -292,7 +292,7 @@ class VariableDetectorLLM:
|
|
|
292
292
|
|
|
293
293
|
# Extract structured output
|
|
294
294
|
if hasattr(response, "structured") and response.structured:
|
|
295
|
-
return response.structured
|
|
295
|
+
return cast(VariableRecurringPattern, response.structured)
|
|
296
296
|
else:
|
|
297
297
|
raise ValueError(f"LLM returned no structured output for '{merchant_name}'")
|
|
298
298
|
|
|
@@ -15,7 +15,7 @@ from __future__ import annotations
|
|
|
15
15
|
|
|
16
16
|
import hashlib
|
|
17
17
|
import logging
|
|
18
|
-
from typing import Any, Optional
|
|
18
|
+
from typing import Any, Optional, cast
|
|
19
19
|
|
|
20
20
|
from pydantic import BaseModel, ConfigDict, Field
|
|
21
21
|
|
|
@@ -383,7 +383,7 @@ class SubscriptionInsightsGenerator:
|
|
|
383
383
|
|
|
384
384
|
# Extract structured output
|
|
385
385
|
if hasattr(response, "structured") and response.structured:
|
|
386
|
-
return response.structured
|
|
386
|
+
return cast(SubscriptionInsights, response.structured)
|
|
387
387
|
else:
|
|
388
388
|
raise ValueError("LLM returned no structured output for insights")
|
|
389
389
|
|
|
@@ -11,6 +11,7 @@ from __future__ import annotations
|
|
|
11
11
|
|
|
12
12
|
import re
|
|
13
13
|
from functools import lru_cache
|
|
14
|
+
from typing import cast
|
|
14
15
|
|
|
15
16
|
try:
|
|
16
17
|
from rapidfuzz import fuzz, process
|
|
@@ -165,7 +166,7 @@ class FuzzyMatcher:
|
|
|
165
166
|
norm2 = normalize_merchant(name2)
|
|
166
167
|
|
|
167
168
|
similarity = fuzz.token_sort_ratio(norm1, norm2)
|
|
168
|
-
return similarity >= self.similarity_threshold
|
|
169
|
+
return cast(bool, similarity >= self.similarity_threshold)
|
|
169
170
|
|
|
170
171
|
def group_merchants(self, merchants: list[str]) -> dict[str, list[str]]:
|
|
171
172
|
"""
|
|
@@ -16,7 +16,7 @@ from __future__ import annotations
|
|
|
16
16
|
|
|
17
17
|
import hashlib
|
|
18
18
|
import logging
|
|
19
|
-
from typing import Any, Optional
|
|
19
|
+
from typing import Any, Optional, cast
|
|
20
20
|
|
|
21
21
|
from pydantic import BaseModel, ConfigDict, Field
|
|
22
22
|
|
|
@@ -354,7 +354,7 @@ class MerchantNormalizer:
|
|
|
354
354
|
|
|
355
355
|
# Extract structured output
|
|
356
356
|
if hasattr(response, "structured") and response.structured:
|
|
357
|
-
return response.structured
|
|
357
|
+
return cast(MerchantNormalized, response.structured)
|
|
358
358
|
else:
|
|
359
359
|
raise ValueError(f"LLM returned no structured output for '{merchant_name}'")
|
|
360
360
|
|
|
@@ -7,7 +7,7 @@ Encrypt/decrypt financial provider API tokens at rest.
|
|
|
7
7
|
import base64
|
|
8
8
|
import json
|
|
9
9
|
import os
|
|
10
|
-
from typing import Any, Dict, Optional
|
|
10
|
+
from typing import Any, Dict, Optional, cast
|
|
11
11
|
|
|
12
12
|
from cryptography.fernet import Fernet, InvalidToken
|
|
13
13
|
|
|
@@ -144,7 +144,7 @@ class ProviderTokenEncryption:
|
|
|
144
144
|
"Token may have been tampered with or used for wrong user/provider."
|
|
145
145
|
)
|
|
146
146
|
|
|
147
|
-
return data["token"]
|
|
147
|
+
return cast(str, data["token"])
|
|
148
148
|
|
|
149
149
|
except InvalidToken as e:
|
|
150
150
|
raise ValueError(
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import httpx
|
|
4
|
+
from typing import Any, cast
|
|
4
5
|
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
|
|
5
6
|
|
|
6
7
|
_DEFAULT_TIMEOUT = httpx.Timeout(20.0)
|
|
@@ -12,8 +13,8 @@ _DEFAULT_TIMEOUT = httpx.Timeout(20.0)
|
|
|
12
13
|
retry=retry_if_exception_type(httpx.HTTPError),
|
|
13
14
|
reraise=True,
|
|
14
15
|
)
|
|
15
|
-
async def aget_json(url: str, **kwargs) -> dict:
|
|
16
|
+
async def aget_json(url: str, **kwargs) -> dict[Any, Any]:
|
|
16
17
|
async with httpx.AsyncClient(timeout=_DEFAULT_TIMEOUT) as client:
|
|
17
18
|
r = await client.get(url, **kwargs)
|
|
18
19
|
r.raise_for_status()
|
|
19
|
-
return r.json()
|
|
20
|
+
return cast(dict[Any, Any], r.json())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/scaffold_templates/models.py.tmpl
RENAMED
|
File without changes
|
{fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/scaffold_templates/repository.py.tmpl
RENAMED
|
File without changes
|
{fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/budgets/scaffold_templates/schemas.py.tmpl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/goals/scaffold_templates/repository.py.tmpl
RENAMED
|
File without changes
|
{fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/goals/scaffold_templates/schemas.py.tmpl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/scaffold_templates/README.md
RENAMED
|
File without changes
|
{fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/scaffold_templates/__init__.py
RENAMED
|
File without changes
|
{fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/scaffold_templates/models.py.tmpl
RENAMED
|
File without changes
|
|
File without changes
|
{fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/investments/scaffold_templates/schemas.py.tmpl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/scaffold_templates/__init__.py
RENAMED
|
File without changes
|
{fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/scaffold_templates/models.py.tmpl
RENAMED
|
File without changes
|
{fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/scaffold_templates/repository.py.tmpl
RENAMED
|
File without changes
|
{fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/net_worth/scaffold_templates/schemas.py.tmpl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fin_infra-0.1.62 → fin_infra-0.1.63}/src/fin_infra/normalization/providers/static_mappings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|