fin-infra 0.1.58__tar.gz → 0.1.60__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.
Files changed (180) hide show
  1. {fin_infra-0.1.58 → fin_infra-0.1.60}/PKG-INFO +1 -1
  2. {fin_infra-0.1.58 → fin_infra-0.1.60}/pyproject.toml +5 -3
  3. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/__init__.py +11 -0
  4. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/analytics/spending.py +8 -7
  5. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/categorization/llm_layer.py +1 -1
  6. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/credit/experian/client.py +14 -26
  7. fin_infra-0.1.60/src/fin_infra/exceptions.py +613 -0
  8. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/investments/add.py +46 -21
  9. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/normalization/currency_converter.py +8 -10
  10. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/normalization/providers/exchangerate.py +6 -5
  11. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/normalization/symbol_resolver.py +7 -6
  12. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/market/coingecko.py +6 -2
  13. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/registry.py +11 -6
  14. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/utils/__init__.py +6 -1
  15. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/utils/retry.py +4 -3
  16. fin_infra-0.1.58/src/fin_infra/utils.py +0 -36
  17. {fin_infra-0.1.58 → fin_infra-0.1.60}/LICENSE +0 -0
  18. {fin_infra-0.1.58 → fin_infra-0.1.60}/README.md +0 -0
  19. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/__main__.py +0 -0
  20. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/analytics/__init__.py +0 -0
  21. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/analytics/add.py +0 -0
  22. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/analytics/cash_flow.py +0 -0
  23. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/analytics/ease.py +0 -0
  24. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/analytics/models.py +0 -0
  25. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/analytics/portfolio.py +0 -0
  26. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/analytics/projections.py +0 -0
  27. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/analytics/rebalancing.py +0 -0
  28. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/analytics/savings.py +0 -0
  29. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/analytics/scenarios.py +0 -0
  30. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/banking/__init__.py +0 -0
  31. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/banking/history.py +0 -0
  32. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/banking/utils.py +0 -0
  33. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/brokerage/__init__.py +0 -0
  34. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/budgets/__init__.py +0 -0
  35. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/budgets/add.py +0 -0
  36. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/budgets/alerts.py +0 -0
  37. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/budgets/ease.py +0 -0
  38. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/budgets/models.py +0 -0
  39. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/budgets/scaffold_templates/README.md +0 -0
  40. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/budgets/scaffold_templates/__init__.py +0 -0
  41. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/budgets/scaffold_templates/models.py.tmpl +0 -0
  42. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/budgets/scaffold_templates/repository.py.tmpl +0 -0
  43. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/budgets/scaffold_templates/schemas.py.tmpl +0 -0
  44. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/budgets/templates.py +0 -0
  45. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/budgets/tracker.py +0 -0
  46. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/cashflows/__init__.py +0 -0
  47. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/cashflows/core.py +0 -0
  48. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/categorization/__init__.py +0 -0
  49. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/categorization/add.py +0 -0
  50. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/categorization/ease.py +0 -0
  51. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/categorization/engine.py +0 -0
  52. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/categorization/models.py +0 -0
  53. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/categorization/rules.py +0 -0
  54. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/categorization/taxonomy.py +0 -0
  55. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/chat/__init__.py +0 -0
  56. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/chat/ease.py +0 -0
  57. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/chat/planning.py +0 -0
  58. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/cli/__init__.py +0 -0
  59. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/cli/cmds/__init__.py +0 -0
  60. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/cli/cmds/scaffold_cmds.py +0 -0
  61. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/clients/__init__.py +0 -0
  62. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/clients/base.py +0 -0
  63. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/clients/plaid.py +0 -0
  64. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/compliance/__init__.py +0 -0
  65. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/credit/__init__.py +0 -0
  66. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/credit/add.py +0 -0
  67. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/credit/experian/__init__.py +0 -0
  68. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/credit/experian/auth.py +0 -0
  69. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/credit/experian/parser.py +0 -0
  70. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/credit/experian/provider.py +0 -0
  71. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/credit/mock.py +0 -0
  72. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/crypto/__init__.py +0 -0
  73. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/crypto/insights.py +0 -0
  74. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/documents/__init__.py +0 -0
  75. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/documents/add.py +0 -0
  76. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/documents/analysis.py +0 -0
  77. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/documents/ease.py +0 -0
  78. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/documents/models.py +0 -0
  79. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/documents/ocr.py +0 -0
  80. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/documents/storage.py +0 -0
  81. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/goals/__init__.py +0 -0
  82. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/goals/add.py +0 -0
  83. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/goals/funding.py +0 -0
  84. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/goals/management.py +0 -0
  85. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/goals/milestones.py +0 -0
  86. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/goals/models.py +0 -0
  87. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/goals/scaffold_templates/README.md +0 -0
  88. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/goals/scaffold_templates/__init__.py +0 -0
  89. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/goals/scaffold_templates/models.py.tmpl +0 -0
  90. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/goals/scaffold_templates/repository.py.tmpl +0 -0
  91. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/goals/scaffold_templates/schemas.py.tmpl +0 -0
  92. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/insights/__init__.py +0 -0
  93. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/insights/aggregator.py +0 -0
  94. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/insights/models.py +0 -0
  95. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/investments/__init__.py +0 -0
  96. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/investments/ease.py +0 -0
  97. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/investments/models.py +0 -0
  98. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/investments/providers/__init__.py +0 -0
  99. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/investments/providers/base.py +0 -0
  100. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/investments/providers/plaid.py +0 -0
  101. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/investments/providers/snaptrade.py +0 -0
  102. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/investments/scaffold_templates/README.md +0 -0
  103. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/investments/scaffold_templates/__init__.py +0 -0
  104. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/investments/scaffold_templates/models.py.tmpl +0 -0
  105. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/investments/scaffold_templates/repository.py.tmpl +0 -0
  106. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/investments/scaffold_templates/schemas.py.tmpl +0 -0
  107. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/markets/__init__.py +0 -0
  108. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/models/__init__.py +0 -0
  109. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/models/accounts.py +0 -0
  110. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/models/brokerage.py +0 -0
  111. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/models/candle.py +0 -0
  112. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/models/credit.py +0 -0
  113. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/models/money.py +0 -0
  114. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/models/quotes.py +0 -0
  115. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/models/tax.py +0 -0
  116. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/models/transactions.py +0 -0
  117. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/net_worth/__init__.py +0 -0
  118. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/net_worth/add.py +0 -0
  119. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/net_worth/aggregator.py +0 -0
  120. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/net_worth/calculator.py +0 -0
  121. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/net_worth/ease.py +0 -0
  122. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/net_worth/goals.py +0 -0
  123. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/net_worth/insights.py +0 -0
  124. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/net_worth/models.py +0 -0
  125. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/net_worth/scaffold_templates/README.md +0 -0
  126. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/net_worth/scaffold_templates/__init__.py +0 -0
  127. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/net_worth/scaffold_templates/models.py.tmpl +0 -0
  128. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/net_worth/scaffold_templates/repository.py.tmpl +0 -0
  129. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/net_worth/scaffold_templates/schemas.py.tmpl +0 -0
  130. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/normalization/__init__.py +0 -0
  131. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/normalization/models.py +0 -0
  132. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/normalization/providers/__init__.py +0 -0
  133. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/normalization/providers/static_mappings.py +0 -0
  134. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/obs/__init__.py +0 -0
  135. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/obs/classifier.py +0 -0
  136. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/__init__.py +0 -0
  137. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/banking/base.py +0 -0
  138. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/banking/plaid_client.py +0 -0
  139. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/banking/teller_client.py +0 -0
  140. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/base.py +0 -0
  141. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/brokerage/alpaca.py +0 -0
  142. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/brokerage/base.py +0 -0
  143. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/credit/experian.py +0 -0
  144. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/identity/stripe_identity.py +0 -0
  145. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/market/alphavantage.py +0 -0
  146. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/market/base.py +0 -0
  147. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/market/ccxt_crypto.py +0 -0
  148. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/market/yahoo.py +0 -0
  149. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/tax/__init__.py +0 -0
  150. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/tax/irs.py +0 -0
  151. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/tax/mock.py +0 -0
  152. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/providers/tax/taxbit.py +0 -0
  153. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/py.typed +0 -0
  154. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/recurring/__init__.py +0 -0
  155. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/recurring/add.py +0 -0
  156. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/recurring/detector.py +0 -0
  157. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/recurring/detectors_llm.py +0 -0
  158. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/recurring/ease.py +0 -0
  159. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/recurring/insights.py +0 -0
  160. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/recurring/models.py +0 -0
  161. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/recurring/normalizer.py +0 -0
  162. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/recurring/normalizers.py +0 -0
  163. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/recurring/summary.py +0 -0
  164. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/scaffold/__init__.py +0 -0
  165. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/scaffold/budgets.py +0 -0
  166. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/scaffold/goals.py +0 -0
  167. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/security/__init__.py +0 -0
  168. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/security/add.py +0 -0
  169. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/security/audit.py +0 -0
  170. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/security/encryption.py +0 -0
  171. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/security/models.py +0 -0
  172. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/security/pii_filter.py +0 -0
  173. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/security/pii_patterns.py +0 -0
  174. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/security/token_store.py +0 -0
  175. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/settings.py +0 -0
  176. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/tax/__init__.py +0 -0
  177. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/tax/add.py +0 -0
  178. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/tax/tlh.py +0 -0
  179. {fin_infra-0.1.58 → fin_infra-0.1.60}/src/fin_infra/utils/http.py +0 -0
  180. {fin_infra-0.1.58 → fin_infra-0.1.60}/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.58
3
+ Version: 0.1.60
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.58"
3
+ version = "0.1.60"
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"
@@ -87,10 +87,12 @@ target-version = "py311"
87
87
  [tool.mypy]
88
88
  python_version = "3.13"
89
89
  ignore_missing_imports = true
90
- no_implicit_optional = false
90
+ no_implicit_optional = true
91
91
  install_types = true
92
92
  non_interactive = true
93
- check_untyped_defs = false
93
+ check_untyped_defs = true
94
+ warn_return_any = true
95
+ warn_unused_ignores = true
94
96
  files = "src"
95
97
  exclude = '^(\.venv|venv|build|dist|node_modules|tests)/'
96
98
  plugins = ["pydantic.mypy"]
@@ -4,8 +4,19 @@ Public surface is intentionally small at this stage. Import from submodules for
4
4
  specific domains (clients, models, markets, credit).
5
5
  """
6
6
 
7
+ from .exceptions import (
8
+ FinInfraError,
9
+ ProviderError,
10
+ ProviderNotFoundError,
11
+ ValidationError,
12
+ )
7
13
  from .version import __version__
8
14
 
9
15
  __all__ = [
10
16
  "__version__",
17
+ # Base errors
18
+ "FinInfraError",
19
+ "ProviderError",
20
+ "ProviderNotFoundError",
21
+ "ValidationError",
11
22
  ]
@@ -44,6 +44,7 @@ Examples:
44
44
 
45
45
  from collections import defaultdict
46
46
  from datetime import timedelta
47
+ from decimal import Decimal
47
48
  from typing import Optional
48
49
 
49
50
  from fin_infra.analytics.models import (
@@ -132,7 +133,7 @@ async def analyze_spending(
132
133
  ]
133
134
 
134
135
  # Calculate top merchants
135
- merchant_totals: dict[str, float] = defaultdict(float)
136
+ merchant_totals: dict[str, Decimal] = defaultdict(Decimal)
136
137
  for t in expense_transactions:
137
138
  merchant = _extract_merchant_name(t.description or "Unknown")
138
139
  merchant_totals[merchant] += abs(t.amount)
@@ -142,7 +143,7 @@ async def analyze_spending(
142
143
  ] # Top 10 merchants
143
144
 
144
145
  # Calculate category breakdown
145
- category_totals: dict[str, float] = defaultdict(float)
146
+ category_totals: dict[str, Decimal] = defaultdict(Decimal)
146
147
  for t in expense_transactions:
147
148
  category = _get_transaction_category(t)
148
149
  category_totals[category] += abs(t.amount)
@@ -261,7 +262,7 @@ def _get_transaction_category(transaction: Transaction) -> str:
261
262
 
262
263
  async def _calculate_spending_trends(
263
264
  user_id: str,
264
- current_category_totals: dict[str, float],
265
+ current_category_totals: dict[str, Decimal],
265
266
  current_period_days: int,
266
267
  banking_provider=None,
267
268
  categorization_provider=None,
@@ -288,7 +289,7 @@ async def _calculate_spending_trends(
288
289
  for category, current_amount in current_category_totals.items():
289
290
  # Mock: assume previous period was 10% lower on average
290
291
  # In reality, would fetch historical data
291
- previous_amount = current_amount * 0.9
292
+ previous_amount = current_amount * Decimal("0.9")
292
293
 
293
294
  change_percent = (
294
295
  ((current_amount - previous_amount) / previous_amount) * 100
@@ -311,7 +312,7 @@ async def _calculate_spending_trends(
311
312
 
312
313
  async def _detect_spending_anomalies(
313
314
  user_id: str,
314
- current_category_totals: dict[str, float],
315
+ current_category_totals: dict[str, Decimal],
315
316
  current_period_days: int,
316
317
  banking_provider=None,
317
318
  categorization_provider=None,
@@ -339,7 +340,7 @@ async def _detect_spending_anomalies(
339
340
  for category, current_amount in current_category_totals.items():
340
341
  # Mock: assume historical average is current amount * 0.8
341
342
  # In reality, would calculate from historical data
342
- average_amount = current_amount * 0.8
343
+ average_amount = current_amount * Decimal("0.8")
343
344
 
344
345
  deviation_percent = (
345
346
  ((current_amount - average_amount) / average_amount) * 100 if average_amount > 0 else 0
@@ -409,7 +410,7 @@ def _generate_mock_transactions(days: int) -> list[Transaction]:
409
410
  Transaction(
410
411
  id=f"mock_{i}",
411
412
  account_id="mock_account",
412
- amount=float(amount),
413
+ amount=Decimal(str(amount)),
413
414
  date=base_date - timedelta(days=days_ago),
414
415
  description=description,
415
416
  )
@@ -20,7 +20,7 @@ from pydantic import BaseModel, Field
20
20
 
21
21
  # ai-infra imports
22
22
  try:
23
- from ai_infra.llm import LLM
23
+ from ai_infra.llm import CoreLLM as LLM
24
24
  from ai_infra.llm.providers import Providers
25
25
  except ImportError:
26
26
  raise ImportError("ai-infra not installed. Install with: pip install ai-infra")
@@ -25,33 +25,21 @@ from tenacity import (
25
25
  )
26
26
 
27
27
  from fin_infra.credit.experian.auth import ExperianAuthManager
28
+ from fin_infra.exceptions import (
29
+ ExperianAPIError,
30
+ ExperianAuthError,
31
+ ExperianNotFoundError,
32
+ ExperianRateLimitError,
33
+ )
28
34
 
29
-
30
- class ExperianAPIError(Exception):
31
- """Base exception for Experian API errors."""
32
-
33
- def __init__(self, message: str, status_code: int | None = None, response: dict | None = None):
34
- super().__init__(message)
35
- self.status_code = status_code
36
- self.response = response
37
-
38
-
39
- class ExperianRateLimitError(ExperianAPIError):
40
- """Raised when rate limit is exceeded (429)."""
41
-
42
- pass
43
-
44
-
45
- class ExperianAuthError(ExperianAPIError):
46
- """Raised when authentication fails (401)."""
47
-
48
- pass
49
-
50
-
51
- class ExperianNotFoundError(ExperianAPIError):
52
- """Raised when user not found in bureau (404)."""
53
-
54
- pass
35
+ # Re-export for backward compatibility
36
+ __all__ = [
37
+ "ExperianAPIError",
38
+ "ExperianAuthError",
39
+ "ExperianNotFoundError",
40
+ "ExperianRateLimitError",
41
+ "ExperianClient",
42
+ ]
55
43
 
56
44
 
57
45
  class ExperianClient: