fin-infra 0.1.63__py3-none-any.whl → 0.1.64__py3-none-any.whl

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.
@@ -162,12 +162,13 @@ async def analyze_spending(
162
162
  )
163
163
 
164
164
  return SpendingInsight(
165
- top_merchants=top_merchants,
166
- category_breakdown=dict(category_totals),
165
+ # Convert Decimal to float for model compatibility (intentional for Pydantic field types)
166
+ top_merchants=[(m, float(v)) for m, v in top_merchants],
167
+ category_breakdown={k: float(v) for k, v in category_totals.items()},
167
168
  spending_trends=spending_trends,
168
169
  anomalies=anomalies,
169
170
  period_days=days,
170
- total_spending=total_spending,
171
+ total_spending=float(total_spending) if total_spending else 0.0,
171
172
  )
172
173
 
173
174
 
@@ -359,9 +360,10 @@ async def _detect_spending_anomalies(
359
360
  anomalies.append(
360
361
  SpendingAnomaly(
361
362
  category=category,
362
- current_amount=current_amount,
363
- average_amount=average_amount,
364
- deviation_percent=deviation_percent,
363
+ # Convert Decimal to float for model compatibility (intentional for Pydantic field types)
364
+ current_amount=float(current_amount),
365
+ average_amount=float(average_amount),
366
+ deviation_percent=float(deviation_percent),
365
367
  severity=severity,
366
368
  )
367
369
  )
@@ -397,10 +397,13 @@ def add_banking(
397
397
  }
398
398
  """
399
399
  # Get all transactions from provider
400
+ # Convert date to ISO string format as expected by BankingProvider.transactions()
401
+ start_date_str: str | None = start_date.isoformat() if start_date else None
402
+ end_date_str: str | None = end_date.isoformat() if end_date else None
400
403
  transactions = banking.transactions(
401
404
  access_token=access_token,
402
- start_date=start_date,
403
- end_date=end_date,
405
+ start_date=start_date_str,
406
+ end_date=end_date_str,
404
407
  )
405
408
 
406
409
  # Apply filters
@@ -212,7 +212,9 @@ def add_brokerage(
212
212
 
213
213
  # Initialize provider if string or None
214
214
  if isinstance(provider, str):
215
- brokerage_provider = easy_brokerage(provider=provider, mode=mode, **config)
215
+ # Cast provider string to Literal type for type checker
216
+ provider_literal: Literal["alpaca"] | None = provider if provider == "alpaca" else None # type: ignore[assignment]
217
+ brokerage_provider = easy_brokerage(provider=provider_literal, mode=mode, **config)
216
218
  elif provider is None:
217
219
  brokerage_provider = easy_brokerage(mode=mode, **config)
218
220
  else:
@@ -241,7 +243,7 @@ def add_brokerage(
241
243
  Returns list of positions with symbol, quantity, P/L, etc.
242
244
  """
243
245
  try:
244
- positions = brokerage_provider.positions()
246
+ positions = list(brokerage_provider.positions()) # Convert Iterable to list for len()
245
247
  return {"positions": positions, "count": len(positions)}
246
248
  except Exception as e:
247
249
  raise HTTPException(status_code=500, detail=f"Error fetching positions: {str(e)}")
@@ -44,7 +44,7 @@ from .taxonomy import Category, CategoryGroup, get_all_categories, get_category_
44
44
  try:
45
45
  from .llm_layer import LLMCategorizer
46
46
  except ImportError:
47
- LLMCategorizer = None
47
+ LLMCategorizer = None # type: ignore[assignment,misc]
48
48
 
49
49
  __all__ = [
50
50
  # Easy setup
@@ -96,7 +96,8 @@ def add_categorization(
96
96
  start_time = time.perf_counter()
97
97
 
98
98
  try:
99
- prediction = engine.categorize(
99
+ # Await the async categorize method
100
+ prediction = await engine.categorize(
100
101
  merchant_name=request.merchant_name,
101
102
  user_id=request.user_id,
102
103
  include_alternatives=request.include_alternatives,
@@ -13,7 +13,7 @@ from .engine import CategorizationEngine
13
13
  try:
14
14
  from .llm_layer import LLMCategorizer
15
15
  except ImportError:
16
- LLMCategorizer = None
16
+ LLMCategorizer = None # type: ignore[assignment,misc]
17
17
 
18
18
 
19
19
  def easy_categorization(
@@ -23,7 +23,7 @@ from .taxonomy import Category
23
23
  try:
24
24
  from .llm_layer import LLMCategorizer
25
25
  except ImportError:
26
- LLMCategorizer = None
26
+ LLMCategorizer = None # type: ignore[assignment,misc]
27
27
 
28
28
  logger = logging.getLogger(__name__)
29
29
 
@@ -51,7 +51,8 @@ from typing import TYPE_CHECKING, Literal
51
51
  if TYPE_CHECKING:
52
52
  from fastapi import FastAPI
53
53
 
54
- from ..providers.base import InvestmentProvider
54
+ # Use the local InvestmentProvider base class (same as providers use)
55
+ from .providers.base import InvestmentProvider
55
56
 
56
57
  # Lazy imports to avoid loading provider SDKs unless needed
57
58
  _provider_cache: dict[str, InvestmentProvider] = {}
@@ -114,6 +115,7 @@ def easy_investments(
114
115
  return _provider_cache[cache_key]
115
116
 
116
117
  # Lazy import and initialize provider
118
+ instance: InvestmentProvider
117
119
  if provider == "plaid":
118
120
  from .providers.plaid import PlaidInvestmentProvider
119
121
 
@@ -172,14 +174,19 @@ def add_investments(
172
174
  >>> # GET /investments/transactions
173
175
  >>> # etc.
174
176
  """
175
- from .add import add_investments_impl
177
+ from .add import add_investments as add_investments_impl
178
+ from .providers.base import InvestmentProvider as InvestmentProviderBase
179
+
180
+ # Resolve provider from string Literal to actual InvestmentProvider instance
181
+ resolved_provider: InvestmentProviderBase | None = None
182
+ if provider is not None:
183
+ resolved_provider = easy_investments(provider=provider, **provider_config) # type: ignore[assignment]
176
184
 
177
185
  return add_investments_impl(
178
186
  app,
179
- provider=provider,
187
+ provider=resolved_provider,
180
188
  prefix=prefix,
181
189
  tags=tags or ["Investments"],
182
- **provider_config,
183
190
  )
184
191
 
185
192
 
@@ -112,19 +112,20 @@ def easy_investments(
112
112
  - Most other SnapTrade brokerages support trading operations
113
113
  """
114
114
  # Auto-detect provider from environment if not specified
115
- if provider is None:
116
- provider = _detect_provider()
115
+ detected_provider: str | None = provider
116
+ if detected_provider is None:
117
+ detected_provider = _detect_provider()
117
118
 
118
119
  # Validate provider
119
- if provider not in ("plaid", "snaptrade"):
120
+ if detected_provider not in ("plaid", "snaptrade"):
120
121
  raise ValueError(
121
- f"Invalid provider: {provider}. Must be 'plaid' or 'snaptrade'."
122
+ f"Invalid provider: {detected_provider}. Must be 'plaid' or 'snaptrade'."
122
123
  )
123
124
 
124
125
  # Instantiate provider
125
- if provider == "plaid":
126
+ if detected_provider == "plaid":
126
127
  return _create_plaid_provider(**config)
127
- elif provider == "snaptrade":
128
+ elif detected_provider == "snaptrade":
128
129
  return _create_snaptrade_provider(**config)
129
130
 
130
131
  # Should never reach here
@@ -233,10 +234,13 @@ def _create_snaptrade_provider(**config: Any) -> InvestmentProvider:
233
234
  "Example: easy_investments(provider='snaptrade', client_id='...', consumer_key='...')"
234
235
  )
235
236
 
237
+ # Ensure base_url is a string (default is set in SnapTradeInvestmentProvider)
238
+ resolved_base_url: str = base_url if isinstance(base_url, str) else "https://api.snaptrade.com/api/v1"
239
+
236
240
  return SnapTradeInvestmentProvider(
237
241
  client_id=client_id,
238
242
  consumer_key=consumer_key,
239
- base_url=base_url,
243
+ base_url=resolved_base_url,
240
244
  )
241
245
 
242
246
 
@@ -71,7 +71,7 @@ class TransactionType(str, Enum):
71
71
  fee = "fee"
72
72
  tax = "tax"
73
73
  transfer = "transfer"
74
- split = "split"
74
+ split = "split" # type: ignore[assignment] # str.split() name conflict
75
75
  merger = "merger"
76
76
  cancel = "cancel"
77
77
  other = "other"
@@ -370,7 +370,7 @@ class PlaidInvestmentProvider(InvestmentProvider):
370
370
  isin=plaid_security.get("isin"),
371
371
  sedol=plaid_security.get("sedol"),
372
372
  ticker_symbol=plaid_security.get("ticker_symbol"),
373
- name=plaid_security.get("name"),
373
+ name=plaid_security.get("name") or "Unknown Security",
374
374
  type=self._normalize_security_type(plaid_security.get("type", "other")),
375
375
  sector=plaid_security.get("sector"),
376
376
  close_price=close_price,
@@ -193,7 +193,11 @@ def add_market_data(
193
193
  if isinstance(provider, MarketDataProvider):
194
194
  market = provider
195
195
  else:
196
- market = easy_market(provider=provider, **config)
196
+ # Cast provider to Literal type for type checker
197
+ provider_literal: Literal["alphavantage", "yahoo"] | None = (
198
+ provider if provider in ("alphavantage", "yahoo", None) else None # type: ignore[assignment]
199
+ )
200
+ market = easy_market(provider=provider_literal, **config)
197
201
 
198
202
  # Create router (public - no auth required)
199
203
  router = public_router(prefix=prefix, tags=["Market Data"])
@@ -223,14 +227,15 @@ def add_market_data(
223
227
  try:
224
228
  candles = market.history(symbol, period=period, interval=interval)
225
229
  # Convert to dicts if they're Pydantic models
226
- candles_list = []
230
+ candles_list: list[dict] = []
227
231
  for candle in candles:
228
232
  if hasattr(candle, "model_dump"):
229
233
  candles_list.append(candle.model_dump())
230
234
  elif hasattr(candle, "dict"):
231
235
  candles_list.append(candle.dict())
232
236
  else:
233
- candles_list.append(candle)
237
+ # Cast to dict for type compatibility
238
+ candles_list.append(dict(candle) if hasattr(candle, "__iter__") else {"data": candle})
234
239
  return {"candles": candles_list}
235
240
  except Exception as e:
236
241
  raise HTTPException(status_code=400, detail=str(e))
@@ -93,7 +93,13 @@ class TellerClient(BankingProvider):
93
93
  ssl_context.load_cert_chain(certfile=cert_path, keyfile=key_path)
94
94
  client_kwargs["verify"] = ssl_context
95
95
 
96
- self.client = httpx.Client(**client_kwargs)
96
+ # Create client with explicit parameters to satisfy type checker
97
+ self.client = httpx.Client(
98
+ base_url=str(client_kwargs["base_url"]),
99
+ timeout=float(client_kwargs["timeout"]), # type: ignore[arg-type]
100
+ headers=client_kwargs["headers"], # type: ignore[arg-type]
101
+ verify=client_kwargs.get("verify", True), # type: ignore[arg-type]
102
+ )
97
103
 
98
104
  def _request(self, method: str, path: str, **kwargs: Any) -> Any:
99
105
  """Make HTTP request to Teller API with error handling.
@@ -313,9 +313,9 @@ class MockTaxProvider(TaxProvider):
313
313
  return CryptoTaxReport(
314
314
  user_id=user_id,
315
315
  tax_year=tax_year,
316
- total_gain_loss=short_term + long_term,
317
- short_term_gain_loss=short_term,
318
- long_term_gain_loss=long_term,
316
+ total_gain_loss=Decimal(short_term + long_term),
317
+ short_term_gain_loss=Decimal(short_term),
318
+ long_term_gain_loss=Decimal(long_term),
319
319
  transaction_count=len(crypto_transactions),
320
320
  cost_basis_method=cost_basis_method,
321
321
  transactions=crypto_transactions,
@@ -162,7 +162,9 @@ async def get_provider_token(
162
162
 
163
163
  # Decrypt token
164
164
  context = {"user_id": user_id, "provider": provider}
165
- token = encryption.decrypt(token_obj.encrypted_token, context=context)
165
+ # Cast to str since SQLAlchemy Column[str] needs explicit conversion for type checker
166
+ encrypted_token_str: str = str(token_obj.encrypted_token)
167
+ token = encryption.decrypt(encrypted_token_str, context=context)
166
168
 
167
169
  # Update last_used_at
168
170
  update_stmt = (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: fin-infra
3
- Version: 0.1.63
3
+ Version: 0.1.64
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
@@ -10,11 +10,11 @@ fin_infra/analytics/projections.py,sha256=7cuG6w1KXq8sd3UNufu5aOcxG5n-foswrHqrgW
10
10
  fin_infra/analytics/rebalancing.py,sha256=K3S7KQiIU2LwyAwWN9VrSly4AOl24vN9tz_JX7I9FJ8,14642
11
11
  fin_infra/analytics/savings.py,sha256=tavIRZtu9FjCm-DeWg5f060GcsdgD-cl-vgKOnieOUw,7574
12
12
  fin_infra/analytics/scenarios.py,sha256=LE_dZVkbxxAx5sxitGhiOhZfWTlYtVbIvS9pEXkijLc,12246
13
- fin_infra/analytics/spending.py,sha256=zXTcYAj_fWQtzOHgSN4P0dSIm80Q5eke6T3LbWltjyU,25882
14
- fin_infra/banking/__init__.py,sha256=IoVLc3FhfE_XWMj9Vt4_gpALStnxu7_8xLw1VBpTSxs,22296
13
+ fin_infra/analytics/spending.py,sha256=SxfsBPdLoHrFKcx56Da63j0YEV_zxYxaV2lEIQIaMQk,26197
14
+ fin_infra/banking/__init__.py,sha256=-Pn8YxpE_aOefFGL4bBmOogywNWShEV271CKxlrvTIM,22556
15
15
  fin_infra/banking/history.py,sha256=1ufAwkTnXr-QJetFzJl4xA2e3dqd1-TkT8pf46MNfho,10630
16
16
  fin_infra/banking/utils.py,sha256=B2ebnTeUz-56l8XMBWnf2txFOr0bXIo3cKPio7_bhc4,15711
17
- fin_infra/brokerage/__init__.py,sha256=RB0wbVlxM9PCbWUezzjrOf19JucVDpCvNlT62LoMzho,17023
17
+ fin_infra/brokerage/__init__.py,sha256=2Qmiubu9kxouidrCcIHOMvYGHEgVDD5y2S2XRBAWng8,17263
18
18
  fin_infra/budgets/__init__.py,sha256=V6euagDkFHvWyjHeI64fxfddhOHDlIWwOc-PnTyyQb4,3986
19
19
  fin_infra/budgets/add.py,sha256=tdfNXD9deEEzy0xCRbTwbx70SX9wiJkWj0Huk_uCjFg,13584
20
20
  fin_infra/budgets/alerts.py,sha256=i0lQa3mLWuLQorWL-77VKhXQG2F_0U1cpdZnK3g1y3M,9720
@@ -29,10 +29,10 @@ fin_infra/budgets/templates.py,sha256=Sbc7RcHXscq34g4t7J8OXM2Kfkt5DHuvqVnFU0Jidd
29
29
  fin_infra/budgets/tracker.py,sha256=U8C7k2VV8bOjtjPIWR8qXktsBNSyBAUnE9o2mjEs1MU,16490
30
30
  fin_infra/cashflows/__init__.py,sha256=OEleZSwEHffxTvz0J52qqlkBwnu4BHbQUW0vKwzsWAs,8579
31
31
  fin_infra/cashflows/core.py,sha256=Or0hPqCvY_ypV0YiMXh-mle6xWK0tE8WuPPAqHGUp8E,532
32
- fin_infra/categorization/__init__.py,sha256=7551OjE668A_Bhm07QSTBkm4PD3uCOEwdz05KnIlr2A,1997
33
- fin_infra/categorization/add.py,sha256=jbxM51MyIFsAcleCMzP1I5jYV9EsKALzBCnuzKk76sc,6328
34
- fin_infra/categorization/ease.py,sha256=NudJBqFByS0YONPn_4O_Q7QYIiVCCgNbAhn-ugJpa0Y,5826
35
- fin_infra/categorization/engine.py,sha256=VxVuLym_RkKK0xpZrfLKuksFVoURmXICgdik7KpxXMs,12075
32
+ fin_infra/categorization/__init__.py,sha256=efLje12AW-ec9Vs5ynb41r4XCIWx5a-Z9WoGb3kQdIE,2030
33
+ fin_infra/categorization/add.py,sha256=rsFPNWx-c8bXHiizA_MHMjsn6YiCPUBVU2kwA_8yoeM,6382
34
+ fin_infra/categorization/ease.py,sha256=oIcPVuxXOPaAhSe_OcfO4eumCg9WpfIZUdg-k-Xx800,5859
35
+ fin_infra/categorization/engine.py,sha256=ZJm-V6I1okDSFQA34GFZCOTsLCztNtmHlbm2-r51mwQ,12108
36
36
  fin_infra/categorization/llm_layer.py,sha256=0Y71o7jzE_Xs2wl_x7COM37PeP8NuTiaKiXzNCVm2sE,12727
37
37
  fin_infra/categorization/models.py,sha256=O8ceQOM0ljRh0jkmnjV7CK5Jyq1DI3lG07UTeeMheNg,5931
38
38
  fin_infra/categorization/rules.py,sha256=m3OogJY0hJe5BrmZqOvOKS2-HRdW4Y5jvvtlPDn9Pn8,12884
@@ -79,20 +79,20 @@ fin_infra/goals/scaffold_templates/schemas.py.tmpl,sha256=M1hS1pK9UDXcNqPW-NGu98
79
79
  fin_infra/insights/__init__.py,sha256=crIXNlztTCcYHNcEVMo8FwCTCUBwIK2wovb4HahzRYw,3988
80
80
  fin_infra/insights/aggregator.py,sha256=XG32mN5w5Nc4AZllmfl1esL4q44mFAf0Fvj9mWev_zk,10249
81
81
  fin_infra/insights/models.py,sha256=xov_YV8oBLJt3YdyVjbryRfcXqmGeGiPvZsZHSbvtl8,3202
82
- fin_infra/investments/__init__.py,sha256=UiWvTdKH7V9aaqZLunPT1_QGfXBAZbPk_w4QmeLWLqo,6324
82
+ fin_infra/investments/__init__.py,sha256=mDHYMLSo14KByrpW9HuxIDFBdfEESZ6tFKC09Vr_aIE,6786
83
83
  fin_infra/investments/add.py,sha256=3cbjXbWoTuDglwk9U48X6768Etv1XLTWysdDPgsn7Yg,17658
84
- fin_infra/investments/ease.py,sha256=ocs7xvnZ1u8riFjH9KHi1yFEUF0lfuEcd-QMpsuiOu8,9229
85
- fin_infra/investments/models.py,sha256=8GQuq-aGww2tzze-VrW71dBNYN918_TmtkwycCVa434,15975
84
+ fin_infra/investments/ease.py,sha256=7oyMcTVmnc8pn3lqriLRruBLEznI_grpDkH7hfXmGhE,9527
85
+ fin_infra/investments/models.py,sha256=KwGLw8jdgX5tw4zZjBWBEKNqKsMo3hJnmsx5hIV-rQU,16032
86
86
  fin_infra/investments/providers/__init__.py,sha256=V1eIzz6EnGJ-pq-9L3S2-evmcExF-YdZfd5P6JMyDtc,383
87
87
  fin_infra/investments/providers/base.py,sha256=KaJdIdeWi2WaWAogcFZw7jcqQ_IzMZw6misBNk-n6bE,9890
88
- fin_infra/investments/providers/plaid.py,sha256=z_f4NbJDhi_vcLDA_SR2yuEaRrjRxbRirlKYH6ofDAk,18086
88
+ fin_infra/investments/providers/plaid.py,sha256=2WqXwPVckIc56dx9BleC10z-WHDt7y1dO1xhsI_8kT4,18108
89
89
  fin_infra/investments/providers/snaptrade.py,sha256=ILpup62u5zCOgnQ_4RF1_m2BY7qowyINB-FUgq-jUrI,23542
90
90
  fin_infra/investments/scaffold_templates/README.md,sha256=PhgxfMLrro2Jz83b7XEnBi7lexiWKqlMrd2UU2Rbs8A,12149
91
91
  fin_infra/investments/scaffold_templates/__init__.py,sha256=iR0oiAzXFYXHBnVJjaEnAzk6omncYOLg0TKMJ7xomBc,82
92
92
  fin_infra/investments/scaffold_templates/models.py.tmpl,sha256=5inP5-jw-qEfPYxSN71tn4AojZ9PesOIeuHTw181N-c,5849
93
93
  fin_infra/investments/scaffold_templates/repository.py.tmpl,sha256=XwOEpQZfuXut1WLiq-GSSvv0oX0iYCW54eJNL0Cav94,14656
94
94
  fin_infra/investments/scaffold_templates/schemas.py.tmpl,sha256=knWmn-Kyr7AdgPD4ZPMb6T49ZuPXeuOMqmjYNyA0CA0,5451
95
- fin_infra/markets/__init__.py,sha256=mStcYiA4dq2yHEyStZyOLd-KkW-Jf657l8NSLLa_MU8,9512
95
+ fin_infra/markets/__init__.py,sha256=S6vaHI5T3NnP_Kwf5bym7P0lFUhewqmXKh6sEPbaBRs,9892
96
96
  fin_infra/models/__init__.py,sha256=q3SkGzDGFkoAMxwqJw8i4cHWt5NGU5ypjOgntxDGVKo,860
97
97
  fin_infra/models/accounts.py,sha256=PeobjGg6WM70OvOTe0JIo0zo7tBM0PDAcyClQT-Jo4o,1141
98
98
  fin_infra/models/brokerage.py,sha256=z6Zyf0N5zmmXtrN2y_4fNmtIP5wNq40H8lrHLBwY7rc,8311
@@ -127,7 +127,7 @@ fin_infra/obs/classifier.py,sha256=qZHgUV6J2sXdOhHCPOxmonyvE4V1vY-A5MDwFpzk2lk,5
127
127
  fin_infra/providers/__init__.py,sha256=jxhQm79T6DVXf7Wpy7luL-p50cE_IMUbjt4o3apzJQU,768
128
128
  fin_infra/providers/banking/base.py,sha256=KeNU4ur3zLKHVsBF1LQifcs2AKX06IEE-Rx_SetFeAs,102
129
129
  fin_infra/providers/banking/plaid_client.py,sha256=21m6ZkovwXuUuj0-dgQVDLxSfxZVjhuXj8di_-q3jGc,6617
130
- fin_infra/providers/banking/teller_client.py,sha256=pdb5JK8hdYAMFVCXBFsxY12aDxhL8afLK4NeZ4KbsvA,9917
130
+ fin_infra/providers/banking/teller_client.py,sha256=QmrsBlk3_rHT-pTQPrIAA74kjIjcgdi-gOb8NA3oBO8,10268
131
131
  fin_infra/providers/base.py,sha256=oLzdExPGE7yg-URtin3vGTQ8hEzG7UnTmDGDWJB5oL0,4273
132
132
  fin_infra/providers/brokerage/alpaca.py,sha256=wRVfVmExiYXCk1pLRmHSrfo91714JIm3rrD0djrNfT8,9938
133
133
  fin_infra/providers/brokerage/base.py,sha256=JJFH0Cqca4Rg4rmxfiwcQt-peRoBf4JpG3g6jx8DVks,106
@@ -141,7 +141,7 @@ fin_infra/providers/market/yahoo.py,sha256=FNhqkCFC0In-Z3zpzmuknEORHLRK5Evk2KSk0
141
141
  fin_infra/providers/registry.py,sha256=yPFmHHaSQERXZTcGkdXAtMU7rL7VwAzW4FOr14o6KS8,8409
142
142
  fin_infra/providers/tax/__init__.py,sha256=Tq2gLyTXL_U_ht6r7HXgaDMCAPylgcRD2ZN-COjSSQU,207
143
143
  fin_infra/providers/tax/irs.py,sha256=f7l6w0byprBszTlCB4ef60K8GrYV-03Dicl1a1Q2oVk,4701
144
- fin_infra/providers/tax/mock.py,sha256=35QulDz-fmgXyibPt1cpMhL0WgGWeziOwHnlEd1QRd0,14415
144
+ fin_infra/providers/tax/mock.py,sha256=AxI3RmEn3exdQeeUNkQYqZ-war5PS--WnLGXfRRee8o,14442
145
145
  fin_infra/providers/tax/taxbit.py,sha256=DEA7vgQPYMjz4ZdC0DpY7112FLZJ2kvwgAbDZnpHFy0,4271
146
146
  fin_infra/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
147
147
  fin_infra/recurring/__init__.py,sha256=ihMPywft8pGqzMu6EXxbQCU7ByoMl_dvad00gWV1mnk,2308
@@ -164,7 +164,7 @@ fin_infra/security/encryption.py,sha256=z1k5LFkuuMCjAUnBzBCOviyi0F1R_vabdHhdJJdb
164
164
  fin_infra/security/models.py,sha256=riQO-083p5rDMRrFxRnc2PTkxkAf-HsSpGvrnzboCNE,1734
165
165
  fin_infra/security/pii_filter.py,sha256=lfARBmPRekkyXKJV0tWI_0KVaDsdV61VH-8RHxvbqUs,8307
166
166
  fin_infra/security/pii_patterns.py,sha256=SM-o7cL6NdgkOmtBedsN2nJZ5QPbeYehZdYmAujk8Y8,3070
167
- fin_infra/security/token_store.py,sha256=UucTXfgRbdbogahS_2q5CPSb7dFyctN9D3m-ecJkqX4,5929
167
+ fin_infra/security/token_store.py,sha256=qgxhBKwhtVpchyHv30mM-cttuGZlzZvZLC4Oa-gTTeg,6075
168
168
  fin_infra/settings.py,sha256=xitpBQJmuvSy9prQhvXOW1scbwB1KAyGD8XqYgU_hQU,1388
169
169
  fin_infra/tax/__init__.py,sha256=NXUjV-k-rw4774pookY3UOwEXYRQauJze6Yift5RjW0,6107
170
170
  fin_infra/tax/add.py,sha256=8INSAv721ir9ICQxQ_oA0hL-Bjg6wLyrtj9tafrcCsA,14552
@@ -173,8 +173,8 @@ fin_infra/utils/__init__.py,sha256=gKacLSWMAis--pasd8AuVN7ap0e9Z1TjRGur0J23EDo,6
173
173
  fin_infra/utils/http.py,sha256=pvcxbNQ9oisoGPkNe3xX9aAgWzEN6mmdtr1w-L02Xj8,629
174
174
  fin_infra/utils/retry.py,sha256=ISBrup5XCuXqHZh9kjTGvGQYcuyYyqZE4u26wW7r3CM,1030
175
175
  fin_infra/version.py,sha256=4t_crzhrLum--oyowUMxtjBTzUtWp7oRTF22ewEvJG4,49
176
- fin_infra-0.1.63.dist-info/LICENSE,sha256=wK-Ya7Ylxa38dSIZRhvNj1ZVLIrHC-BAI8v38PNADiA,1061
177
- fin_infra-0.1.63.dist-info/METADATA,sha256=CYK6i2jvcZZ-Y7eKY4eYnuUCiMSwwV2UZWe2QKtARAo,10218
178
- fin_infra-0.1.63.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
179
- fin_infra-0.1.63.dist-info/entry_points.txt,sha256=Sr1uikvALZMeKm-DIkeKG4L9c4SNqysXGO_IRF8_9eU,53
180
- fin_infra-0.1.63.dist-info/RECORD,,
176
+ fin_infra-0.1.64.dist-info/LICENSE,sha256=wK-Ya7Ylxa38dSIZRhvNj1ZVLIrHC-BAI8v38PNADiA,1061
177
+ fin_infra-0.1.64.dist-info/METADATA,sha256=e3BndWoe-yekpgp-__h85zwt-_f5PMLj3inQ4Y-oS_8,10218
178
+ fin_infra-0.1.64.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
179
+ fin_infra-0.1.64.dist-info/entry_points.txt,sha256=Sr1uikvALZMeKm-DIkeKG4L9c4SNqysXGO_IRF8_9eU,53
180
+ fin_infra-0.1.64.dist-info/RECORD,,