tax-engine 0.1.0__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.
Files changed (599) hide show
  1. tax_engine/__init__.py +6 -0
  2. tax_engine/adapters/__init__.py +1 -0
  3. tax_engine/adapters/inbound/__init__.py +1 -0
  4. tax_engine/adapters/inbound/trace_english/__init__.py +45 -0
  5. tax_engine/adapters/inbound/trace_english/arithmetic.py +619 -0
  6. tax_engine/adapters/inbound/trace_english/blank.py +73 -0
  7. tax_engine/adapters/inbound/trace_english/choices.py +125 -0
  8. tax_engine/adapters/inbound/trace_english/figures.py +47 -0
  9. tax_engine/adapters/inbound/trace_english/forms.py +45 -0
  10. tax_engine/adapters/inbound/trace_english/line_renderer.py +26 -0
  11. tax_engine/adapters/inbound/trace_english/names.py +169 -0
  12. tax_engine/adapters/inbound/trace_english/rate_tables.py +178 -0
  13. tax_engine/adapters/inbound/trace_english/record_lists.py +149 -0
  14. tax_engine/adapters/inbound/trace_english/registry.py +96 -0
  15. tax_engine/adapters/inbound/trace_english/renderer.py +51 -0
  16. tax_engine/adapters/inbound/trace_english/unit_text.py +123 -0
  17. tax_engine/adapters/inbound/unit_text.py +64 -0
  18. tax_engine/adapters/outbound/__init__.py +1 -0
  19. tax_engine/adapters/outbound/capability_modules.py +38 -0
  20. tax_engine/adapters/outbound/jurisdiction_packages.py +188 -0
  21. tax_engine/adapters/outbound/parameter_parser.py +126 -0
  22. tax_engine/adapters/outbound/parser_modules.py +33 -0
  23. tax_engine/adapters/outbound/yaml_jurisdictions.py +967 -0
  24. tax_engine/adapters/outbound/yaml_parameters.py +137 -0
  25. tax_engine/adapters/outbound/yaml_support.py +265 -0
  26. tax_engine/adapters/text.py +73 -0
  27. tax_engine/application/__init__.py +1 -0
  28. tax_engine/application/ports/__init__.py +1 -0
  29. tax_engine/application/ports/jurisdiction_source.py +17 -0
  30. tax_engine/application/ports/parameter_source.py +22 -0
  31. tax_engine/application/services/__init__.py +1 -0
  32. tax_engine/application/services/tax_computation.py +100 -0
  33. tax_engine/domain/__init__.py +1 -0
  34. tax_engine/domain/artifact.py +261 -0
  35. tax_engine/domain/blank.py +54 -0
  36. tax_engine/domain/capability.py +626 -0
  37. tax_engine/domain/capability_builder.py +244 -0
  38. tax_engine/domain/composition.py +256 -0
  39. tax_engine/domain/errors.py +219 -0
  40. tax_engine/domain/figure_names.py +54 -0
  41. tax_engine/domain/form.py +616 -0
  42. tax_engine/domain/jurisdiction.py +40 -0
  43. tax_engine/domain/jurisdiction_code.py +37 -0
  44. tax_engine/domain/kinds.py +247 -0
  45. tax_engine/domain/manifest.py +475 -0
  46. tax_engine/domain/parameters/__init__.py +5 -0
  47. tax_engine/domain/parameters/amount.py +31 -0
  48. tax_engine/domain/parameters/amount_by_band.py +122 -0
  49. tax_engine/domain/parameters/brackets.py +189 -0
  50. tax_engine/domain/parameters/class_rates.py +180 -0
  51. tax_engine/domain/parameters/conditions.py +195 -0
  52. tax_engine/domain/parameters/credit.py +31 -0
  53. tax_engine/domain/parameters/datasets.py +41 -0
  54. tax_engine/domain/parameters/factor.py +33 -0
  55. tax_engine/domain/parameters/fraction.py +38 -0
  56. tax_engine/domain/parameters/kind.py +34 -0
  57. tax_engine/domain/parameters/rate.py +31 -0
  58. tax_engine/domain/parameters/rate_table.py +111 -0
  59. tax_engine/domain/parameters/rounding.py +148 -0
  60. tax_engine/domain/parameters/rounding_only.py +19 -0
  61. tax_engine/domain/parameters/surcharge_tiers.py +91 -0
  62. tax_engine/domain/parameters/threshold_rate.py +45 -0
  63. tax_engine/domain/record_list.py +156 -0
  64. tax_engine/domain/registry.py +138 -0
  65. tax_engine/domain/trace/__init__.py +37 -0
  66. tax_engine/domain/trace/arithmetic.py +918 -0
  67. tax_engine/domain/trace/base.py +31 -0
  68. tax_engine/domain/trace/blank.py +106 -0
  69. tax_engine/domain/trace/choices.py +142 -0
  70. tax_engine/domain/trace/forms.py +36 -0
  71. tax_engine/domain/trace/rate_tables.py +224 -0
  72. tax_engine/domain/trace/record_lists.py +174 -0
  73. tax_engine/domain/unit.py +101 -0
  74. tax_engine/domain/worksheet.py +202 -0
  75. tax_engine/factory.py +27 -0
  76. tax_engine/jurisdictions/__init__.py +5 -0
  77. tax_engine/jurisdictions/ca/__init__.py +11 -0
  78. tax_engine/jurisdictions/ca/capabilities/__init__.py +7 -0
  79. tax_engine/jurisdictions/ca/capabilities/amount_by_count.py +60 -0
  80. tax_engine/jurisdictions/ca/capabilities/amount_or_divided_by_rate.py +76 -0
  81. tax_engine/jurisdictions/ca/capabilities/contribution_tier.py +79 -0
  82. tax_engine/jurisdictions/ca/capabilities/count_by_conditions.py +147 -0
  83. tax_engine/jurisdictions/ca/capabilities/given_or_contribution_tier.py +68 -0
  84. tax_engine/jurisdictions/ca/capabilities/tapered_amount.py +58 -0
  85. tax_engine/jurisdictions/ca/capabilities/yes_or_no_count.py +47 -0
  86. tax_engine/jurisdictions/ca/catalog/__init__.py +42 -0
  87. tax_engine/jurisdictions/ca/catalog/alternative_minimum_tax.py +1152 -0
  88. tax_engine/jurisdictions/ca/catalog/base.py +13 -0
  89. tax_engine/jurisdictions/ca/catalog/canada_workers_benefit.py +139 -0
  90. tax_engine/jurisdictions/ca/catalog/capital_gains_deduction_charts.py +1429 -0
  91. tax_engine/jurisdictions/ca/catalog/credits_against_federal_tax.py +445 -0
  92. tax_engine/jurisdictions/ca/catalog/deductions.py +172 -0
  93. tax_engine/jurisdictions/ca/catalog/income.py +73 -0
  94. tax_engine/jurisdictions/ca/catalog/investment_tax_credit.py +296 -0
  95. tax_engine/jurisdictions/ca/catalog/net_tax.py +280 -0
  96. tax_engine/jurisdictions/ca/catalog/non_refundable_credits.py +1176 -0
  97. tax_engine/jurisdictions/ca/catalog/other_inputs.py +203 -0
  98. tax_engine/jurisdictions/ca/catalog/personal_amounts.py +1429 -0
  99. tax_engine/jurisdictions/ca/catalog/rc381_cpp_qpp.py +910 -0
  100. tax_engine/jurisdictions/ca/catalog/refund.py +547 -0
  101. tax_engine/jurisdictions/ca/catalog/refundable_credits.py +311 -0
  102. tax_engine/jurisdictions/ca/catalog/resp_aips.py +106 -0
  103. tax_engine/jurisdictions/ca/catalog/rrsp_fhsa.py +459 -0
  104. tax_engine/jurisdictions/ca/catalog/t1032_pension_income_splitting.py +620 -0
  105. tax_engine/jurisdictions/ca/catalog/t1043.py +139 -0
  106. tax_engine/jurisdictions/ca/catalog/t1139.py +748 -0
  107. tax_engine/jurisdictions/ca/catalog/t1206_share_dispositions.py +177 -0
  108. tax_engine/jurisdictions/ca/catalog/t1212.py +39 -0
  109. tax_engine/jurisdictions/ca/catalog/t2017_reserve.py +581 -0
  110. tax_engine/jurisdictions/ca/catalog/t2205.py +206 -0
  111. tax_engine/jurisdictions/ca/catalog/t746.py +138 -0
  112. tax_engine/jurisdictions/ca/catalog/t777.py +1374 -0
  113. tax_engine/jurisdictions/ca/catalog/t90.py +130 -0
  114. tax_engine/jurisdictions/ca/catalog/t936.py +260 -0
  115. tax_engine/jurisdictions/ca/catalog/taxable_income.py +50 -0
  116. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6.yaml +11 -0
  117. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_1.yaml +20 -0
  118. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_10.yaml +17 -0
  119. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_11_inputs.yaml +14 -0
  120. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_12.yaml +22 -0
  121. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_13.yaml +19 -0
  122. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_14_inputs.yaml +17 -0
  123. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_15.yaml +26 -0
  124. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_17.yaml +14 -0
  125. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_18.yaml +19 -0
  126. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_20.yaml +18 -0
  127. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_21.yaml +15 -0
  128. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_22.yaml +18 -0
  129. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_24.yaml +15 -0
  130. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_25.yaml +21 -0
  131. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_27.yaml +18 -0
  132. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_28.yaml +22 -0
  133. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_5.yaml +19 -0
  134. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_6.yaml +19 -0
  135. tax_engine/jurisdictions/ca/forms/schedule_6/schedule_6_line_7.yaml +21 -0
  136. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8.yaml +17 -0
  137. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8_inputs.yaml +13 -0
  138. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8_line_1.yaml +18 -0
  139. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8_line_11.yaml +18 -0
  140. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8_line_12.yaml +17 -0
  141. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8_line_2.yaml +16 -0
  142. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8_line_22.yaml +18 -0
  143. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8_line_25.yaml +24 -0
  144. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8_line_28.yaml +17 -0
  145. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8_line_4.yaml +17 -0
  146. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8_line_5.yaml +14 -0
  147. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8_line_7.yaml +27 -0
  148. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8_line_b.yaml +15 -0
  149. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8_line_d.yaml +17 -0
  150. tax_engine/jurisdictions/ca/forms/schedule_8/schedule_8_line_e.yaml +15 -0
  151. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits.yaml +30 -0
  152. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_101.yaml +19 -0
  153. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_106.yaml +19 -0
  154. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_125.yaml +21 -0
  155. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_128.yaml +20 -0
  156. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_130.yaml +20 -0
  157. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_132.yaml +19 -0
  158. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_167.yaml +21 -0
  159. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_30000.yaml +30 -0
  160. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_31260.yaml +27 -0
  161. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_33500.yaml +19 -0
  162. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_33800.yaml +17 -0
  163. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_35000.yaml +22 -0
  164. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_40400.yaml +21 -0
  165. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_40500_inputs.yaml +14 -0
  166. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_40600.yaml +20 -0
  167. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_40600_inputs.yaml +15 -0
  168. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_41600.yaml +20 -0
  169. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_41700.yaml +19 -0
  170. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_42000.yaml +20 -0
  171. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_42900.yaml +19 -0
  172. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_43500.yaml +37 -0
  173. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_48200.yaml +54 -0
  174. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_76.yaml +80 -0
  175. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_84.yaml +20 -0
  176. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_96.yaml +39 -0
  177. tax_engine/jurisdictions/ca/forms/t1_tax_and_credits/t1_tax_and_credits_line_98.yaml +21 -0
  178. tax_engine/jurisdictions/ca/forms/t1_taxable_income/t1_taxable_income.yaml +18 -0
  179. tax_engine/jurisdictions/ca/forms/t1_taxable_income/t1_taxable_income_inputs.yaml +14 -0
  180. tax_engine/jurisdictions/ca/forms/t1_taxable_income/t1_taxable_income_line_10400_inputs.yaml +14 -0
  181. tax_engine/jurisdictions/ca/forms/t1_taxable_income/t1_taxable_income_line_15000.yaml +20 -0
  182. tax_engine/jurisdictions/ca/forms/t1_taxable_income/t1_taxable_income_line_23300.yaml +14 -0
  183. tax_engine/jurisdictions/ca/forms/t1_taxable_income/t1_taxable_income_line_23400.yaml +22 -0
  184. tax_engine/jurisdictions/ca/forms/t1_taxable_income/t1_taxable_income_line_23600.yaml +19 -0
  185. tax_engine/jurisdictions/ca/forms/t1_taxable_income/t1_taxable_income_line_23600_signed.yaml +24 -0
  186. tax_engine/jurisdictions/ca/forms/t1_taxable_income/t1_taxable_income_line_25700_inputs.yaml +13 -0
  187. tax_engine/jurisdictions/ca/forms/t1_taxable_income/t1_taxable_income_line_26000.yaml +23 -0
  188. tax_engine/jurisdictions/ca/forms/t2204/t2204.yaml +15 -0
  189. tax_engine/jurisdictions/ca/forms/t2204/t2204_inputs.yaml +34 -0
  190. tax_engine/jurisdictions/ca/forms/t2204/t2204_line_1.yaml +46 -0
  191. tax_engine/jurisdictions/ca/forms/t2204/t2204_line_10.yaml +16 -0
  192. tax_engine/jurisdictions/ca/forms/t2204/t2204_line_13.yaml +20 -0
  193. tax_engine/jurisdictions/ca/forms/t2204/t2204_line_14.yaml +17 -0
  194. tax_engine/jurisdictions/ca/forms/t2204/t2204_line_15.yaml +46 -0
  195. tax_engine/jurisdictions/ca/forms/t2204/t2204_line_16.yaml +19 -0
  196. tax_engine/jurisdictions/ca/forms/t2204/t2204_line_3.yaml +32 -0
  197. tax_engine/jurisdictions/ca/forms/t2204/t2204_line_4.yaml +25 -0
  198. tax_engine/jurisdictions/ca/forms/t2204/t2204_line_6.yaml +23 -0
  199. tax_engine/jurisdictions/ca/forms/t2204/t2204_line_7.yaml +24 -0
  200. tax_engine/jurisdictions/ca/forms/t2204/t2204_line_8.yaml +18 -0
  201. tax_engine/jurisdictions/ca/parameter_parsers/__init__.py +2 -0
  202. tax_engine/jurisdictions/ca/parameter_parsers/amount_by_count.py +28 -0
  203. tax_engine/jurisdictions/ca/parameter_parsers/claim_reduction.py +30 -0
  204. tax_engine/jurisdictions/ca/parameter_parsers/contribution_tier.py +28 -0
  205. tax_engine/jurisdictions/ca/parameter_parsers/taper.py +24 -0
  206. tax_engine/jurisdictions/ca/parameter_parsers/year_amounts.py +40 -0
  207. tax_engine/jurisdictions/ca/parameter_shapes/__init__.py +1 -0
  208. tax_engine/jurisdictions/ca/parameter_shapes/amount_by_count.py +61 -0
  209. tax_engine/jurisdictions/ca/parameter_shapes/claim_reduction.py +45 -0
  210. tax_engine/jurisdictions/ca/parameter_shapes/contribution_tier.py +58 -0
  211. tax_engine/jurisdictions/ca/parameter_shapes/taper.py +48 -0
  212. tax_engine/jurisdictions/ca/parameter_shapes/year_amounts.py +90 -0
  213. tax_engine/jurisdictions/ca/parameters/age_income_threshold/2025.yaml +13 -0
  214. tax_engine/jurisdictions/ca/parameters/age_maximum/2025.yaml +13 -0
  215. tax_engine/jurisdictions/ca/parameters/age_rate/2025.yaml +14 -0
  216. tax_engine/jurisdictions/ca/parameters/amt_applicable_rate/2025.yaml +11 -0
  217. tax_engine/jurisdictions/ca/parameters/amt_basic_exemption/2025.yaml +11 -0
  218. tax_engine/jurisdictions/ca/parameters/amt_federal_surtax_rate/2025.yaml +14 -0
  219. tax_engine/jurisdictions/ca/parameters/amt_federal_tax_rate/2025.yaml +13 -0
  220. tax_engine/jurisdictions/ca/parameters/amt_non_refundable_credits_rate/2025.yaml +11 -0
  221. tax_engine/jurisdictions/ca/parameters/amt_t2203_column_5_percentage_maximum/2025.yaml +15 -0
  222. tax_engine/jurisdictions/ca/parameters/basic_personal_amount/2025.yaml +37 -0
  223. tax_engine/jurisdictions/ca/parameters/basic_personal_amount/2026.yaml +17 -0
  224. tax_engine/jurisdictions/ca/parameters/brackets/2025.yaml +33 -0
  225. tax_engine/jurisdictions/ca/parameters/brackets/2026.yaml +21 -0
  226. tax_engine/jurisdictions/ca/parameters/canada_employment_amount/2025.yaml +17 -0
  227. tax_engine/jurisdictions/ca/parameters/canada_employment_amount/2026.yaml +12 -0
  228. tax_engine/jurisdictions/ca/parameters/cent_rounding/2025.yaml +20 -0
  229. tax_engine/jurisdictions/ca/parameters/cent_rounding/2026.yaml +22 -0
  230. tax_engine/jurisdictions/ca/parameters/chart_2016_part_1_amount_a/2025.yaml +10 -0
  231. tax_engine/jurisdictions/ca/parameters/chart_2016_part_2_amount_a/2025.yaml +10 -0
  232. tax_engine/jurisdictions/ca/parameters/chart_2017_part_1_amount_a/2025.yaml +10 -0
  233. tax_engine/jurisdictions/ca/parameters/chart_2017_part_2_amount_a/2025.yaml +10 -0
  234. tax_engine/jurisdictions/ca/parameters/chart_2018_part_1_amount_a/2025.yaml +10 -0
  235. tax_engine/jurisdictions/ca/parameters/chart_2018_part_2_amount_a/2025.yaml +10 -0
  236. tax_engine/jurisdictions/ca/parameters/chart_2019_part_1_amount_a/2025.yaml +10 -0
  237. tax_engine/jurisdictions/ca/parameters/chart_2019_part_2_amount_a/2025.yaml +10 -0
  238. tax_engine/jurisdictions/ca/parameters/chart_2020_part_1_amount_a/2025.yaml +10 -0
  239. tax_engine/jurisdictions/ca/parameters/chart_2020_part_2_amount_a/2025.yaml +10 -0
  240. tax_engine/jurisdictions/ca/parameters/chart_2021_part_1_amount_a/2025.yaml +9 -0
  241. tax_engine/jurisdictions/ca/parameters/chart_2021_part_2_amount_a/2025.yaml +9 -0
  242. tax_engine/jurisdictions/ca/parameters/chart_2022_part_1_amount_a/2025.yaml +9 -0
  243. tax_engine/jurisdictions/ca/parameters/chart_2022_part_2_amount_a/2025.yaml +9 -0
  244. tax_engine/jurisdictions/ca/parameters/chart_2023_part_1_amount_a/2025.yaml +9 -0
  245. tax_engine/jurisdictions/ca/parameters/chart_2023_part_2_amount_a/2025.yaml +9 -0
  246. tax_engine/jurisdictions/ca/parameters/chart_2024_period_1_amount_a/2025.yaml +10 -0
  247. tax_engine/jurisdictions/ca/parameters/chart_2024_period_2_amount_a/2025.yaml +10 -0
  248. tax_engine/jurisdictions/ca/parameters/chart_2025_part_1_amount_a/2025.yaml +10 -0
  249. tax_engine/jurisdictions/ca/parameters/chart_2025_part_2_amount_a/2025.yaml +10 -0
  250. tax_engine/jurisdictions/ca/parameters/chart_2_numerator_one/2025.yaml +10 -0
  251. tax_engine/jurisdictions/ca/parameters/child_care_earned_income_fraction/2025.yaml +14 -0
  252. tax_engine/jurisdictions/ca/parameters/cpp_additional_maximum_pensionable_earnings/2025.yaml +31 -0
  253. tax_engine/jurisdictions/ca/parameters/cpp_additional_maximum_pensionable_earnings/2026.yaml +30 -0
  254. tax_engine/jurisdictions/ca/parameters/cpp_basic_exemption/2025.yaml +30 -0
  255. tax_engine/jurisdictions/ca/parameters/cpp_basic_exemption/2026.yaml +29 -0
  256. tax_engine/jurisdictions/ca/parameters/cpp_line_11_base_contribution/2025.yaml +21 -0
  257. tax_engine/jurisdictions/ca/parameters/cpp_line_11_base_contribution/2026.yaml +16 -0
  258. tax_engine/jurisdictions/ca/parameters/cpp_line_12_first_additional_contribution/2025.yaml +18 -0
  259. tax_engine/jurisdictions/ca/parameters/cpp_line_12_first_additional_contribution/2026.yaml +16 -0
  260. tax_engine/jurisdictions/ca/parameters/cpp_line_22_second_additional_contribution/2025.yaml +16 -0
  261. tax_engine/jurisdictions/ca/parameters/cpp_line_22_second_additional_contribution/2026.yaml +16 -0
  262. tax_engine/jurisdictions/ca/parameters/cpp_line_7_maximum/2025.yaml +14 -0
  263. tax_engine/jurisdictions/ca/parameters/cpp_line_7_maximum/2026.yaml +14 -0
  264. tax_engine/jurisdictions/ca/parameters/cpp_maximum_pensionable_earnings/2025.yaml +30 -0
  265. tax_engine/jurisdictions/ca/parameters/cpp_maximum_pensionable_earnings/2026.yaml +29 -0
  266. tax_engine/jurisdictions/ca/parameters/cpp_pensionable_earnings_per_slip_maximum/2025.yaml +15 -0
  267. tax_engine/jurisdictions/ca/parameters/cpp_pensionable_earnings_per_slip_maximum/2026.yaml +14 -0
  268. tax_engine/jurisdictions/ca/parameters/cpp_second_additional_earnings_maximum/2025.yaml +31 -0
  269. tax_engine/jurisdictions/ca/parameters/cpp_second_additional_earnings_maximum/2026.yaml +31 -0
  270. tax_engine/jurisdictions/ca/parameters/credit_rate/2025.yaml +13 -0
  271. tax_engine/jurisdictions/ca/parameters/credit_rate/2026.yaml +11 -0
  272. tax_engine/jurisdictions/ca/parameters/cwb_base_amount/2025.yaml +10 -0
  273. tax_engine/jurisdictions/ca/parameters/cwb_base_amount/2026.yaml +11 -0
  274. tax_engine/jurisdictions/ca/parameters/cwb_maximum/2025.yaml +11 -0
  275. tax_engine/jurisdictions/ca/parameters/cwb_maximum/2026.yaml +11 -0
  276. tax_engine/jurisdictions/ca/parameters/cwb_rate/2025.yaml +11 -0
  277. tax_engine/jurisdictions/ca/parameters/cwb_rate/2026.yaml +13 -0
  278. tax_engine/jurisdictions/ca/parameters/cwb_reduction_rate/2025.yaml +11 -0
  279. tax_engine/jurisdictions/ca/parameters/cwb_reduction_rate/2026.yaml +13 -0
  280. tax_engine/jurisdictions/ca/parameters/cwb_reduction_threshold/2025.yaml +13 -0
  281. tax_engine/jurisdictions/ca/parameters/cwb_reduction_threshold/2026.yaml +11 -0
  282. tax_engine/jurisdictions/ca/parameters/disability_self_base_amount/2025.yaml +13 -0
  283. tax_engine/jurisdictions/ca/parameters/disability_self_care_threshold/2025.yaml +13 -0
  284. tax_engine/jurisdictions/ca/parameters/disability_self_supplement_maximum/2025.yaml +12 -0
  285. tax_engine/jurisdictions/ca/parameters/donation_first_tier_maximum/2025.yaml +12 -0
  286. tax_engine/jurisdictions/ca/parameters/donation_high_income_threshold/2025.yaml +12 -0
  287. tax_engine/jurisdictions/ca/parameters/donation_high_income_threshold/2026.yaml +16 -0
  288. tax_engine/jurisdictions/ca/parameters/donation_net_income_rate/2025.yaml +11 -0
  289. tax_engine/jurisdictions/ca/parameters/donation_net_income_rate/2026.yaml +13 -0
  290. tax_engine/jurisdictions/ca/parameters/ei_maximum_insurable_earnings/2025.yaml +15 -0
  291. tax_engine/jurisdictions/ca/parameters/ei_maximum_insurable_earnings/2026.yaml +15 -0
  292. tax_engine/jurisdictions/ca/parameters/ei_premium/2025.yaml +24 -0
  293. tax_engine/jurisdictions/ca/parameters/ei_premium/2026.yaml +18 -0
  294. tax_engine/jurisdictions/ca/parameters/fhsa_annual_amount/2025.yaml +13 -0
  295. tax_engine/jurisdictions/ca/parameters/fhsa_lifetime_limit/2025.yaml +12 -0
  296. tax_engine/jurisdictions/ca/parameters/foreign_property_income_credit_limit_rate/2025.yaml +14 -0
  297. tax_engine/jurisdictions/ca/parameters/home_buyers_maximum/2025.yaml +16 -0
  298. tax_engine/jurisdictions/ca/parameters/logging_income_rate/2025.yaml +14 -0
  299. tax_engine/jurisdictions/ca/parameters/medical_net_income_rate/2025.yaml +12 -0
  300. tax_engine/jurisdictions/ca/parameters/medical_threshold_ceiling/2025.yaml +13 -0
  301. tax_engine/jurisdictions/ca/parameters/net_capital_loss_numerator_one_2000/2025.yaml +10 -0
  302. tax_engine/jurisdictions/ca/parameters/northern_residency_rate/2025.yaml +11 -0
  303. tax_engine/jurisdictions/ca/parameters/oas_benefits_base_amount/2025.yaml +13 -0
  304. tax_engine/jurisdictions/ca/parameters/other_payments_line_9_over_limit_conditions/2025.yaml +19 -0
  305. tax_engine/jurisdictions/ca/parameters/political_credit_column_2_line_2/2025.yaml +12 -0
  306. tax_engine/jurisdictions/ca/parameters/political_credit_column_2_line_6/2025.yaml +12 -0
  307. tax_engine/jurisdictions/ca/parameters/political_credit_column_3_line_2/2025.yaml +12 -0
  308. tax_engine/jurisdictions/ca/parameters/political_credit_column_3_line_6/2025.yaml +12 -0
  309. tax_engine/jurisdictions/ca/parameters/political_credit_shortcut_amount/2025.yaml +14 -0
  310. tax_engine/jurisdictions/ca/parameters/political_credit_shortcut_threshold/2025.yaml +14 -0
  311. tax_engine/jurisdictions/ca/parameters/resp_aips_lifetime_limit/2025.yaml +12 -0
  312. tax_engine/jurisdictions/ca/parameters/schedule_8_zero/2025.yaml +11 -0
  313. tax_engine/jurisdictions/ca/parameters/schedule_8_zero/2026.yaml +13 -0
  314. tax_engine/jurisdictions/ca/parameters/social_benefits_repayment_rate/2025.yaml +11 -0
  315. tax_engine/jurisdictions/ca/parameters/spouse_caregiver_base/2025.yaml +15 -0
  316. tax_engine/jurisdictions/ca/parameters/spouse_caregiver_maximum/2025.yaml +13 -0
  317. tax_engine/jurisdictions/ca/parameters/spouse_designated_tuition_maximum/2025.yaml +15 -0
  318. tax_engine/jurisdictions/ca/parameters/spouse_return_age_amount_maximum/2025.yaml +13 -0
  319. tax_engine/jurisdictions/ca/parameters/spouse_return_basic_personal_amount_maximum/2025.yaml +13 -0
  320. tax_engine/jurisdictions/ca/parameters/spouse_return_disability_amount_maximum/2025.yaml +13 -0
  321. tax_engine/jurisdictions/ca/parameters/spouse_return_pension_income_amount_maximum/2025.yaml +13 -0
  322. tax_engine/jurisdictions/ca/parameters/t2204_exemption/2025.yaml +11 -0
  323. tax_engine/jurisdictions/ca/parameters/t2204_exemption/2026.yaml +13 -0
  324. tax_engine/jurisdictions/ca/parameters/t2204_line_15_conditions/2025.yaml +17 -0
  325. tax_engine/jurisdictions/ca/parameters/t2204_line_15_conditions/2026.yaml +19 -0
  326. tax_engine/jurisdictions/ca/parameters/t2204_line_1_conditions/2025.yaml +25 -0
  327. tax_engine/jurisdictions/ca/parameters/t2204_line_1_conditions/2026.yaml +27 -0
  328. tax_engine/jurisdictions/ca/parameters/t2204_maximum_insurable_earnings/2025.yaml +14 -0
  329. tax_engine/jurisdictions/ca/parameters/t2204_maximum_insurable_earnings/2026.yaml +16 -0
  330. tax_engine/jurisdictions/ca/parameters/top_up_threshold/2025.yaml +12 -0
  331. tax_engine/jurisdictions/ca/parameters/tuition_income_limit/2025.yaml +15 -0
  332. tax_engine/jurisdictions/ca/trace/__init__.py +27 -0
  333. tax_engine/jurisdictions/ca/trace/amount_by_count.py +36 -0
  334. tax_engine/jurisdictions/ca/trace/contribution_tier.py +41 -0
  335. tax_engine/jurisdictions/ca/trace/given_amount.py +30 -0
  336. tax_engine/jurisdictions/ca/trace/tapered_amount.py +42 -0
  337. tax_engine/jurisdictions/ca/trace_english/__init__.py +17 -0
  338. tax_engine/jurisdictions/ca/trace_english/amount_by_count.py +25 -0
  339. tax_engine/jurisdictions/ca/trace_english/contribution_tier.py +30 -0
  340. tax_engine/jurisdictions/ca/trace_english/given_amount.py +20 -0
  341. tax_engine/jurisdictions/ca/trace_english/tapered_amount.py +37 -0
  342. tax_engine/jurisdictions/ca/trace_english/units.py +11 -0
  343. tax_engine/jurisdictions/ca/units.py +8 -0
  344. tax_engine/jurisdictions/ca_ab/__init__.py +11 -0
  345. tax_engine/jurisdictions/ca_ab/capabilities/__init__.py +7 -0
  346. tax_engine/jurisdictions/ca_ab/capabilities/tax_on_taxable_income.py +78 -0
  347. tax_engine/jurisdictions/ca_ab/catalog.py +391 -0
  348. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428.yaml +17 -0
  349. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_credits.yaml +21 -0
  350. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_credits_line_1.yaml +15 -0
  351. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_credits_line_27.yaml +14 -0
  352. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_credits_line_32.yaml +17 -0
  353. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_credits_line_33.yaml +17 -0
  354. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_credits_line_36.yaml +18 -0
  355. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_credits_line_39.yaml +16 -0
  356. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_credits_line_41.yaml +20 -0
  357. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_credits_line_43.yaml +17 -0
  358. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_credits_line_5.yaml +18 -0
  359. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_credits_line_52.yaml +20 -0
  360. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_credits_line_54.yaml +16 -0
  361. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_credits_line_58.yaml +21 -0
  362. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_10.yaml +18 -0
  363. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_11.yaml +19 -0
  364. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_12.yaml +18 -0
  365. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_13.yaml +19 -0
  366. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_14.yaml +18 -0
  367. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_15.yaml +21 -0
  368. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_16.yaml +14 -0
  369. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_25.yaml +16 -0
  370. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_29.yaml +13 -0
  371. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_3.yaml +20 -0
  372. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_34_inputs.yaml +12 -0
  373. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_4.yaml +20 -0
  374. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_41_input.yaml +14 -0
  375. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_51_inputs.yaml +12 -0
  376. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_57_inputs.yaml +11 -0
  377. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_59.yaml +22 -0
  378. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_6.yaml +19 -0
  379. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_60_inputs.yaml +12 -0
  380. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_61.yaml +21 -0
  381. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_62.yaml +14 -0
  382. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_63_inputs.yaml +11 -0
  383. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_64.yaml +19 -0
  384. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_64_inputs.yaml +12 -0
  385. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_65.yaml +23 -0
  386. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_66.yaml +18 -0
  387. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_67.yaml +19 -0
  388. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_67_inputs.yaml +12 -0
  389. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_68.yaml +18 -0
  390. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_69_inputs.yaml +12 -0
  391. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_7.yaml +22 -0
  392. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_70.yaml +21 -0
  393. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_72_input.yaml +13 -0
  394. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_73.yaml +21 -0
  395. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_74.yaml +13 -0
  396. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_75.yaml +20 -0
  397. tax_engine/jurisdictions/ca_ab/manifests/2025/ab428_line_8.yaml +21 -0
  398. tax_engine/jurisdictions/ca_ab/manifests/2025/manifest.yaml +39 -0
  399. tax_engine/jurisdictions/ca_ab/manifests/2025/return.yaml +157 -0
  400. tax_engine/jurisdictions/ca_ab/manifests/2025/salary.yaml +8 -0
  401. tax_engine/jurisdictions/ca_ab/manifests/2025/worksheet_ab428.yaml +10 -0
  402. tax_engine/jurisdictions/ca_ab/manifests/2025/worksheet_ab428_line_1.yaml +15 -0
  403. tax_engine/jurisdictions/ca_ab/manifests/2025/worksheet_ab428_line_2.yaml +15 -0
  404. tax_engine/jurisdictions/ca_ab/manifests/2025/worksheet_ab428_line_3.yaml +20 -0
  405. tax_engine/jurisdictions/ca_ab/manifests/2025/worksheet_ab428_line_5.yaml +17 -0
  406. tax_engine/jurisdictions/ca_ab/manifests/2025/worksheet_ab428_line_6.yaml +14 -0
  407. tax_engine/jurisdictions/ca_ab/manifests/2025/worksheet_ab428_line_7.yaml +16 -0
  408. tax_engine/jurisdictions/ca_ab/manifests/2025/worksheet_ab428_line_9.yaml +17 -0
  409. tax_engine/jurisdictions/ca_ab/parameters/basic_personal_amount/2025.yaml +12 -0
  410. tax_engine/jurisdictions/ca_ab/parameters/basic_personal_amount/2026.yaml +13 -0
  411. tax_engine/jurisdictions/ca_ab/parameters/brackets_lines_2_to_8/2025.yaml +24 -0
  412. tax_engine/jurisdictions/ca_ab/parameters/brackets_lines_2_to_8/2026.yaml +20 -0
  413. tax_engine/jurisdictions/ca_ab/parameters/brackets_lines_9_to_15/2025.yaml +11 -0
  414. tax_engine/jurisdictions/ca_ab/parameters/brackets_lines_9_to_15/2026.yaml +18 -0
  415. tax_engine/jurisdictions/ca_ab/parameters/cent_rounding/2025.yaml +12 -0
  416. tax_engine/jurisdictions/ca_ab/parameters/cent_rounding/2026.yaml +14 -0
  417. tax_engine/jurisdictions/ca_ab/parameters/credit_rate/2025.yaml +11 -0
  418. tax_engine/jurisdictions/ca_ab/parameters/credit_rate/2026.yaml +16 -0
  419. tax_engine/jurisdictions/ca_ab/parameters/cwb_base_amount/2025.yaml +11 -0
  420. tax_engine/jurisdictions/ca_ab/parameters/cwb_base_amount/2026.yaml +17 -0
  421. tax_engine/jurisdictions/ca_ab/parameters/cwb_maximum/2025.yaml +12 -0
  422. tax_engine/jurisdictions/ca_ab/parameters/cwb_maximum/2026.yaml +16 -0
  423. tax_engine/jurisdictions/ca_ab/parameters/cwb_rate/2025.yaml +12 -0
  424. tax_engine/jurisdictions/ca_ab/parameters/cwb_rate/2026.yaml +17 -0
  425. tax_engine/jurisdictions/ca_ab/parameters/cwb_reduction_threshold/2025.yaml +13 -0
  426. tax_engine/jurisdictions/ca_ab/parameters/cwb_reduction_threshold/2026.yaml +18 -0
  427. tax_engine/jurisdictions/ca_ab/parameters/exact_rounding/2025.yaml +11 -0
  428. tax_engine/jurisdictions/ca_ab/parameters/exact_rounding/2026.yaml +13 -0
  429. tax_engine/jurisdictions/ca_ab/parameters/marginal_rate_gate/2025.yaml +16 -0
  430. tax_engine/jurisdictions/ca_ab/parameters/marginal_rate_gate/2026.yaml +18 -0
  431. tax_engine/jurisdictions/ca_ab/parameters/minimum_tax_rate/2025.yaml +11 -0
  432. tax_engine/jurisdictions/ca_ab/parameters/minimum_tax_rate/2026.yaml +13 -0
  433. tax_engine/jurisdictions/ca_ab/parameters/rate_rounding/2025.yaml +12 -0
  434. tax_engine/jurisdictions/ca_ab/parameters/rate_rounding/2026.yaml +14 -0
  435. tax_engine/jurisdictions/ca_ab/parameters/supplemental_credit_base/2025.yaml +10 -0
  436. tax_engine/jurisdictions/ca_ab/parameters/supplemental_credit_base/2026.yaml +13 -0
  437. tax_engine/jurisdictions/ca_ab/parameters/supplemental_credit_rate/2025.yaml +10 -0
  438. tax_engine/jurisdictions/ca_ab/parameters/supplemental_credit_rate/2026.yaml +13 -0
  439. tax_engine/jurisdictions/ca_ab/trace/__init__.py +14 -0
  440. tax_engine/jurisdictions/ca_ab/trace/tax_on_taxable_income.py +31 -0
  441. tax_engine/jurisdictions/ca_ab/trace_english/__init__.py +11 -0
  442. tax_engine/jurisdictions/ca_ab/trace_english/tax_on_taxable_income.py +24 -0
  443. tax_engine/jurisdictions/ca_on/__init__.py +11 -0
  444. tax_engine/jurisdictions/ca_on/capabilities/__init__.py +7 -0
  445. tax_engine/jurisdictions/ca_on/capabilities/surtax_factor.py +61 -0
  446. tax_engine/jurisdictions/ca_on/catalog.py +484 -0
  447. tax_engine/jurisdictions/ca_on/manifests/2025/manifest.yaml +27 -0
  448. tax_engine/jurisdictions/ca_on/manifests/2025/on428.yaml +25 -0
  449. tax_engine/jurisdictions/ca_on/manifests/2025/on428_a.yaml +11 -0
  450. tax_engine/jurisdictions/ca_on/manifests/2025/on428_a_line_13.yaml +35 -0
  451. tax_engine/jurisdictions/ca_on/manifests/2025/on428_a_line_16.yaml +14 -0
  452. tax_engine/jurisdictions/ca_on/manifests/2025/on428_a_line_17.yaml +20 -0
  453. tax_engine/jurisdictions/ca_on/manifests/2025/on428_a_line_19.yaml +16 -0
  454. tax_engine/jurisdictions/ca_on/manifests/2025/on428_a_line_20.yaml +19 -0
  455. tax_engine/jurisdictions/ca_on/manifests/2025/on428_a_line_3.yaml +16 -0
  456. tax_engine/jurisdictions/ca_on/manifests/2025/on428_a_line_5.yaml +29 -0
  457. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_18.yaml +16 -0
  458. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_19.yaml +14 -0
  459. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_21.yaml +13 -0
  460. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_24.yaml +17 -0
  461. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_25.yaml +18 -0
  462. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_27_inputs.yaml +12 -0
  463. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_28.yaml +17 -0
  464. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_3.yaml +30 -0
  465. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_31.yaml +16 -0
  466. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_35.yaml +17 -0
  467. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_4.yaml +17 -0
  468. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_43_inputs.yaml +12 -0
  469. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_44.yaml +21 -0
  470. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_46.yaml +16 -0
  471. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_49_inputs.yaml +12 -0
  472. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_5.yaml +17 -0
  473. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_50.yaml +18 -0
  474. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_53.yaml +16 -0
  475. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_54_inputs.yaml +12 -0
  476. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_55.yaml +20 -0
  477. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_57_inputs.yaml +12 -0
  478. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_6.yaml +21 -0
  479. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_60_inputs.yaml +12 -0
  480. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_61.yaml +19 -0
  481. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_65.yaml +20 -0
  482. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_66.yaml +17 -0
  483. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_67.yaml +17 -0
  484. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_68.yaml +20 -0
  485. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_69.yaml +17 -0
  486. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_7.yaml +24 -0
  487. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_71.yaml +19 -0
  488. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_72_inputs.yaml +13 -0
  489. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_73.yaml +21 -0
  490. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_74.yaml +14 -0
  491. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_77.yaml +16 -0
  492. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_78.yaml +17 -0
  493. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_8.yaml +19 -0
  494. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_80.yaml +55 -0
  495. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_81.yaml +16 -0
  496. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_82_inputs.yaml +12 -0
  497. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_83.yaml +19 -0
  498. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_85.yaml +17 -0
  499. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_86.yaml +18 -0
  500. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_87.yaml +20 -0
  501. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_87_inputs.yaml +13 -0
  502. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_88.yaml +17 -0
  503. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_89.yaml +27 -0
  504. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_9.yaml +14 -0
  505. tax_engine/jurisdictions/ca_on/manifests/2025/on428_line_90.yaml +24 -0
  506. tax_engine/jurisdictions/ca_on/manifests/2025/return.yaml +222 -0
  507. tax_engine/jurisdictions/ca_on/manifests/2025/salary.yaml +8 -0
  508. tax_engine/jurisdictions/ca_on/parameters/basic_personal_amount/2025.yaml +13 -0
  509. tax_engine/jurisdictions/ca_on/parameters/basic_personal_amount/2026.yaml +11 -0
  510. tax_engine/jurisdictions/ca_on/parameters/brackets/2025.yaml +30 -0
  511. tax_engine/jurisdictions/ca_on/parameters/brackets/2026.yaml +20 -0
  512. tax_engine/jurisdictions/ca_on/parameters/cent_rounding/2025.yaml +16 -0
  513. tax_engine/jurisdictions/ca_on/parameters/cent_rounding/2026.yaml +18 -0
  514. tax_engine/jurisdictions/ca_on/parameters/credit_rate/2025.yaml +12 -0
  515. tax_engine/jurisdictions/ca_on/parameters/credit_rate/2026.yaml +11 -0
  516. tax_engine/jurisdictions/ca_on/parameters/exact_rounding/2025.yaml +10 -0
  517. tax_engine/jurisdictions/ca_on/parameters/exact_rounding/2026.yaml +12 -0
  518. tax_engine/jurisdictions/ca_on/parameters/farmers_food_donation_rate/2025.yaml +11 -0
  519. tax_engine/jurisdictions/ca_on/parameters/farmers_food_donation_rate/2026.yaml +13 -0
  520. tax_engine/jurisdictions/ca_on/parameters/health_premium_rows/2025.yaml +27 -0
  521. tax_engine/jurisdictions/ca_on/parameters/health_premium_rows/2026.yaml +24 -0
  522. tax_engine/jurisdictions/ca_on/parameters/lift_individual_income_threshold/2025.yaml +14 -0
  523. tax_engine/jurisdictions/ca_on/parameters/lift_individual_income_threshold/2026.yaml +19 -0
  524. tax_engine/jurisdictions/ca_on/parameters/lift_maximum/2025.yaml +14 -0
  525. tax_engine/jurisdictions/ca_on/parameters/lift_maximum/2026.yaml +19 -0
  526. tax_engine/jurisdictions/ca_on/parameters/lift_rate/2025.yaml +13 -0
  527. tax_engine/jurisdictions/ca_on/parameters/lift_rate/2026.yaml +14 -0
  528. tax_engine/jurisdictions/ca_on/parameters/lift_single_rate/2025.yaml +12 -0
  529. tax_engine/jurisdictions/ca_on/parameters/lift_single_rate/2026.yaml +14 -0
  530. tax_engine/jurisdictions/ca_on/parameters/marginal_rate_gate/2025.yaml +16 -0
  531. tax_engine/jurisdictions/ca_on/parameters/marginal_rate_gate/2026.yaml +18 -0
  532. tax_engine/jurisdictions/ca_on/parameters/on428_line_80_conditions/2025.yaml +19 -0
  533. tax_engine/jurisdictions/ca_on/parameters/on428_line_80_conditions/2026.yaml +21 -0
  534. tax_engine/jurisdictions/ca_on/parameters/rate_rounding/2025.yaml +12 -0
  535. tax_engine/jurisdictions/ca_on/parameters/rate_rounding/2026.yaml +14 -0
  536. tax_engine/jurisdictions/ca_on/parameters/surtax_line_66/2025.yaml +14 -0
  537. tax_engine/jurisdictions/ca_on/parameters/surtax_line_66/2026.yaml +12 -0
  538. tax_engine/jurisdictions/ca_on/parameters/surtax_line_67/2025.yaml +14 -0
  539. tax_engine/jurisdictions/ca_on/parameters/surtax_line_67/2026.yaml +12 -0
  540. tax_engine/jurisdictions/ca_on/parameters/tax_reduction_basic/2025.yaml +13 -0
  541. tax_engine/jurisdictions/ca_on/parameters/tax_reduction_basic/2026.yaml +14 -0
  542. tax_engine/jurisdictions/ca_on/parameters/tax_reduction_multiplier/2025.yaml +13 -0
  543. tax_engine/jurisdictions/ca_on/parameters/tax_reduction_multiplier/2026.yaml +14 -0
  544. tax_engine/jurisdictions/ca_on/trace/__init__.py +14 -0
  545. tax_engine/jurisdictions/ca_on/trace/surtax_factor.py +37 -0
  546. tax_engine/jurisdictions/ca_on/trace_english/__init__.py +11 -0
  547. tax_engine/jurisdictions/ca_on/trace_english/surtax_factor.py +43 -0
  548. tax_engine/jurisdictions/core/__init__.py +14 -0
  549. tax_engine/jurisdictions/core/capabilities/__init__.py +7 -0
  550. tax_engine/jurisdictions/core/capabilities/amount_by_band.py +54 -0
  551. tax_engine/jurisdictions/core/capabilities/amount_by_band_rate.py +49 -0
  552. tax_engine/jurisdictions/core/capabilities/apply_fraction.py +48 -0
  553. tax_engine/jurisdictions/core/capabilities/apply_rate.py +42 -0
  554. tax_engine/jurisdictions/core/capabilities/apply_ratio.py +91 -0
  555. tax_engine/jurisdictions/core/capabilities/at_most.py +51 -0
  556. tax_engine/jurisdictions/core/capabilities/bracket_column_figure.py +101 -0
  557. tax_engine/jurisdictions/core/capabilities/capped_amount.py +45 -0
  558. tax_engine/jurisdictions/core/capabilities/choose_by_count.py +69 -0
  559. tax_engine/jurisdictions/core/capabilities/credit_amount.py +40 -0
  560. tax_engine/jurisdictions/core/capabilities/divide.py +67 -0
  561. tax_engine/jurisdictions/core/capabilities/first_record_count.py +65 -0
  562. tax_engine/jurisdictions/core/capabilities/greater_of.py +47 -0
  563. tax_engine/jurisdictions/core/capabilities/lesser_of.py +48 -0
  564. tax_engine/jurisdictions/core/capabilities/multiple_over.py +62 -0
  565. tax_engine/jurisdictions/core/capabilities/multiply_by_rate.py +68 -0
  566. tax_engine/jurisdictions/core/capabilities/per_unit_amount.py +50 -0
  567. tax_engine/jurisdictions/core/capabilities/progressive_tax.py +49 -0
  568. tax_engine/jurisdictions/core/capabilities/record_positive_total.py +60 -0
  569. tax_engine/jurisdictions/core/capabilities/record_total.py +61 -0
  570. tax_engine/jurisdictions/core/capabilities/subtract.py +64 -0
  571. tax_engine/jurisdictions/core/capabilities/subtract_not_below_zero.py +66 -0
  572. tax_engine/jurisdictions/core/capabilities/sum.py +54 -0
  573. tax_engine/jurisdictions/core/capabilities/sum_not_below_zero.py +56 -0
  574. tax_engine/jurisdictions/core/capabilities/tiered_surcharge.py +56 -0
  575. tax_engine/jurisdictions/core/capabilities/times_count.py +65 -0
  576. tax_engine/jurisdictions/core/catalog.py +6 -0
  577. tax_engine/jurisdictions/core/parameter_parsers/__init__.py +5 -0
  578. tax_engine/jurisdictions/core/parameter_parsers/amount.py +19 -0
  579. tax_engine/jurisdictions/core/parameter_parsers/amount_by_band.py +50 -0
  580. tax_engine/jurisdictions/core/parameter_parsers/brackets.py +52 -0
  581. tax_engine/jurisdictions/core/parameter_parsers/class_rates.py +106 -0
  582. tax_engine/jurisdictions/core/parameter_parsers/conditions.py +79 -0
  583. tax_engine/jurisdictions/core/parameter_parsers/credit.py +19 -0
  584. tax_engine/jurisdictions/core/parameter_parsers/factor.py +19 -0
  585. tax_engine/jurisdictions/core/parameter_parsers/fraction.py +23 -0
  586. tax_engine/jurisdictions/core/parameter_parsers/rate.py +19 -0
  587. tax_engine/jurisdictions/core/parameter_parsers/rate_table.py +40 -0
  588. tax_engine/jurisdictions/core/parameter_parsers/rounding_only.py +19 -0
  589. tax_engine/jurisdictions/core/parameter_parsers/surcharge_tiers.py +42 -0
  590. tax_engine/jurisdictions/core/parameter_parsers/threshold_rate.py +23 -0
  591. tax_engine/jurisdictions/core/trace_english/__init__.py +7 -0
  592. tax_engine/jurisdictions/core/trace_english/units.py +13 -0
  593. tax_engine/jurisdictions/core/units.py +10 -0
  594. tax_engine/registrations.py +67 -0
  595. tax_engine-0.1.0.dist-info/METADATA +144 -0
  596. tax_engine-0.1.0.dist-info/RECORD +599 -0
  597. tax_engine-0.1.0.dist-info/WHEEL +5 -0
  598. tax_engine-0.1.0.dist-info/licenses/LICENSE +202 -0
  599. tax_engine-0.1.0.dist-info/top_level.txt +1 -0
tax_engine/__init__.py ADDED
@@ -0,0 +1,6 @@
1
+ """Tax computation engine and jurisdiction implementations."""
2
+
3
+ from tax_engine.application.services.tax_computation import TaxComputationService
4
+ from tax_engine.factory import build_tax_computation
5
+
6
+ __all__ = ["TaxComputationService", "build_tax_computation"]
@@ -0,0 +1 @@
1
+ """Adapters for loading engine data and rendering computation traces."""
@@ -0,0 +1 @@
1
+ """Inbound adapters for engine-facing interfaces."""
@@ -0,0 +1,45 @@
1
+ """English rendering of the structured trace: one readable sentence per trace line.
2
+
3
+ A new module of core trace lines adds its renderer module here; a jurisdiction renders its own lines
4
+ in its `trace_english` package.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from tax_engine.adapters.inbound.trace_english import (
10
+ arithmetic,
11
+ blank,
12
+ choices,
13
+ figures,
14
+ forms,
15
+ line_renderer,
16
+ names,
17
+ rate_tables,
18
+ record_lists,
19
+ registry,
20
+ renderer,
21
+ unit_text,
22
+ )
23
+ from tax_engine.adapters.inbound.trace_english.line_renderer import LineRenderer
24
+ from tax_engine.adapters.inbound.trace_english.names import EnglishNames, FigureNames, Labelled
25
+ from tax_engine.adapters.inbound.trace_english.renderer import EnglishTraceRenderer
26
+
27
+ __all__ = [
28
+ "EnglishNames",
29
+ "EnglishTraceRenderer",
30
+ "FigureNames",
31
+ "Labelled",
32
+ "LineRenderer",
33
+ "arithmetic",
34
+ "blank",
35
+ "choices",
36
+ "figures",
37
+ "forms",
38
+ "line_renderer",
39
+ "names",
40
+ "rate_tables",
41
+ "record_lists",
42
+ "registry",
43
+ "renderer",
44
+ "unit_text",
45
+ ]
@@ -0,0 +1,619 @@
1
+ """English text for the trace lines of `tax_engine.domain.trace.arithmetic`: one renderer class
2
+ per line class, each registered with `@english_renderer`.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from tax_engine.adapters.inbound.trace_english.figures import EnglishFigures
8
+ from tax_engine.adapters.inbound.trace_english.names import EnglishNames
9
+ from tax_engine.adapters.inbound.trace_english.registry import english_renderer
10
+ from tax_engine.domain.trace.arithmetic import (
11
+ AmountOrDividedByRateLine,
12
+ AmountWhenMoreLine,
13
+ AtMostLine,
14
+ CappedAmountLine,
15
+ ClaimAtMostLine,
16
+ CountAtLeastLine,
17
+ CountAtMostLine,
18
+ CountNotRefusedLine,
19
+ CountWithoutRecordsLine,
20
+ CreditAmountLine,
21
+ DividedByRateLine,
22
+ FractionAppliedLine,
23
+ GreaterOfLine,
24
+ LesserOfLine,
25
+ LesserOfWhenPositiveLine,
26
+ LesserOfWithMaximumLine,
27
+ MoreThanPerUnitLine,
28
+ MultipleOverLine,
29
+ MultipliedByRateLine,
30
+ PercentageAppliedLine,
31
+ PerUnitAmountLine,
32
+ PositivePartOfNegationLine,
33
+ QuotientLine,
34
+ RateAppliedLine,
35
+ RatioAppliedLine,
36
+ RatioTruncatedLine,
37
+ RoundedTotalLine,
38
+ SignChosenDifferenceLine,
39
+ SubtractedLine,
40
+ SubtractedNotBelowZeroLine,
41
+ SumLine,
42
+ SumNotBelowZeroLine,
43
+ ThresholdGateLine,
44
+ TimesCountLine,
45
+ YesOrNoCountLine,
46
+ )
47
+
48
+
49
+ @english_renderer
50
+ class RoundedTotalRenderer:
51
+ """English text for RoundedTotalLine."""
52
+
53
+ line_class = RoundedTotalLine
54
+
55
+ def render(self, line: RoundedTotalLine, names: EnglishNames) -> str:
56
+ """The English sentence for `line`."""
57
+ return (
58
+ f"Based on {names.figure(line.base, line.base_amount)} gives "
59
+ f"{names.shown(line.label, line.amount)} ({EnglishFigures.rounding(line.rounding)})"
60
+ )
61
+
62
+
63
+ @english_renderer
64
+ class SumRenderer:
65
+ """English text for SumLine."""
66
+
67
+ line_class = SumLine
68
+
69
+ def render(self, line: SumLine, names: EnglishNames) -> str:
70
+ """The English sentence for `line`."""
71
+ terms = " plus ".join(names.figure(kind, amount) for kind, amount in line.parts)
72
+ if not line.parts:
73
+ return f"Nothing to add, so {names.shown(line.label, line.total)}"
74
+ return (
75
+ f"{terms} gives {names.shown(line.label, line.total)} "
76
+ f"({EnglishFigures.rounding(line.rounding)})"
77
+ )
78
+
79
+
80
+ @english_renderer
81
+ class SumNotBelowZeroRenderer:
82
+ """English text for SumNotBelowZeroLine."""
83
+
84
+ line_class = SumNotBelowZeroLine
85
+
86
+ def render(self, line: SumNotBelowZeroLine, names: EnglishNames) -> str:
87
+ """The English sentence for `line`."""
88
+ terms = " plus ".join(names.figure(kind, amount) for kind, amount in line.parts)
89
+ if not line.parts:
90
+ return f"Nothing to add, not below 0, so {names.shown(line.label, line.total)}"
91
+ return (
92
+ f"{terms}, not below 0, gives {names.shown(line.label, line.total)} "
93
+ f"({EnglishFigures.rounding(line.rounding)})"
94
+ )
95
+
96
+
97
+ @english_renderer
98
+ class RateAppliedRenderer:
99
+ """English text for RateAppliedLine."""
100
+
101
+ line_class = RateAppliedLine
102
+
103
+ def render(self, line: RateAppliedLine, names: EnglishNames) -> str:
104
+ """The English sentence for `line`."""
105
+ return (
106
+ f"{EnglishFigures.percent(line.rate.value)}% of "
107
+ f"{names.figure(line.base, line.base_amount)} gives "
108
+ f"{names.shown(line.label, line.amount)} ({EnglishFigures.rounding(line.rounding)})"
109
+ )
110
+
111
+
112
+ @english_renderer
113
+ class DividedByRateRenderer:
114
+ """English text for DividedByRateLine."""
115
+
116
+ line_class = DividedByRateLine
117
+
118
+ def render(self, line: DividedByRateLine, names: EnglishNames) -> str:
119
+ """The English sentence for `line`."""
120
+ return (
121
+ f"{names.figure(line.dividend, line.dividend_amount)} divided by "
122
+ f"{EnglishFigures.percent(line.rate.value)}% gives "
123
+ f"{names.shown(line.label, line.result)} ({EnglishFigures.rounding(line.rounding)})"
124
+ )
125
+
126
+
127
+ @english_renderer
128
+ class SignChosenDifferenceRenderer:
129
+ """English text for SignChosenDifferenceLine."""
130
+
131
+ line_class = SignChosenDifferenceLine
132
+
133
+ def render(self, line: SignChosenDifferenceLine, names: EnglishNames) -> str:
134
+ """The English sentence for `line`."""
135
+ if line.sign_amount >= 0:
136
+ return (
137
+ f"{names.figure(line.difference, line.difference_amount)}, because "
138
+ f"{names.figure(line.sign, line.sign_amount)} is not negative, "
139
+ f"gives {names.shown(line.label, line.result)}"
140
+ )
141
+ return (
142
+ f"{names.figure(line.sign, line.sign_amount)} is negative, so the lesser of "
143
+ f"{names.figure(line.reference, line.reference_amount)} and the size of "
144
+ f"{names.figure(line.difference, line.difference_amount)}, as a negative, "
145
+ f"gives {names.shown(line.label, line.result)}"
146
+ )
147
+
148
+
149
+ @english_renderer
150
+ class SubtractedRenderer:
151
+ """English text for SubtractedLine."""
152
+
153
+ line_class = SubtractedLine
154
+
155
+ def render(self, line: SubtractedLine, names: EnglishNames) -> str:
156
+ """The English sentence for `line`."""
157
+ return (
158
+ f"{names.figure(line.minuend, line.minuend_amount)} less "
159
+ f"{names.figure(line.subtrahend, line.subtrahend_amount)} gives "
160
+ f"{names.shown(line.label, line.result)} ({EnglishFigures.rounding(line.rounding)})"
161
+ )
162
+
163
+
164
+ @english_renderer
165
+ class SubtractedNotBelowZeroRenderer:
166
+ """English text for SubtractedNotBelowZeroLine."""
167
+
168
+ line_class = SubtractedNotBelowZeroLine
169
+
170
+ def render(self, line: SubtractedNotBelowZeroLine, names: EnglishNames) -> str:
171
+ """The English sentence for `line`."""
172
+ return (
173
+ f"{names.figure(line.minuend, line.minuend_amount)} less "
174
+ f"{names.figure(line.subtrahend, line.subtrahend_amount)}, not below 0, gives "
175
+ f"{names.shown(line.label, line.result)} ({EnglishFigures.rounding(line.rounding)})"
176
+ )
177
+
178
+
179
+ @english_renderer
180
+ class CreditAmountRenderer:
181
+ """English text for CreditAmountLine."""
182
+
183
+ line_class = CreditAmountLine
184
+
185
+ def render(self, line: CreditAmountLine, names: EnglishNames) -> str:
186
+ """The English sentence for `line`."""
187
+ return (
188
+ f"Credit amount of {EnglishFigures.money(line.basis.amount)} "
189
+ f"({EnglishFigures.rounding(line.rounding)})"
190
+ )
191
+
192
+
193
+ @english_renderer
194
+ class CappedAmountRenderer:
195
+ """English text for CappedAmountLine."""
196
+
197
+ line_class = CappedAmountLine
198
+
199
+ def render(self, line: CappedAmountLine, names: EnglishNames) -> str:
200
+ """The English sentence for `line`."""
201
+ return (
202
+ f"Lesser of {names.figure(line.base, line.base_amount)} and "
203
+ f"{names.parameter(line.cap)} gives "
204
+ f"{names.shown(line.label, line.amount)} ({EnglishFigures.rounding(line.rounding)})"
205
+ )
206
+
207
+
208
+ @english_renderer
209
+ class LesserOfRenderer:
210
+ """English text for LesserOfLine."""
211
+
212
+ line_class = LesserOfLine
213
+
214
+ def render(self, line: LesserOfLine, names: EnglishNames) -> str:
215
+ """The English sentence for `line`."""
216
+ terms = EnglishFigures.listing([names.figure(kind, amount) for kind, amount in line.parts])
217
+ word = "Lesser" if len(line.parts) == 2 else "Least"
218
+ if len(line.parts) == 1:
219
+ return f"{terms} gives {names.shown(line.label, line.result)}"
220
+ return f"{word} of {terms} gives {names.shown(line.label, line.result)}"
221
+
222
+
223
+ @english_renderer
224
+ class LesserOfWithMaximumRenderer:
225
+ """English text for LesserOfWithMaximumLine."""
226
+
227
+ line_class = LesserOfWithMaximumLine
228
+
229
+ def render(self, line: LesserOfWithMaximumLine, names: EnglishNames) -> str:
230
+ """The English sentence for `line`."""
231
+ terms = EnglishFigures.listing(
232
+ [
233
+ *(names.figure(kind, amount) for kind, amount in line.parts),
234
+ names.parameter(line.maximum),
235
+ ]
236
+ )
237
+ word = "Lesser" if len(line.parts) == 1 else "Least"
238
+ return (
239
+ f"{word} of {terms} gives "
240
+ f"{names.shown(line.label, line.result)} ({EnglishFigures.rounding(line.rounding)})"
241
+ )
242
+
243
+
244
+ @english_renderer
245
+ class GreaterOfRenderer:
246
+ """English text for GreaterOfLine."""
247
+
248
+ line_class = GreaterOfLine
249
+
250
+ def render(self, line: GreaterOfLine, names: EnglishNames) -> str:
251
+ """The English sentence for `line`."""
252
+ terms = EnglishFigures.listing([names.figure(kind, amount) for kind, amount in line.parts])
253
+ word = "Greater" if len(line.parts) == 2 else "Greatest"
254
+ if len(line.parts) == 1:
255
+ return f"{terms} gives {names.shown(line.label, line.result)}"
256
+ return f"{word} of {terms} gives {names.shown(line.label, line.result)}"
257
+
258
+
259
+ @english_renderer
260
+ class PerUnitAmountRenderer:
261
+ """English text for PerUnitAmountLine."""
262
+
263
+ line_class = PerUnitAmountLine
264
+
265
+ def render(self, line: PerUnitAmountLine, names: EnglishNames) -> str:
266
+ """The English sentence for `line`."""
267
+ return (
268
+ f"{EnglishFigures.money(line.per_unit.value)} for each of "
269
+ f"{names.figure(line.count_kind, line.count)} gives "
270
+ f"{names.shown(line.label, line.result)} ({EnglishFigures.rounding(line.rounding)})"
271
+ )
272
+
273
+
274
+ @english_renderer
275
+ class MultipleOverRenderer:
276
+ """English text for MultipleOverLine."""
277
+
278
+ line_class = MultipleOverLine
279
+
280
+ def render(self, line: MultipleOverLine, names: EnglishNames) -> str:
281
+ """The English sentence for `line`."""
282
+ return (
283
+ f"{format(line.factor.value.normalize(), 'f')} × "
284
+ f"{names.figure(line.base, line.base_amount)} less "
285
+ f"{names.figure(line.less, line.less_amount)}, not below 0, gives "
286
+ f"{names.shown(line.label, line.amount)} ({EnglishFigures.rounding(line.rounding)})"
287
+ )
288
+
289
+
290
+ @english_renderer
291
+ class AtMostRenderer:
292
+ """English text for AtMostLine."""
293
+
294
+ line_class = AtMostLine
295
+
296
+ def render(self, line: AtMostLine, names: EnglishNames) -> str:
297
+ """The English sentence for `line`."""
298
+ return (
299
+ f"{names.figure(line.amount_kind, line.amount_value)}, at most "
300
+ f"{names.figure(line.bound, line.bound_value)}"
301
+ )
302
+
303
+
304
+ @english_renderer
305
+ class ClaimAtMostRenderer:
306
+ """English text for ClaimAtMostLine."""
307
+
308
+ line_class = ClaimAtMostLine
309
+
310
+ def render(self, line: ClaimAtMostLine, names: EnglishNames) -> str:
311
+ """The English sentence for `line`."""
312
+ if line.maximum_value < 0:
313
+ return (
314
+ f"{names.figure(line.claim_kind, line.claim_value)}, allowed because "
315
+ f"{names.figure(line.maximum_kind, line.maximum_value)} is negative"
316
+ )
317
+ return (
318
+ f"{names.figure(line.claim_kind, line.claim_value)}, at most "
319
+ f"{names.figure(line.maximum_kind, line.maximum_value)}"
320
+ )
321
+
322
+
323
+ @english_renderer
324
+ class FractionAppliedRenderer:
325
+ """English text for FractionAppliedLine."""
326
+
327
+ line_class = FractionAppliedLine
328
+
329
+ def render(self, line: FractionAppliedLine, names: EnglishNames) -> str:
330
+ """The English sentence for `line`."""
331
+ fraction = line.fraction
332
+ share = (
333
+ f"{fraction.numerator} times"
334
+ if fraction.denominator == 1
335
+ else f"{fraction.numerator}/{fraction.denominator} of"
336
+ )
337
+ return (
338
+ f"{share} {names.figure(line.base, line.base_amount)} gives "
339
+ f"{names.shown(line.label, line.amount)} ({EnglishFigures.rounding(line.rounding)})"
340
+ )
341
+
342
+
343
+ @english_renderer
344
+ class PercentageAppliedRenderer:
345
+ """English text for PercentageAppliedLine."""
346
+
347
+ line_class = PercentageAppliedLine
348
+
349
+ def render(self, line: PercentageAppliedLine, names: EnglishNames) -> str:
350
+ """The English sentence for `line`."""
351
+ return (
352
+ f"{names.of(line.percentage_kind)} "
353
+ f"({format(line.percentage_value.normalize(), 'f')}%) of "
354
+ f"{names.figure(line.amount_kind, line.amount_value)} gives "
355
+ f"{names.shown(line.label, line.result)} ({EnglishFigures.rounding(line.rounding)})"
356
+ )
357
+
358
+
359
+ @english_renderer
360
+ class MultipliedByRateRenderer:
361
+ """English text for MultipliedByRateLine."""
362
+
363
+ line_class = MultipliedByRateLine
364
+
365
+ def render(self, line: MultipliedByRateLine, names: EnglishNames) -> str:
366
+ """The English sentence for `line`."""
367
+ return (
368
+ f"{names.of(line.rate_kind)} ({EnglishFigures.percent(line.rate_value)}%) of "
369
+ f"{names.figure(line.base_kind, line.base_value)} gives "
370
+ f"{names.shown(line.label, line.result)} ({EnglishFigures.rounding(line.rounding)})"
371
+ )
372
+
373
+
374
+ @english_renderer
375
+ class RatioAppliedRenderer:
376
+ """English text for RatioAppliedLine."""
377
+
378
+ line_class = RatioAppliedLine
379
+
380
+ def render(self, line: RatioAppliedLine, names: EnglishNames) -> str:
381
+ """The English sentence for `line`."""
382
+ return (
383
+ f"{names.figure(line.amount_kind, line.amount_value)} × "
384
+ f"{names.figure(line.numerator_kind, line.numerator_value)} / "
385
+ f"{names.figure(line.denominator_kind, line.denominator_value)} gives "
386
+ f"{names.shown(line.label, line.amount)} ({EnglishFigures.rounding(line.rounding)})"
387
+ )
388
+
389
+
390
+ @english_renderer
391
+ class TimesCountRenderer:
392
+ """English text for TimesCountLine."""
393
+
394
+ line_class = TimesCountLine
395
+
396
+ def render(self, line: TimesCountLine, names: EnglishNames) -> str:
397
+ """The English sentence for `line`."""
398
+ return (
399
+ f"{names.figure(line.amount_kind, line.amount_value)} for each of "
400
+ f"{names.figure(line.count_kind, line.count)} gives "
401
+ f"{names.shown(line.label, line.result)} ({EnglishFigures.rounding(line.rounding)})"
402
+ )
403
+
404
+
405
+ @english_renderer
406
+ class QuotientRenderer:
407
+ """English text for QuotientLine."""
408
+
409
+ line_class = QuotientLine
410
+
411
+ def render(self, line: QuotientLine, names: EnglishNames) -> str:
412
+ """The English sentence for `line`."""
413
+ dividend = names.figure(line.dividend, line.dividend_amount)
414
+ divisor = names.figure(line.divisor, line.divisor_amount)
415
+ result = names.shown(line.label, line.result)
416
+ if line.divisor_amount == 0:
417
+ return f"{dividend} divided by {divisor}, which is zero, gives {result}"
418
+ return (
419
+ f"{dividend} divided by {divisor} gives {result} "
420
+ f"({EnglishFigures.rounding(line.rounding)})"
421
+ )
422
+
423
+
424
+ @english_renderer
425
+ class ThresholdGateRenderer:
426
+ """English text for ThresholdGateLine."""
427
+
428
+ line_class = ThresholdGateLine
429
+
430
+ def render(self, line: ThresholdGateLine, names: EnglishNames) -> str:
431
+ """The English sentence for `line`."""
432
+ amount = names.figure(line.amount_kind, line.amount_value)
433
+ gate = names.figure(line.gate_kind, line.gate_value)
434
+ threshold = EnglishFigures.money(line.threshold.value)
435
+ rounded = EnglishFigures.rounding(line.rounding)
436
+ if line.gate_value >= line.threshold.value:
437
+ return (
438
+ f"{amount}, because {gate} is at least {threshold}, gives "
439
+ f"{names.shown(line.label, line.result)} ({rounded})"
440
+ )
441
+ return (
442
+ f"{names.shown(line.label, line.result)}, because {gate} is below {threshold}, "
443
+ f"so {amount} does not apply"
444
+ )
445
+
446
+
447
+ @english_renderer
448
+ class AmountOrDividedByRateRenderer:
449
+ """English text for AmountOrDividedByRateLine."""
450
+
451
+ line_class = AmountOrDividedByRateLine
452
+
453
+ def render(self, line: AmountOrDividedByRateLine, names: EnglishNames) -> str:
454
+ """The English sentence for `line`."""
455
+ amount = names.figure(line.amount_kind, line.amount_value)
456
+ rounded = EnglishFigures.rounding(line.rounding)
457
+ limit = EnglishFigures.money(line.limit.threshold)
458
+ if line.amount_value <= line.limit.threshold:
459
+ return (
460
+ f"{amount} is {limit} or less, so it stands as "
461
+ f"{names.shown(line.label, line.result)} ({rounded})"
462
+ )
463
+ return (
464
+ f"{amount} is over {limit}, so "
465
+ f"{names.figure(line.dividend_kind, line.dividend_value)} divided by "
466
+ f"{EnglishFigures.percent(line.limit.rate.value)}% gives "
467
+ f"{names.shown(line.label, line.result)} ({rounded})"
468
+ )
469
+
470
+
471
+ @english_renderer
472
+ class CountAtLeastRenderer:
473
+ """English text for CountAtLeastLine."""
474
+
475
+ line_class = CountAtLeastLine
476
+
477
+ def render(self, line: CountAtLeastLine, names: EnglishNames) -> str:
478
+ """The English sentence for `line`."""
479
+ return (
480
+ f"{names.figure(line.count_kind, line.count)}, at least "
481
+ f"{names.figure(line.minimum_kind, line.minimum)}"
482
+ )
483
+
484
+
485
+ @english_renderer
486
+ class MoreThanPerUnitRenderer:
487
+ """English text for MoreThanPerUnitLine."""
488
+
489
+ line_class = MoreThanPerUnitLine
490
+
491
+ def render(self, line: MoreThanPerUnitLine, names: EnglishNames) -> str:
492
+ """The English sentence for `line`."""
493
+ if line.count == 0:
494
+ return (
495
+ f"{names.figure(line.total_kind, line.total)}, with no {names.of(line.count_kind)}"
496
+ )
497
+ return (
498
+ f"{names.figure(line.total_kind, line.total)}, more than "
499
+ f"{EnglishFigures.money(line.minimum_total)} "
500
+ f"({EnglishFigures.money(line.per_unit.value)} for each of "
501
+ f"{names.figure(line.count_kind, line.count)}, "
502
+ f"{EnglishFigures.rounding(line.rounding)})"
503
+ )
504
+
505
+
506
+ @english_renderer
507
+ class CountAtMostRenderer:
508
+ """English text for CountAtMostLine."""
509
+
510
+ line_class = CountAtMostLine
511
+
512
+ def render(self, line: CountAtMostLine, names: EnglishNames) -> str:
513
+ """The English sentence for `line`."""
514
+ return (
515
+ f"{names.figure(line.count_kind, line.count)}, at most "
516
+ f"{names.figure(line.maximum_kind, line.maximum)}"
517
+ )
518
+
519
+
520
+ @english_renderer
521
+ class YesOrNoCountRenderer:
522
+ """English text for YesOrNoCountLine."""
523
+
524
+ line_class = YesOrNoCountLine
525
+
526
+ def render(self, line: YesOrNoCountLine, names: EnglishNames) -> str:
527
+ """The English sentence for `line`."""
528
+ return f"{names.figure(line.count_kind, line.count)}, a yes or no answer of 0 or 1"
529
+
530
+
531
+ @english_renderer
532
+ class CountWithoutRecordsRenderer:
533
+ """English text for CountWithoutRecordsLine."""
534
+
535
+ line_class = CountWithoutRecordsLine
536
+
537
+ def render(self, line: CountWithoutRecordsLine, names: EnglishNames) -> str:
538
+ """The English sentence for `line`."""
539
+ head = f"{names.figure(line.count_kind, line.count)}, "
540
+ if line.record_count == 0:
541
+ return f"{head}with no {names.of(line.records_kind)} (0 records)"
542
+ noun = "record" if line.record_count == 1 else "records"
543
+ return f"{head}with {line.record_count} {noun} of {names.of(line.records_kind)}"
544
+
545
+
546
+ @english_renderer
547
+ class CountNotRefusedRenderer:
548
+ """English text for CountNotRefusedLine."""
549
+
550
+ line_class = CountNotRefusedLine
551
+
552
+ def render(self, line: CountNotRefusedLine, names: EnglishNames) -> str:
553
+ """The English sentence for `line`."""
554
+ return f"{names.figure(line.count_kind, line.count)}, not refused by the listed conditions"
555
+
556
+
557
+ @english_renderer
558
+ class RatioTruncatedRenderer:
559
+ """English text for RatioTruncatedLine."""
560
+
561
+ line_class = RatioTruncatedLine
562
+
563
+ def render(self, line: RatioTruncatedLine, names: EnglishNames) -> str:
564
+ """The English sentence for `line`."""
565
+ cap = ", capped at 1," if line.cap_at_one else ""
566
+ return (
567
+ f"{names.figure(line.dividend, line.dividend_amount)} divided by "
568
+ f"{names.figure(line.divisor, line.divisor_amount)}{cap} gives "
569
+ f"{names.shown(line.label, line.result)} ({EnglishFigures.rounding(line.rounding)})"
570
+ )
571
+
572
+
573
+ @english_renderer
574
+ class PositivePartOfNegationRenderer:
575
+ """English text for PositivePartOfNegationLine."""
576
+
577
+ line_class = PositivePartOfNegationLine
578
+
579
+ def render(self, line: PositivePartOfNegationLine, names: EnglishNames) -> str:
580
+ """The English sentence for `line`."""
581
+ return (
582
+ f"Negation of {names.figure(line.amount_kind, line.amount_value)}, not below 0, "
583
+ f"gives {names.shown(line.label, line.result)}"
584
+ )
585
+
586
+
587
+ @english_renderer
588
+ class LesserOfWhenPositiveRenderer:
589
+ """English text for LesserOfWhenPositiveLine."""
590
+
591
+ line_class = LesserOfWhenPositiveLine
592
+
593
+ def render(self, line: LesserOfWhenPositiveLine, names: EnglishNames) -> str:
594
+ """The English sentence for `line`."""
595
+ terms = EnglishFigures.listing([names.figure(kind, amount) for kind, amount in line.parts])
596
+ word = "Lesser" if len(line.parts) == 2 else "Least"
597
+ lesser = f"{word} of {terms}" if len(line.parts) > 1 else terms
598
+ brackets = ", shown in brackets" if line.bracket else ""
599
+ gate = "" if line.all_positive else ", not all positive"
600
+ separator = "," if brackets or gate else ""
601
+ return f"{lesser}{brackets}{gate}{separator} gives {names.shown(line.label, line.result)}"
602
+
603
+
604
+ @english_renderer
605
+ class AmountWhenMoreRenderer:
606
+ """English text for AmountWhenMoreLine."""
607
+
608
+ line_class = AmountWhenMoreLine
609
+
610
+ def render(self, line: AmountWhenMoreLine, names: EnglishNames) -> str:
611
+ """The English sentence for `line`."""
612
+ more = names.figure(line.more_kind, line.more_value)
613
+ than = names.figure(line.than_kind, line.than_value)
614
+ if line.more_value > line.than_value:
615
+ return (
616
+ f"{names.figure(line.amount_kind, line.amount_value)}, because {more} is more "
617
+ f"than {than}, gives {names.shown(line.label, line.result)}"
618
+ )
619
+ return f"{names.shown(line.label, line.result)}, because {more} is not more than {than}"