taxcalc 4.6.0__tar.gz → 4.6.1__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 (242) hide show
  1. {taxcalc-4.6.0/taxcalc.egg-info → taxcalc-4.6.1}/PKG-INFO +1 -1
  2. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/about/releases.md +23 -0
  3. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/cli.md +43 -12
  4. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/index.md +8 -14
  5. {taxcalc-4.6.0 → taxcalc-4.6.1}/setup.py +1 -1
  6. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/__init__.py +1 -1
  7. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/calculator.py +3 -3
  8. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/cli/tc.py +80 -30
  9. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/data.py +2 -2
  10. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/parameters.py +0 -5
  11. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/policy_current_law.json +6 -2
  12. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/taxcalcio.py +91 -53
  13. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_calculator.py +1 -1
  14. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_reforms.py +7 -7
  15. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_taxcalcio.py +9 -30
  16. {taxcalc-4.6.0 → taxcalc-4.6.1/taxcalc.egg-info}/PKG-INFO +1 -1
  17. {taxcalc-4.6.0 → taxcalc-4.6.1}/.coveragerc +0 -0
  18. {taxcalc-4.6.0 → taxcalc-4.6.1}/.github/FUNDING.yml +0 -0
  19. {taxcalc-4.6.0 → taxcalc-4.6.1}/.github/workflows/build_and_test.yml +0 -0
  20. {taxcalc-4.6.0 → taxcalc-4.6.1}/.github/workflows/check_jupyterbook.yml +0 -0
  21. {taxcalc-4.6.0 → taxcalc-4.6.1}/.github/workflows/deploy_jupyterbook.yml +0 -0
  22. {taxcalc-4.6.0 → taxcalc-4.6.1}/.github/workflows/deploy_parameters_docs.yml +0 -0
  23. {taxcalc-4.6.0 → taxcalc-4.6.1}/.gitignore +0 -0
  24. {taxcalc-4.6.0 → taxcalc-4.6.1}/LICENSE +0 -0
  25. {taxcalc-4.6.0 → taxcalc-4.6.1}/MANIFEST.in +0 -0
  26. {taxcalc-4.6.0 → taxcalc-4.6.1}/Makefile +0 -0
  27. {taxcalc-4.6.0 → taxcalc-4.6.1}/PSL_catalog.json +0 -0
  28. {taxcalc-4.6.0 → taxcalc-4.6.1}/README.md +0 -0
  29. {taxcalc-4.6.0 → taxcalc-4.6.1}/codecov.yml +0 -0
  30. {taxcalc-4.6.0 → taxcalc-4.6.1}/conda.recipe/bld.bat +0 -0
  31. {taxcalc-4.6.0 → taxcalc-4.6.1}/conda.recipe/build.sh +0 -0
  32. {taxcalc-4.6.0 → taxcalc-4.6.1}/conda.recipe/meta.yaml +0 -0
  33. {taxcalc-4.6.0 → taxcalc-4.6.1}/csv_show.sh +0 -0
  34. {taxcalc-4.6.0 → taxcalc-4.6.1}/csv_vars.sh +0 -0
  35. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/PSL.svg +0 -0
  36. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/_config.yml +0 -0
  37. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/_static/atr.png +0 -0
  38. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/_static/mtr.png +0 -0
  39. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/_static/pch.png +0 -0
  40. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/_toc.yml +0 -0
  41. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/about/LICENSE.md +0 -0
  42. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/about/history.md +0 -0
  43. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/about/roadmap.md +0 -0
  44. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/api/calcfunctions.rst +0 -0
  45. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/api/calculator.rst +0 -0
  46. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/api/consumption.rst +0 -0
  47. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/api/data.rst +0 -0
  48. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/api/decorators.rst +0 -0
  49. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/api/growdiff.rst +0 -0
  50. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/api/growfactors.rst +0 -0
  51. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/api/parameters.rst +0 -0
  52. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/api/policy.rst +0 -0
  53. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/api/public_api.rst +0 -0
  54. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/api/records.rst +0 -0
  55. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/api/taxcalcio.rst +0 -0
  56. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/api/utils.rst +0 -0
  57. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/api/utilsprvt.rst +0 -0
  58. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/contributing/RELEASING.md +0 -0
  59. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/contributing/contributor_guide.md +0 -0
  60. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/contributing/param_naming.md +0 -0
  61. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/contributing/pr_workflow.md +0 -0
  62. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/contributing/testing.md +0 -0
  63. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/README.md +0 -0
  64. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/assumption_params.md +0 -0
  65. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/index.md +0 -0
  66. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/input_vars.md +0 -0
  67. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/make/make_io_vars.py +0 -0
  68. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/make/make_params.py +0 -0
  69. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/make/make_uguide.py +0 -0
  70. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/output_vars.md +0 -0
  71. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/policy_params.md +0 -0
  72. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/python_interface.md +0 -0
  73. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/templates/assumption_params_template.md +0 -0
  74. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/templates/input_vars_template.md +0 -0
  75. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/templates/output_vars_template.md +0 -0
  76. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/guide/templates/policy_params_template.md +0 -0
  77. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/README.md +0 -0
  78. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/_static/reformA.json +0 -0
  79. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/_static/reformB.json +0 -0
  80. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/_static/reformC.json +0 -0
  81. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/convert_all.sh +0 -0
  82. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/index.md +0 -0
  83. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/md_src/recipe00.md +0 -0
  84. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/md_src/recipe01.md +0 -0
  85. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/md_src/recipe02.md +0 -0
  86. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/md_src/recipe03.md +0 -0
  87. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/md_src/recipe04.md +0 -0
  88. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/md_src/recipe04_pandas.md +0 -0
  89. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/md_src/recipe05.md +0 -0
  90. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/md_src/recipe06.md +0 -0
  91. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/recipe00.ipynb +0 -0
  92. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/recipe01.ipynb +0 -0
  93. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/recipe02.ipynb +0 -0
  94. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/recipe03.ipynb +0 -0
  95. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/recipe04.ipynb +0 -0
  96. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/recipe04_pandas.ipynb +0 -0
  97. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/recipe05.ipynb +0 -0
  98. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/recipes/recipe06.ipynb +0 -0
  99. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/usage/data.md +0 -0
  100. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/usage/overview.md +0 -0
  101. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/usage/starting.md +0 -0
  102. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/usage/tcja_after_2025.md +0 -0
  103. {taxcalc-4.6.0 → taxcalc-4.6.1}/docs/use_cases.md +0 -0
  104. {taxcalc-4.6.0 → taxcalc-4.6.1}/environment.yml +0 -0
  105. {taxcalc-4.6.0 → taxcalc-4.6.1}/extend_tcja.py +0 -0
  106. {taxcalc-4.6.0 → taxcalc-4.6.1}/gitpr +0 -0
  107. {taxcalc-4.6.0 → taxcalc-4.6.1}/gitpr.bat +0 -0
  108. {taxcalc-4.6.0 → taxcalc-4.6.1}/gitsync +0 -0
  109. {taxcalc-4.6.0 → taxcalc-4.6.1}/gitsync.bat +0 -0
  110. {taxcalc-4.6.0 → taxcalc-4.6.1}/ppp.py +0 -0
  111. {taxcalc-4.6.0 → taxcalc-4.6.1}/pyproject.toml +0 -0
  112. {taxcalc-4.6.0 → taxcalc-4.6.1}/pytest.ini +0 -0
  113. {taxcalc-4.6.0 → taxcalc-4.6.1}/setup.cfg +0 -0
  114. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/assumptions/ASSUMPTIONS.md +0 -0
  115. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/assumptions/README.md +0 -0
  116. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/assumptions/economic_assumptions_template.json +0 -0
  117. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/calcfunctions.py +0 -0
  118. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/cli/__init__.py +0 -0
  119. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/conftest.py +0 -0
  120. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/consumption.json +0 -0
  121. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/consumption.py +0 -0
  122. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/cps.csv.gz +0 -0
  123. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/cps_weights.csv.gz +0 -0
  124. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/decorators.py +0 -0
  125. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/growdiff.json +0 -0
  126. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/growdiff.py +0 -0
  127. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/growfactors.csv +0 -0
  128. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/growfactors.py +0 -0
  129. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/policy.py +0 -0
  130. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/puf_ratios.csv +0 -0
  131. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/puf_weights.csv.gz +0 -0
  132. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/records.py +0 -0
  133. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/records_variables.json +0 -0
  134. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/2017_law.json +0 -0
  135. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/2017_law.out.csv +0 -0
  136. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/ARPA.json +0 -0
  137. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/ARPA.out.csv +0 -0
  138. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/BrownKhanna.json +0 -0
  139. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/BrownKhanna.out.csv +0 -0
  140. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/CARES.json +0 -0
  141. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/CARES.out.csv +0 -0
  142. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/ConsolidatedAppropriationsAct2021.json +0 -0
  143. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/ConsolidatedAppropriationsAct2021.out.csv +0 -0
  144. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/Larson2019.json +0 -0
  145. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/Larson2019.out.csv +0 -0
  146. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/README.md +0 -0
  147. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/REFORMS.md +0 -0
  148. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/Renacci.json +0 -0
  149. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/Renacci.out.csv +0 -0
  150. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/SandersDeFazio.json +0 -0
  151. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/SandersDeFazio.out.csv +0 -0
  152. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/TCJA.json +0 -0
  153. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/TCJA.md +0 -0
  154. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/TCJA.out.csv +0 -0
  155. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/Trump2016.json +0 -0
  156. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/Trump2016.out.csv +0 -0
  157. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/Trump2017.json +0 -0
  158. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/Trump2017.out.csv +0 -0
  159. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/archive/Clinton2016.json +0 -0
  160. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/archive/RyanBrady.json +0 -0
  161. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/archive/TCJA_House.json +0 -0
  162. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/archive/TCJA_House_Amended.json +0 -0
  163. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/archive/TCJA_Reconciliation.json +0 -0
  164. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/archive/TCJA_Senate.json +0 -0
  165. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/archive/TCJA_Senate_111417.json +0 -0
  166. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/archive/TCJA_Senate_120117.json +0 -0
  167. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/cases.csv +0 -0
  168. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/clp.out.csv +0 -0
  169. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/ext.json +0 -0
  170. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/growfactors_ext.csv +0 -0
  171. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/ptaxes0.json +0 -0
  172. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/ptaxes0.out.csv +0 -0
  173. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/ptaxes1.json +0 -0
  174. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/ptaxes1.out.csv +0 -0
  175. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/ptaxes2.json +0 -0
  176. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/ptaxes2.out.csv +0 -0
  177. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/ptaxes3.json +0 -0
  178. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/reforms/ptaxes3.out.csv +0 -0
  179. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/benefits_expect.csv +0 -0
  180. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/cmpi_cps_expect.txt +0 -0
  181. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/cmpi_puf_expect.txt +0 -0
  182. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/conftest.py +0 -0
  183. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/cpscsv_agg_expect.csv +0 -0
  184. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/puf_var_correl_coeffs_2016.csv +0 -0
  185. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/puf_var_wght_means_by_year.csv +0 -0
  186. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/pufcsv_agg_expect.csv +0 -0
  187. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/pufcsv_mtr_expect.txt +0 -0
  188. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/reforms.json +0 -0
  189. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/reforms_expect.csv +0 -0
  190. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_4package.py +0 -0
  191. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_benefits.py +0 -0
  192. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_calcfunctions.py +0 -0
  193. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_compare.py +0 -0
  194. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_compatible_data.py +0 -0
  195. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_consumption.py +0 -0
  196. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_cpscsv.py +0 -0
  197. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_data.py +0 -0
  198. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_decorators.py +0 -0
  199. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_growdiff.py +0 -0
  200. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_growfactors.py +0 -0
  201. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_parameters.py +0 -0
  202. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_policy.py +0 -0
  203. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_puf_var_stats.py +0 -0
  204. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_pufcsv.py +0 -0
  205. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_records.py +0 -0
  206. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_responses.py +0 -0
  207. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/tests/test_utils.py +0 -0
  208. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/utils.py +0 -0
  209. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/utilsprvt.py +0 -0
  210. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/CSV_INPUT_VARS.md +0 -0
  211. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/CSV_OUTPUT_VARS.md +0 -0
  212. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/README.md +0 -0
  213. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/Differences_Explained.md +0 -0
  214. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/README.md +0 -0
  215. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/expected_differences/a17-taxdiffs-expect.csv +0 -0
  216. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/expected_differences/a18-taxdiffs-expect.csv +0 -0
  217. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/expected_differences/a19-taxdiffs-expect.csv +0 -0
  218. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/expected_differences/a20-taxdiffs-expect.csv +0 -0
  219. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/expected_differences/a21-taxdiffs-expect.csv +0 -0
  220. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/expected_differences/b17-taxdiffs-expect.csv +0 -0
  221. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/expected_differences/b18-taxdiffs-expect.csv +0 -0
  222. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/expected_differences/b19-taxdiffs-expect.csv +0 -0
  223. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/expected_differences/b20-taxdiffs-expect.csv +0 -0
  224. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/expected_differences/b21-taxdiffs-expect.csv +0 -0
  225. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/expected_differences/c17-taxdiffs-expect.csv +0 -0
  226. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/expected_differences/c18-taxdiffs-expect.csv +0 -0
  227. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/expected_differences/c19-taxdiffs-expect.csv +0 -0
  228. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/input_setup.py +0 -0
  229. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/main_comparison.py +0 -0
  230. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/prepare_taxcalc_input.py +0 -0
  231. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/process_taxcalc_output.py +0 -0
  232. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/taxsim_emulation.json +0 -0
  233. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/taxsim_input.py +0 -0
  234. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/tc_sims.py +0 -0
  235. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/taxsim35/tests_35.py +0 -0
  236. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc/validation/tests_35.sh +0 -0
  237. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc.egg-info/SOURCES.txt +0 -0
  238. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc.egg-info/dependency_links.txt +0 -0
  239. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc.egg-info/entry_points.txt +0 -0
  240. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc.egg-info/requires.txt +0 -0
  241. {taxcalc-4.6.0 → taxcalc-4.6.1}/taxcalc.egg-info/top_level.txt +0 -0
  242. {taxcalc-4.6.0 → taxcalc-4.6.1}/tctest-nojit.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taxcalc
3
- Version: 4.6.0
3
+ Version: 4.6.1
4
4
  Summary: Tax-Calculator
5
5
  Home-page: https://github.com/PSLmodels/Tax-Calculator
6
6
  Download-URL: https://github.com/PSLmodels/Tax-Calculator
@@ -4,6 +4,29 @@ Go [here](https://github.com/PSLmodels/Tax-Calculator/pulls?q=is%3Apr+is%3Aclose
4
4
  for a complete commit history.
5
5
 
6
6
 
7
+ 2025-05-09 Release 4.6.1
8
+ ------------------------
9
+ (last merged pull request is
10
+ [#2900](https://github.com/PSLmodels/Tax-Calculator/pull/2900))
11
+
12
+ **This is a minor enhancement and bug-fix release.**
13
+
14
+ **API Changes**
15
+
16
+ **New Features**
17
+ - Add ability to specify compound reforms when using the CLI tool's
18
+ `--baseline` option
19
+ [[#2896](https://github.com/PSLmodels/Tax-Calculator/pull/2896) by Martin Holmer]
20
+ - Improve documentation of the `parameter_indexing_CPI_offset` policy parameter
21
+ [[#2897](https://github.com/PSLmodels/Tax-Calculator/pull/2897) by Martin Holmer]
22
+ - Add CLI `--numyears N` option that allows faster multiple-year runs with `tc`
23
+ [[#2900](https://github.com/PSLmodels/Tax-Calculator/pull/2900) by Martin Holmer]
24
+
25
+ **Bug Fixes**
26
+ - Remove redundant Parameters class property
27
+ [[#2898](https://github.com/PSLmodels/Tax-Calculator/pull/2898) by Martin Holmer]
28
+
29
+
7
30
  2025-04-30 Release 4.6.0
8
31
  ------------------------
9
32
  (last merged pull request is
@@ -375,18 +375,11 @@ The `cps-24-#-ref3-#-mtr.html` file looks something like this:
375
375
  In all the examples in this section, we have executed one `tc` run at
376
376
  at time. But **what if you want to execute many `tc` runs** because
377
377
  you want results for many years and/or for several different reforms.
378
- Unless you are asking for an enormous dump database, a single `tc` run
379
- should take no more than one minute on your computer. The easiest way
380
- to speed up the execution of many `tc` runs is to split them into
381
- groups of runs and execute each group of runs in a different
382
- command-prompt window. On most modern computers that have four or
383
- more CPU cores, at least eight gigabytes of memory, and fast disk
384
- storage, executing four or five runs in different windows will take
385
- only a little more time than executing a single `tc` run. If you have
386
- more than one run in each group, put them in a Unix/Mac bash script or
387
- a Windows batch file, and execute one script in each command-prompt
388
- window. If it still takes too long, consider splitting the `tc` runs
389
- across more than one computer.
378
+ The best way to execute multiple-year runs (say, ten-year runs to
379
+ generate budget-window estimates) is to use the `--numyears N` option
380
+ as decribed
381
+ [here](https://github.com/PSLmodels/Tax-Calculator/pull/2900#issue-3047043290)
382
+ and below in the final section of this document.
390
383
 
391
384
  ## Tabulate reform results
392
385
 
@@ -529,3 +522,41 @@ Notice the -331.101 aggregate change in income tax liability induced
529
522
  by the reform is essentially the same as the -331.1 amount in the
530
523
  --tables output above, although the income subgroups amounts differ
531
524
  because the income groups are defined in different ways.
525
+
526
+ ## Generate budget-window results
527
+
528
+ Sometimes ten-year results for a reform are needed. The easiest way
529
+ to generate such budget-window results is to use the CLI tool's
530
+ `--numyears N` option. If `ext.json` contains the
531
+ extend-TCJA-beyond-2025 reform, then we can execute the following run:
532
+
533
+ ```
534
+ % tc ../tmd.csv 2026 --numyears 10 --reform ext.json --tables
535
+ Read input data for 2021; input data were extrapolated to 2026
536
+ Write tabular output to file tmd-26-#-ext-#-tables.text
537
+ Advance input data and policy to 2027
538
+ Write tabular output to file tmd-27-#-ext-#-tables.text
539
+ Advance input data and policy to 2028
540
+ Write tabular output to file tmd-28-#-ext-#-tables.text
541
+ Advance input data and policy to 2029
542
+ Write tabular output to file tmd-29-#-ext-#-tables.text
543
+ Advance input data and policy to 2030
544
+ Write tabular output to file tmd-30-#-ext-#-tables.text
545
+ Advance input data and policy to 2031
546
+ Write tabular output to file tmd-31-#-ext-#-tables.text
547
+ Advance input data and policy to 2032
548
+ Write tabular output to file tmd-32-#-ext-#-tables.text
549
+ Advance input data and policy to 2033
550
+ Write tabular output to file tmd-33-#-ext-#-tables.text
551
+ Advance input data and policy to 2034
552
+ Write tabular output to file tmd-34-#-ext-#-tables.text
553
+ Advance input data and policy to 2035
554
+ Write tabular output to file tmd-35-#-ext-#-tables.text
555
+ Execution time is 60.9 seconds
556
+ ```
557
+
558
+ [PR
559
+ #2900](https://github.com/PSLmodels/Tax-Calculator/pull/2900#issue-3047043290)
560
+ discusses how much faster this is relative to executing ten separate
561
+ `tc` runs, and also shows how to tabulate the ten-year aggregate
562
+ reform result from the files generated by this run.
@@ -5,17 +5,14 @@ Tax-Calculator
5
5
 
6
6
  Tax-Calculator is an open-source microsimulation model for static analysis of
7
7
  USA federal income and payroll taxes.
8
- You can install it with [Anaconda](https://www.anaconda.com/products/individual)
9
- via:
10
-
8
+ You can install it with [PyPI](https://pypi.org/project/taxcalc/) via:
11
9
  ```
12
- conda update taxcalc
10
+ pip install taxcalc
13
11
  ```
14
-
15
- or with [PyPI](https://pypi.org/project/taxcalc/) via:
16
-
12
+ or with [Anaconda](https://www.anaconda.com/products/individual)
13
+ via:
17
14
  ```
18
- pip install taxcalc
15
+ conda install conda-forge::taxcalc
19
16
  ```
20
17
 
21
18
  When using sample data that represent the USA population,
@@ -57,18 +54,15 @@ cross-model validation work with NBER's TAXSIM-35 model is described
57
54
 
58
55
  ## Latest release
59
56
 
60
- {doc}`4.5.0 (2025-03-11) <about/releases>`
57
+ {doc}`4.6.1 (2025-05-09) <about/releases>`
61
58
 
62
59
  If you are already using Tax-Calculator, upgrade using the following command:
63
-
64
60
  ```
65
- conda update conda-forge::taxcalc
61
+ pip install --upgrade taxcalc
66
62
  ```
67
-
68
63
  or
69
-
70
64
  ```
71
- pip install --upgrade taxcalc
65
+ conda update conda-forge::taxcalc
72
66
  ```
73
67
 
74
68
  If you're a new user, read {doc}`usage/starting`.
@@ -7,7 +7,7 @@ from setuptools import setup
7
7
  with open("README.md", "r", encoding="utf-8") as f:
8
8
  longdesc = f.read()
9
9
 
10
- VERSION = "4.6.0"
10
+ VERSION = "4.6.1"
11
11
 
12
12
  config = {
13
13
  "description": "Tax-Calculator",
@@ -14,6 +14,6 @@ from taxcalc.taxcalcio import *
14
14
  from taxcalc.utils import *
15
15
  from taxcalc.cli import *
16
16
 
17
- __version__ = '4.6.0'
17
+ __version__ = '4.6.1'
18
18
  __min_python3_version__ = 10
19
19
  __max_python3_version__ = 12
@@ -305,11 +305,11 @@ class Calculator():
305
305
  return self.__consumption.benval_params()
306
306
 
307
307
  @property
308
- def reform_warnings(self):
308
+ def reform_errors(self):
309
309
  """
310
- Calculator class embedded Policy object's parameter_warnings.
310
+ Calculator class embedded Policy object's parameter_errors.
311
311
  """
312
- return self.__policy.parameter_warnings
312
+ return self.__policy.parameter_errors
313
313
 
314
314
  @property
315
315
  def current_year(self):
@@ -1,6 +1,6 @@
1
1
  """
2
2
  Command-line interface (CLI) to Tax-Calculator,
3
- which can be accessed as 'tc' from an installed taxcalc conda package.
3
+ which can be accessed as 'tc' from an installed taxcalc package.
4
4
  """
5
5
  # CODING-STYLE CHECKS:
6
6
  # pycodestyle tc.py
@@ -30,7 +30,7 @@ def cli_tc_main():
30
30
 
31
31
  # parse command-line arguments:
32
32
  usage_str = 'tc INPUT TAXYEAR {}{}{}{}'.format(
33
- '[--help]\n',
33
+ '[--help] [--numyears N]\n',
34
34
  (
35
35
  ' '
36
36
  '[--baseline BASELINE] [--reform REFORM] '
@@ -63,15 +63,26 @@ def cli_tc_main():
63
63
  'are computed.'),
64
64
  type=int,
65
65
  default=0)
66
+ parser.add_argument('--numyears', metavar='N',
67
+ help=('N is an integer indicating for how many '
68
+ 'years taxes are calculated. No --numyears '
69
+ 'implies calculations are done only for '
70
+ 'TAXYEAR. N greater than one implies output '
71
+ 'is written to separate files for each year '
72
+ 'beginning with TAXYEAR.'),
73
+ type=int,
74
+ default=1)
66
75
  parser.add_argument('--baseline',
67
76
  help=('BASELINE is name of optional JSON reform file. '
77
+ 'A compound reform can be specified using 2+ '
78
+ 'file names separated by plus (+) character(s). '
68
79
  'No --baseline implies baseline policy is '
69
80
  'current-law policy.'),
70
81
  default=None)
71
82
  parser.add_argument('--reform',
72
83
  help=('REFORM is name of optional JSON reform file. '
73
- 'A compound reform can be specified using two '
74
- 'file names separated by a plus (+) character. '
84
+ 'A compound reform can be specified using 2+ '
85
+ 'file names separated by plus (+) character(s). '
75
86
  'No --reform implies reform policy is '
76
87
  'current-law policy).'),
77
88
  default=None)
@@ -167,11 +178,54 @@ def cli_tc_main():
167
178
  _write_test_files()
168
179
  inputfn = TEST_INPUT_FILENAME
169
180
  taxyear = TEST_TAXYEAR
181
+ args.numyears = 1
170
182
  args.dumpdb = True
171
183
  else:
172
184
  inputfn = args.INPUT
173
185
  taxyear = args.TAXYEAR
174
- # instantiate TaxCalcIO object and do tax analysis
186
+ # check taxyear value
187
+ if taxyear > tc.Policy.LAST_BUDGET_YEAR:
188
+ msg = f'ERROR: TAXYEAR is greater than {tc.Policy.LAST_BUDGET_YEAR}\n'
189
+ sys.stderr.write(msg)
190
+ sys.stderr.write('USAGE: tc --help\n')
191
+ return 1
192
+ # check numyears value
193
+ if args.numyears < 1:
194
+ msg = 'ERROR: --numyears parameter N is less than one\n'
195
+ sys.stderr.write(msg)
196
+ sys.stderr.write('USAGE: tc --help\n')
197
+ return 1
198
+ max_numyears = tc.Policy.LAST_BUDGET_YEAR - taxyear + 1
199
+ if args.numyears > max_numyears:
200
+ msg = f'ERROR: --numyears parameter N is greater than {max_numyears}\n'
201
+ sys.stderr.write(msg)
202
+ sys.stderr.write('USAGE: tc --help\n')
203
+ return 1
204
+ # specify if aging input data
205
+ aging_data = (
206
+ inputfn.endswith('puf.csv') or
207
+ inputfn.endswith('cps.csv') or
208
+ inputfn.endswith('tmd.csv')
209
+ )
210
+ # check args.dumpdb and args.dumpvars consistency
211
+ if not args.dumpdb and args.dumpvars:
212
+ msg = 'ERROR: DUMPVARS file specified without --dumpdb option\n'
213
+ sys.stderr.write(msg)
214
+ sys.stderr.write('USAGE: tc --help\n')
215
+ return 1
216
+ # specify dumpvars_str from args.dumpvars file
217
+ dumpvars_str = ''
218
+ if args.dumpvars:
219
+ if os.path.exists(args.dumpvars):
220
+ with open(args.dumpvars, 'r', encoding='utf-8') as dfile:
221
+ dumpvars_str = dfile.read()
222
+ else:
223
+ msg = f'ERROR: DUMPVARS file {args.dumpvars} does not exist\n'
224
+ sys.stderr.write(msg)
225
+ sys.stderr.write('USAGE: tc --help\n')
226
+ return 1
227
+ # do calculations for taxyear
228
+ # ... initialize TaxCalcIO object for taxyear
175
229
  tcio = tc.TaxCalcIO(
176
230
  input_data=inputfn,
177
231
  tax_year=taxyear,
@@ -187,17 +241,13 @@ def cli_tc_main():
187
241
  sys.stderr.write(tcio.errmsg + '\n')
188
242
  sys.stderr.write('USAGE: tc --help\n')
189
243
  return 1
190
- aging = (
191
- inputfn.endswith('puf.csv') or
192
- inputfn.endswith('cps.csv') or
193
- inputfn.endswith('tmd.csv')
194
- )
195
244
  tcio.init(
196
245
  input_data=inputfn,
197
246
  tax_year=taxyear,
198
247
  baseline=args.baseline,
199
- reform=args.reform, assump=args.assump,
200
- aging_input_data=aging,
248
+ reform=args.reform,
249
+ assump=args.assump,
250
+ aging_input_data=aging_data,
201
251
  exact_calculations=args.exact,
202
252
  )
203
253
  if tcio.errmsg:
@@ -207,23 +257,7 @@ def cli_tc_main():
207
257
  sys.stderr.write(tcio.errmsg + '\n')
208
258
  sys.stderr.write('USAGE: tc --help\n')
209
259
  return 1
210
- # check args.dumpdb and args.dumpvars consistency
211
- if not args.dumpdb and args.dumpvars:
212
- msg = 'ERROR: DUMPVARS file specified without --dumpdb option\n'
213
- sys.stderr.write(msg)
214
- sys.stderr.write('USAGE: tc --help\n')
215
- return 1
216
- # construct dumpvars set from dumpvars_str
217
- dumpvars_str = ''
218
- if args.dumpvars:
219
- if os.path.exists(args.dumpvars):
220
- with open(args.dumpvars, 'r', encoding='utf-8') as dfile:
221
- dumpvars_str = dfile.read()
222
- else:
223
- msg = f'ERROR: DUMPVARS file {args.dumpvars} does not exist\n'
224
- sys.stderr.write(msg)
225
- sys.stderr.write('USAGE: tc --help\n')
226
- return 1
260
+ # ... conduct tax analysis for taxyear
227
261
  dumpvars_list = tcio.dump_variables(dumpvars_str)
228
262
  if tcio.errmsg:
229
263
  if tcio.errmsg.endswith('\n'):
@@ -232,7 +266,6 @@ def cli_tc_main():
232
266
  sys.stderr.write(tcio.errmsg + '\n')
233
267
  sys.stderr.write('USAGE: tc --help\n')
234
268
  return 1
235
- # conduct tax analysis
236
269
  tcio.analyze(
237
270
  output_params=args.params,
238
271
  output_tables=args.tables,
@@ -244,6 +277,23 @@ def cli_tc_main():
244
277
  if args.test:
245
278
  retcode = _compare_test_output_files()
246
279
  return retcode
280
+ # quit if args.numyears is equal to one
281
+ if args.numyears == 1:
282
+ if not args.silent:
283
+ print( # pragma: no cover
284
+ f'Execution time is {(time.time() - start_time):.1f} seconds'
285
+ )
286
+ return 0
287
+ # analyze years after taxyear if args.numyears is greater than one
288
+ for xyear in range(1, args.numyears):
289
+ tcio.advance_to_year(taxyear + xyear, aging_data)
290
+ tcio.analyze(
291
+ output_params=args.params,
292
+ output_tables=args.tables,
293
+ output_graphs=args.graphs,
294
+ output_dump=args.dumpdb,
295
+ dump_varlist=dumpvars_list,
296
+ )
247
297
  if not args.silent:
248
298
  print( # pragma: no cover
249
299
  f'Execution time is {(time.time() - start_time):.1f} seconds'
@@ -147,8 +147,8 @@ class Data():
147
147
 
148
148
  def increment_year(self):
149
149
  """
150
- Add one to current year; and also does
151
- extrapolation & reweighting for new current year if aged_data is True.
150
+ Add one to current year; and also does extrapolation & reweighting
151
+ of data for the new current year if self._aging_data is True.
152
152
  """
153
153
  # move to next year
154
154
  self.__current_year += 1
@@ -706,11 +706,6 @@ class Parameters(pt.Parameters):
706
706
  """Propery docstring"""
707
707
  return self.end_year - self.start_year + 1
708
708
 
709
- @property
710
- def parameter_warnings(self):
711
- """Propery docstring"""
712
- return self.errors or {}
713
-
714
709
  @property
715
710
  def parameter_errors(self):
716
711
  """Propery docstring"""
@@ -76,8 +76,8 @@
76
76
  }
77
77
  },
78
78
  "parameter_indexing_CPI_offset": {
79
- "title": "OBSOLETE: Decimal offset ADDED to unchained CPI to get parameter indexing rate",
80
- "description": "OBSOLETE policy parameter.",
79
+ "title": "Decimal offset added to chained CPI-U inflation rate to get policy parameter indexing rate",
80
+ "description": "Always zero in policy_current_law.json, but non-zero values are allowed in reforms.",
81
81
  "notes": "",
82
82
  "section_1": "Parameter Indexing",
83
83
  "section_2": "Offsets",
@@ -104,6 +104,10 @@
104
104
  {
105
105
  "year": 2017,
106
106
  "value": 0.0
107
+ },
108
+ {
109
+ "year": 2018,
110
+ "value": 0.0
107
111
  }
108
112
  ],
109
113
  "validators": {
@@ -115,23 +115,37 @@ class TaxCalcIO():
115
115
  else:
116
116
  msg = 'INPUT is neither string nor Pandas DataFrame'
117
117
  self.errmsg += f'ERROR: {msg}\n'
118
- # check name and existence of BASELINE file
118
+ # check name(s) and existence of BASELINE file(s)
119
119
  bas = '-x'
120
120
  if baseline is None:
121
+ self.specified_baseline = False
121
122
  bas = '-#'
122
123
  elif isinstance(baseline, str):
123
- # remove any leading directory path from BASELINE filename
124
- fname = os.path.basename(baseline)
125
- # check if fname ends with ".json"
126
- if fname.endswith('.json'):
127
- bas = f'-{fname[:-5]}'
128
- else:
129
- msg = 'BASELINE file name does not end in .json'
130
- self.errmsg += f'ERROR: {msg}\n'
131
- # check existence of BASELINE file
132
- if not os.path.isfile(baseline):
133
- msg = 'BASELINE file could not be found'
134
- self.errmsg += f'ERROR: {msg}\n'
124
+ self.specified_baseline = True
125
+ # split any compound baseline into list of simple reforms
126
+ basnames = []
127
+ baselines = baseline.split('+')
128
+ for bas in baselines:
129
+ # remove any leading directory path from bas filename
130
+ fname = os.path.basename(bas)
131
+ # check if fname ends with ".json"
132
+ if not fname.endswith('.json'):
133
+ msg = f'{fname} does not end in .json'
134
+ self.errmsg += f'ERROR: BASELINE file name {msg}\n'
135
+ # check existence of BASELINE file
136
+ if not os.path.isfile(bas):
137
+ msg = f'{bas} could not be found'
138
+ self.errmsg += f'ERROR: BASELINE file {msg}\n'
139
+ # add fname to list of basnames used in output file names
140
+ basnames.append(fname)
141
+ # create (possibly compound) baseline name for output file names
142
+ bas = '-'
143
+ num_basnames = 0
144
+ for basname in basnames:
145
+ num_basnames += 1
146
+ if num_basnames > 1:
147
+ bas += '+'
148
+ bas += f'{basname[:-5]}'
135
149
  else:
136
150
  msg = 'TaxCalcIO.ctor: baseline is neither None nor str'
137
151
  self.errmsg += f'ERROR: {msg}\n'
@@ -191,6 +205,15 @@ class TaxCalcIO():
191
205
  self.errmsg += f'ERROR: {msg}\n'
192
206
  # create OUTPUT file name and delete any existing output files
193
207
  self.output_filename = f'{inp}{bas}{ref}{asm}.xxx'
208
+ self.delete_output_files()
209
+ # initialize variables whose values are set in init method
210
+ self.calc_ref = None
211
+ self.calc_bas = None
212
+
213
+ def delete_output_files(self):
214
+ """
215
+ Delete all output files derived from self.output_filename.
216
+ """
194
217
  extensions = [
195
218
  '-params.bas',
196
219
  '-params.ref',
@@ -202,9 +225,6 @@ class TaxCalcIO():
202
225
  ]
203
226
  for ext in extensions:
204
227
  delete_file(self.output_filename.replace('.xxx', ext))
205
- # initialize variables whose values are set in init method
206
- self.calc_ref = None
207
- self.calc_bas = None
208
228
 
209
229
  def init(self, input_data, tax_year, baseline, reform, assump,
210
230
  aging_input_data, exact_calculations):
@@ -258,8 +278,12 @@ class TaxCalcIO():
258
278
  return
259
279
  # get assumption sub-dictionaries
260
280
  assumpdict = Calculator.read_json_param_objects(None, assump)
261
- # get policy parameter dictionary from --baseline file
262
- poldict_bas = Calculator.read_json_param_objects(baseline, None)
281
+ # get policy parameter dictionaries from --baseline file(s)
282
+ poldicts_bas = []
283
+ if self.specified_baseline:
284
+ for bas in baseline.split('+'):
285
+ pdict = Calculator.read_json_param_objects(bas, None)
286
+ poldicts_bas.append(pdict['policy'])
263
287
  # get policy parameter dictionaries from --reform file(s)
264
288
  poldicts_ref = []
265
289
  if self.specified_reform:
@@ -288,20 +312,29 @@ class TaxCalcIO():
288
312
  self.gf_reform = copy.deepcopy(gfactors_ref)
289
313
  # create Policy objects:
290
314
  # ... the baseline Policy object
291
- pol_bas = Policy(
292
- gfactors=gfactors_bas,
293
- last_budget_year=last_b_year,
294
- )
295
- try:
296
- pol_bas.implement_reform(
297
- poldict_bas['policy'],
298
- print_warnings=True,
299
- raise_errors=False,
315
+ if self.specified_baseline:
316
+ pol_bas = Policy(
317
+ gfactors=gfactors_bas,
318
+ last_budget_year=last_b_year,
319
+ )
320
+ for poldict in poldicts_bas:
321
+ try:
322
+ pol_bas.implement_reform(
323
+ poldict,
324
+ print_warnings=True,
325
+ raise_errors=False,
326
+ )
327
+ if self.errmsg:
328
+ self.errmsg += "\n"
329
+ for _, errors in pol_bas.parameter_errors.items():
330
+ self.errmsg += "\n".join(errors)
331
+ except paramtools.ValidationError as valerr_msg:
332
+ self.errmsg += str(valerr_msg)
333
+ else:
334
+ pol_bas = Policy(
335
+ gfactors=gfactors_bas,
336
+ last_budget_year=last_b_year,
300
337
  )
301
- for _, errors in pol_bas.parameter_errors.items():
302
- self.errmsg += "\n".join(errors)
303
- except paramtools.ValidationError as valerr_msg:
304
- self.errmsg += str(valerr_msg)
305
338
  # ... the reform Policy object
306
339
  if self.specified_reform:
307
340
  pol_ref = Policy(
@@ -419,6 +452,22 @@ class TaxCalcIO():
419
452
  dirpath = os.path.abspath(os.path.dirname(__file__))
420
453
  return os.path.join(dirpath, self.output_filename)
421
454
 
455
+ def advance_to_year(self, year, aging_data):
456
+ """
457
+ Update self.output_filename and advance Calculator objects to year.
458
+ """
459
+ # update self.output_filename and delete output files
460
+ parts = self.output_filename.split('-')
461
+ parts[1] = str(year)[2:]
462
+ self.output_filename = '-'.join(parts)
463
+ self.delete_output_files()
464
+ # advance baseline and reform Calculator objects to specified year
465
+ self.calc_bas.advance_to_year(year)
466
+ self.calc_ref.advance_to_year(year)
467
+ idata = 'Advance input data and ' if aging_data else 'Advance'
468
+ if not self.silent:
469
+ print(f'{idata} policy to {year}')
470
+
422
471
  def analyze(
423
472
  self,
424
473
  output_params=False,
@@ -458,47 +507,36 @@ class TaxCalcIO():
458
507
  """
459
508
  # pylint: disable=too-many-arguments,too-many-positional-arguments
460
509
  # pylint: disable=too-many-branches,too-many-locals
461
- if self.puf_input_data and self.calc_ref.reform_warnings:
462
- print( # pragma: no cover
463
- 'PARAMETER VALUE WARNING(S): '
464
- '(read documentation for each parameter)\n'
465
- f'{self.calc_ref.reform_warnings}'
466
- 'CONTINUING WITH CALCULATIONS...'
467
- )
468
- calc_base_calculated = False
510
+ doing_calcs = output_tables or output_graphs or output_dump
511
+ # optionally write --params output to text files
512
+ if output_params:
513
+ self.write_policy_params_files()
514
+ if not doing_calcs:
515
+ return
516
+ # do output calculations
517
+ self.calc_bas.calc_all()
469
518
  self.calc_ref.calc_all()
470
519
  if output_dump:
471
520
  assert isinstance(dump_varlist, list)
472
521
  assert len(dump_varlist) > 0
473
- # might need marginal tax rates
522
+ # might need marginal tax rates for dumpdb
474
523
  (mtr_ptax_ref, mtr_itax_ref,
475
524
  _) = self.calc_ref.mtr(wrt_full_compensation=False,
476
525
  calc_all_already_called=True)
477
- self.calc_bas.calc_all()
478
- calc_base_calculated = True
479
526
  (mtr_ptax_bas, mtr_itax_bas,
480
527
  _) = self.calc_bas.mtr(wrt_full_compensation=False,
481
528
  calc_all_already_called=True)
482
529
  else:
483
- # definitely do not need marginal tax rates
530
+ # do not need marginal tax rates for dumpdb
484
531
  mtr_ptax_ref = None
485
532
  mtr_itax_ref = None
486
533
  mtr_ptax_bas = None
487
534
  mtr_itax_bas = None
488
- # optionally write --params output to text files
489
- if output_params:
490
- self.write_policy_params_files()
491
535
  # optionally write --tables output to text file
492
536
  if output_tables:
493
- if not calc_base_calculated:
494
- self.calc_bas.calc_all()
495
- calc_base_calculated = True
496
537
  self.write_tables_file()
497
538
  # optionally write --graphs output to HTML files
498
539
  if output_graphs:
499
- if not calc_base_calculated:
500
- self.calc_bas.calc_all()
501
- calc_base_calculated = True
502
540
  self.write_graph_files()
503
541
  # optionally write --dumpdb output to SQLite database file
504
542
  if output_dump:
@@ -731,7 +769,7 @@ class TaxCalcIO():
731
769
 
732
770
  def dump_variables(self, dumpvars_str):
733
771
  """
734
- Return set of variable names extracted from dumpvars_str, plus
772
+ Return list of variable names extracted from dumpvars_str, plus
735
773
  minimal baseline/reform variables even if not in dumpvars_str.
736
774
  Also, builds self.errmsg if any specified variables are not valid.
737
775
  """
@@ -69,7 +69,7 @@ def test_make_calculator_with_policy_reform(cps_subsample):
69
69
  pol.implement_reform(reform)
70
70
  # create a Calculator object using this policy reform
71
71
  calc = Calculator(policy=pol, records=rec)
72
- assert calc.reform_warnings == {}
72
+ assert calc.reform_errors == {}
73
73
  # check that Policy object embedded in Calculator object is correct
74
74
  assert calc.current_year == year
75
75
  assert calc.policy_param('II_em') == 4000