policyengine-core 3.26.2__tar.gz → 3.26.3__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 (385) hide show
  1. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/CHANGELOG.md +8 -0
  2. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/PKG-INFO +1 -1
  3. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/holders/helpers.py +19 -5
  4. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/holders/holder.py +37 -18
  5. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/operations/uprate_parameters.py +171 -127
  6. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/parameter_node.py +1 -1
  7. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/parameter_scale_bracket.py +1 -1
  8. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/simulations/simulation.py +40 -12
  9. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/pyproject.toml +1 -1
  10. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameters/operations/test_uprating.py +100 -0
  11. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_apply_reform_preserves_user_inputs.py +111 -0
  12. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_holder_branch_fallback.py +15 -0
  13. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/.github/ISSUE_TEMPLATE.md +0 -0
  14. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  15. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/.github/bump_version.py +0 -0
  16. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/.github/changelog_template.md +0 -0
  17. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/.github/get-changelog-diff.sh +0 -0
  18. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/.github/has-functional-changes.sh +0 -0
  19. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/.github/is-version-number-acceptable.sh +0 -0
  20. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/.github/publish-git-tag.sh +0 -0
  21. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/.github/workflows/pr.yaml +0 -0
  22. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/.github/workflows/push.yaml +0 -0
  23. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/.gitignore +0 -0
  24. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/.python-version +0 -0
  25. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/AGENTS.md +0 -0
  26. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/CLAUDE.md +0 -0
  27. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/CONTRIBUTING.md +0 -0
  28. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/LICENSE +0 -0
  29. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/MANIFEST.in +0 -0
  30. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/Makefile +0 -0
  31. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/README.md +0 -0
  32. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/_build/logs/myst.build.json +0 -0
  33. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/changelog.d/.gitkeep +0 -0
  34. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/_config.yml +0 -0
  35. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/_static/style.css +0 -0
  36. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/_toc.yml +0 -0
  37. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/add_plotly_to_book.py +0 -0
  38. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/contributing/intro.md +0 -0
  39. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/engineering/skills/README.md +0 -0
  40. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/engineering/skills/documentation_review.md +0 -0
  41. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/engineering/skills/github-prs.md +0 -0
  42. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/engineering/skills/testing.md +0 -0
  43. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/intro.md +0 -0
  44. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/logo.png +0 -0
  45. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/commons.md +0 -0
  46. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/country_template.md +0 -0
  47. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/data.md +0 -0
  48. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/data_storage.md +0 -0
  49. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/entities.md +0 -0
  50. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/enums.md +0 -0
  51. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/errors.md +0 -0
  52. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/experimental.md +0 -0
  53. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/extension_template.md +0 -0
  54. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/holders.md +0 -0
  55. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/parameters.md +0 -0
  56. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/periods.md +0 -0
  57. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/populations.md +0 -0
  58. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/projectors.md +0 -0
  59. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/reforms.md +0 -0
  60. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/scripts.md +0 -0
  61. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/simulations.md +0 -0
  62. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/taxbenefitsystems.md +0 -0
  63. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/taxscales.md +0 -0
  64. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/tools.md +0 -0
  65. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/tracers.md +0 -0
  66. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/types.md +0 -0
  67. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/variables.md +0 -0
  68. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/python_api/warnings.md +0 -0
  69. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/usage/country.ipynb +0 -0
  70. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/usage/datasets.ipynb +0 -0
  71. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/usage/parameters.md +0 -0
  72. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/usage/reforms.ipynb +0 -0
  73. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/docs/usage/simulation.ipynb +0 -0
  74. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/mypy.ini +0 -0
  75. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/__init__.py +0 -0
  76. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/build_metadata.py +0 -0
  77. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/charts/__init__.py +0 -0
  78. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/charts/api.py +0 -0
  79. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/charts/bar.py +0 -0
  80. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/charts/formatting.py +0 -0
  81. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/commons/__init__.py +0 -0
  82. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/commons/formulas.py +0 -0
  83. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/commons/misc.py +0 -0
  84. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/commons/rates.py +0 -0
  85. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/__init__.py +0 -0
  86. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/constants.py +0 -0
  87. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/data/__init__.py +0 -0
  88. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/data/datasets/__init__.py +0 -0
  89. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/data/datasets/country_template_dataset.py +0 -0
  90. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/entities.py +0 -0
  91. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/modelled_policies.yaml +0 -0
  92. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/parameters/benefits/basic_income.yaml +0 -0
  93. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/parameters/benefits/housing_allowance.yaml +0 -0
  94. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/parameters/benefits/index.yaml +0 -0
  95. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/parameters/benefits/parenting_allowance/amount.yaml +0 -0
  96. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/parameters/benefits/parenting_allowance/income_threshold.yaml +0 -0
  97. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/parameters/general/age_of_majority.yaml +0 -0
  98. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/parameters/general/age_of_retirement.yaml +0 -0
  99. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/parameters/taxes/housing_tax.yaml +0 -0
  100. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/parameters/taxes/income_tax_rate.yaml +0 -0
  101. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/parameters/taxes/social_security_contribution.yaml +0 -0
  102. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/reforms/__init__.py +0 -0
  103. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/reforms/add_dynamic_variable.py +0 -0
  104. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/reforms/add_new_tax.py +0 -0
  105. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/reforms/flat_social_security_contribution.py +0 -0
  106. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/reforms/modify_social_security_taxation.py +0 -0
  107. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/reforms/removal_basic_income.py +0 -0
  108. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/situation_examples/__init__.py +0 -0
  109. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/situation_examples/couple.json +0 -0
  110. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/situation_examples/housing.json +0 -0
  111. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/situation_examples/single.json +0 -0
  112. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/tests/age.yaml +0 -0
  113. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/tests/basic_income.yaml +0 -0
  114. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/tests/disposable_income.yaml +0 -0
  115. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/tests/housing_allowance.yaml +0 -0
  116. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/tests/housing_tax.yaml +0 -0
  117. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/tests/income_tax.yaml +0 -0
  118. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/tests/reforms/add_dynamic_variable.yaml +0 -0
  119. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/tests/reforms/add_new_tax.yaml +0 -0
  120. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/tests/reforms/modify_social_security_taxation.yaml +0 -0
  121. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/tests/situations/income_tax.yaml +0 -0
  122. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/tests/situations/parenting_allowance.yaml +0 -0
  123. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/tests/social_security_contribution.yaml +0 -0
  124. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/tests/test_microsimulation.py +0 -0
  125. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/variables/__init__.py +0 -0
  126. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/variables/benefits.py +0 -0
  127. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/variables/demographics.py +0 -0
  128. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/variables/housing.py +0 -0
  129. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/variables/ids.py +0 -0
  130. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/variables/income.py +0 -0
  131. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/variables/stats.py +0 -0
  132. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/country_template/variables/taxes.py +0 -0
  133. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/data/__init__.py +0 -0
  134. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/data/dataset.py +0 -0
  135. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/data_storage/__init__.py +0 -0
  136. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/data_storage/in_memory_storage.py +0 -0
  137. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/data_storage/on_disk_storage.py +0 -0
  138. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/data_structures/__init__.py +0 -0
  139. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/data_structures/parameter_metadata.py +0 -0
  140. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/data_structures/parameter_node_metadata.py +0 -0
  141. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/data_structures/reference.py +0 -0
  142. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/data_structures/unit.py +0 -0
  143. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/entities/__init__.py +0 -0
  144. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/entities/entity.py +0 -0
  145. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/entities/group_entity.py +0 -0
  146. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/entities/helpers.py +0 -0
  147. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/entities/role.py +0 -0
  148. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/enums/__init__.py +0 -0
  149. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/enums/config.py +0 -0
  150. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/enums/enum.py +0 -0
  151. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/enums/enum_array.py +0 -0
  152. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/errors/__init__.py +0 -0
  153. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/errors/cycle_error.py +0 -0
  154. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/errors/empty_argument_error.py +0 -0
  155. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/errors/nan_creation_error.py +0 -0
  156. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/errors/parameter_not_found_error.py +0 -0
  157. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/errors/parameter_parsing_error.py +0 -0
  158. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/errors/period_mismatch_error.py +0 -0
  159. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/errors/situation_parsing_error.py +0 -0
  160. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/errors/spiral_error.py +0 -0
  161. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/errors/variable_name_conflict_error.py +0 -0
  162. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/errors/variable_not_found_error.py +0 -0
  163. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/experimental/__init__.py +0 -0
  164. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/experimental/memory_config.py +0 -0
  165. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/extension_template/__init__.py +0 -0
  166. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/extension_template/local_benefit.py +0 -0
  167. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/extension_template/parameters/local_town/child_allowance/amount.yaml +0 -0
  168. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/extension_template/parameters/local_town/child_allowance/index.yaml +0 -0
  169. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/extension_template/parameters/local_town/index.yaml +0 -0
  170. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/extension_template/tests/local_benefit.yaml +0 -0
  171. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/holders/__init__.py +0 -0
  172. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/model_api.py +0 -0
  173. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/__init__.py +0 -0
  174. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/at_instant_like.py +0 -0
  175. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/config.py +0 -0
  176. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/helpers.py +0 -0
  177. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/operations/__init__.py +0 -0
  178. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/operations/get_parameter.py +0 -0
  179. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/operations/homogenize_parameters.py +0 -0
  180. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/operations/interpolate_parameters.py +0 -0
  181. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/operations/propagate_parameter_metadata.py +0 -0
  182. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/parameter.py +0 -0
  183. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/parameter_at_instant.py +0 -0
  184. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/parameter_node_at_instant.py +0 -0
  185. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/parameter_scale.py +0 -0
  186. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/parameters/vectorial_parameter_node_at_instant.py +0 -0
  187. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/periods/__init__.py +0 -0
  188. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/periods/config.py +0 -0
  189. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/periods/helpers.py +0 -0
  190. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/periods/instant_.py +0 -0
  191. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/periods/period_.py +0 -0
  192. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/populations/__init__.py +0 -0
  193. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/populations/config.py +0 -0
  194. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/populations/group_population.py +0 -0
  195. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/populations/population.py +0 -0
  196. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/projectors/__init__.py +0 -0
  197. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/projectors/entity_to_person_projector.py +0 -0
  198. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/projectors/first_person_to_entity_projector.py +0 -0
  199. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/projectors/helpers.py +0 -0
  200. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/projectors/projector.py +0 -0
  201. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/projectors/unique_role_to_entity_projector.py +0 -0
  202. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/reforms/__init__.py +0 -0
  203. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/reforms/reform.py +0 -0
  204. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/scripts/__init__.py +0 -0
  205. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/scripts/assets/__init__.py +0 -0
  206. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/scripts/assets/index.html +0 -0
  207. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/scripts/policyengine_command.py +0 -0
  208. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/scripts/run_data.py +0 -0
  209. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/scripts/run_test.py +0 -0
  210. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/scripts/simulation_generator.py +0 -0
  211. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/simulations/__init__.py +0 -0
  212. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/simulations/helpers.py +0 -0
  213. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/simulations/individual_sim.py +0 -0
  214. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/simulations/microsimulation.py +0 -0
  215. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/simulations/simulation_builder.py +0 -0
  216. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/simulations/simulation_macro_cache.py +0 -0
  217. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/taxbenefitsystems/__init__.py +0 -0
  218. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/taxbenefitsystems/tax_benefit_system.py +0 -0
  219. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/taxscales/__init__.py +0 -0
  220. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/taxscales/abstract_rate_tax_scale.py +0 -0
  221. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/taxscales/abstract_tax_scale.py +0 -0
  222. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/taxscales/amount_tax_scale_like.py +0 -0
  223. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/taxscales/helpers.py +0 -0
  224. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/taxscales/linear_average_rate_tax_scale.py +0 -0
  225. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/taxscales/marginal_amount_tax_scale.py +0 -0
  226. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/taxscales/marginal_rate_tax_scale.py +0 -0
  227. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/taxscales/rate_tax_scale_like.py +0 -0
  228. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/taxscales/single_amount_tax_scale.py +0 -0
  229. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/taxscales/tax_scale_like.py +0 -0
  230. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tools/__init__.py +0 -0
  231. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tools/google_cloud.py +0 -0
  232. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tools/hugging_face.py +0 -0
  233. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tools/simulation_dumper.py +0 -0
  234. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tools/test_from_situation.py +0 -0
  235. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tools/test_runner.py +0 -0
  236. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tools/win_file_manager.py +0 -0
  237. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tracers/__init__.py +0 -0
  238. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tracers/computation_log.py +0 -0
  239. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tracers/flat_trace.py +0 -0
  240. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tracers/full_tracer.py +0 -0
  241. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tracers/performance_log.py +0 -0
  242. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tracers/simple_tracer.py +0 -0
  243. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tracers/trace_node.py +0 -0
  244. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tracers/tracing_parameter_node_at_instant.py +0 -0
  245. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/tracers/variable_graph.py +0 -0
  246. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/types/__init__.py +0 -0
  247. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/types/data_types/__init__.py +0 -0
  248. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/types/data_types/arrays.py +0 -0
  249. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/variables/__init__.py +0 -0
  250. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/variables/config.py +0 -0
  251. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/variables/defined_for.py +0 -0
  252. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/variables/helpers.py +0 -0
  253. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/variables/typing.py +0 -0
  254. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/variables/variable.py +0 -0
  255. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/warnings/__init__.py +0 -0
  256. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/warnings/libyaml_warning.py +0 -0
  257. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/warnings/memory_config_warning.py +0 -0
  258. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/policyengine_core/warnings/tempfile_warning.py +0 -0
  259. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/pytest.ini +0 -0
  260. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/test.ipynb +0 -0
  261. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/__init__.py +0 -0
  262. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/conftest.py +0 -0
  263. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/__init__.py +0 -0
  264. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/commons/__init__.py +0 -0
  265. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/commons/test_between_function.py +0 -0
  266. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/commons/test_formulas.py +0 -0
  267. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/commons/test_is_in_function.py +0 -0
  268. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/commons/test_random_seed.py +0 -0
  269. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/commons/test_rates.py +0 -0
  270. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/data/test_dataset.py +0 -0
  271. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/enums/test_enum.py +0 -0
  272. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/model_api/test_index_.py +0 -0
  273. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/__init__.py +0 -0
  274. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/array_type.yaml +0 -0
  275. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/duplicate_key.yaml +0 -0
  276. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/filesystem_hierarchy/empty_index_file/index.yaml +0 -0
  277. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/filesystem_hierarchy/node1/param.yaml +0 -0
  278. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/indentation.yaml +0 -0
  279. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/missing_value.yaml +0 -0
  280. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/parameter_for_unit_propagation.yaml +0 -0
  281. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/test_parameter_clone.py +0 -0
  282. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/test_parameter_validation.py +0 -0
  283. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/test_propagate_units.py +0 -0
  284. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/unexpected_key_in_parameter.yaml +0 -0
  285. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/unexpected_key_in_scale.yaml +0 -0
  286. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/unexpected_key_in_value_at_instant.yaml +0 -0
  287. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/unexpected_key_in_value_history.yaml +0 -0
  288. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/wrong_date.yaml +0 -0
  289. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/wrong_scale.yaml +0 -0
  290. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/wrong_type_in_bracket.yaml +0 -0
  291. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/wrong_type_in_brackets.yaml +0 -0
  292. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/wrong_type_in_parameter.yaml +0 -0
  293. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/wrong_type_in_scale.yaml +0 -0
  294. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/wrong_type_in_value_history.yaml +0 -0
  295. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/wrong_value.yaml +0 -0
  296. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameter_validation/yaml_hierarchy/node1.yaml +0 -0
  297. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameters/operations/test_interpolation.py +0 -0
  298. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameters/operations/test_nesting.py +0 -0
  299. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameters/operations/test_propagation.py +0 -0
  300. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameters/test_numpy2_structured_arrays.py +0 -0
  301. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameters_fancy_indexing/__init__.py +0 -0
  302. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameters_fancy_indexing/bareme.yaml +0 -0
  303. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameters_fancy_indexing/local_tax.yaml +0 -0
  304. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameters_fancy_indexing/rate.yaml +0 -0
  305. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/parameters_fancy_indexing/test_fancy_indexing.py +0 -0
  306. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/tax_scales/__init__.py +0 -0
  307. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/tax_scales/test_abstract_rate_tax_scale.py +0 -0
  308. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/tax_scales/test_abstract_tax_scale.py +0 -0
  309. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/tax_scales/test_linear_average_rate_tax_scale.py +0 -0
  310. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/tax_scales/test_marginal_amount_tax_scale.py +0 -0
  311. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/tax_scales/test_marginal_rate_tax_scale.py +0 -0
  312. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/tax_scales/test_rate_tax_scale_like.py +0 -0
  313. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/tax_scales/test_single_amount_tax_scale.py +0 -0
  314. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/tax_scales/test_tax_scales_commons.py +0 -0
  315. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_apply_reform_invalidates_cache.py +0 -0
  316. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_assert_near_precision.py +0 -0
  317. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_axes.py +0 -0
  318. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_bincount_minlength.py +0 -0
  319. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_build_metadata.py +0 -0
  320. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_calculate_output.py +0 -0
  321. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_countries.py +0 -0
  322. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_cycles.py +0 -0
  323. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_dataset_getattr.py +0 -0
  324. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_dump_restore.py +0 -0
  325. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_entities.py +0 -0
  326. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_eternity_subperiods.py +0 -0
  327. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_extensions.py +0 -0
  328. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_fast_cache.py +0 -0
  329. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_fast_cache_guards.py +0 -0
  330. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_formulas.py +0 -0
  331. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_holders.py +0 -0
  332. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_macro_cache_not_singleton.py +0 -0
  333. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_medium_fixes.py +0 -0
  334. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_microsimulation_person_accessor.py +0 -0
  335. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_opt_out_cache.py +0 -0
  336. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_pandas3_compatibility.py +0 -0
  337. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_parameters.py +0 -0
  338. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_periods.py +0 -0
  339. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_projectors.py +0 -0
  340. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_reform_parameter_isolation.py +0 -0
  341. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_reforms.py +0 -0
  342. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_simulation_builder.py +0 -0
  343. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_simulations.py +0 -0
  344. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_stable_hash_seed.py +0 -0
  345. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_storage_delete_branch.py +0 -0
  346. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_subsample_invalidates_cache.py +0 -0
  347. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_tax_benefit_system_cache_identity.py +0 -0
  348. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_tracers.py +0 -0
  349. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/test_yaml.py +0 -0
  350. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/tools/__init__.py +0 -0
  351. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/tools/test_assert_near.py +0 -0
  352. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/tools/test_google_cloud.py +0 -0
  353. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/tools/test_hugging_face.py +0 -0
  354. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/tools/test_runner/test_yaml_runner.py +0 -0
  355. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/variables/test_adds.py +0 -0
  356. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/variables/test_annualize.py +0 -0
  357. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/variables/test_bounds.py +0 -0
  358. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/variables/test_defined_for.py +0 -0
  359. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/variables/test_subtracts.py +0 -0
  360. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/variables/test_subtracts_sign.py +0 -0
  361. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/core/variables/test_variables.py +0 -0
  362. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/__init__.py +0 -0
  363. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/appclient.py +0 -0
  364. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/entities.py +0 -0
  365. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/simulations.py +0 -0
  366. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/taxbenefitsystems.py +0 -0
  367. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/variables.py +0 -0
  368. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/__init__.py +0 -0
  369. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/directory/subdirectory/test_4.yaml +0 -0
  370. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/directory/test_1.yaml +0 -0
  371. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/directory/test_2.yaml +0 -0
  372. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/failing_test_absolute_error_margin.yaml +0 -0
  373. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/failing_test_relative_error_margin.yaml +0 -0
  374. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/test_absolute_error_margin.yaml +0 -0
  375. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/test_failure.yaml +0 -0
  376. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/test_name_filter.yaml +0 -0
  377. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/test_relative_error_margin.yaml +0 -0
  378. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/test_success.yml +0 -0
  379. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/test_with_anchors.yaml +0 -0
  380. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/test_with_extension.yaml +0 -0
  381. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/test_with_reform.yaml +0 -0
  382. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/fixtures/yaml_tests/test_with_reform_2.yaml +0 -0
  383. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/smoke/test_country_init.py +0 -0
  384. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/tests/smoke/test_us.py +0 -0
  385. {policyengine_core-3.26.2 → policyengine_core-3.26.3}/uv.lock +0 -0
@@ -1,3 +1,11 @@
1
+ ## [3.26.3] - 2026-05-14
2
+
3
+ ### Fixed
4
+
5
+ - Preserve values passed through dispatched `set_input` handlers across cache invalidation.
6
+ - Apply chained parameter uprating dependencies in deterministic dependency order.
7
+
8
+
1
9
  ## [3.26.2] - 2026-05-14
2
10
 
3
11
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: policyengine-core
3
- Version: 3.26.2
3
+ Version: 3.26.3
4
4
  Summary: Core microsimulation engine enabling country-specific policy models.
5
5
  Project-URL: Homepage, https://github.com/policyengine/policyengine-core
6
6
  Author-email: PolicyEngine <hello@policyengine.org>
@@ -10,6 +10,18 @@ from policyengine_core.periods import Period
10
10
  log = logging.getLogger(__name__)
11
11
 
12
12
 
13
+ def get_input_branch(holder: Holder) -> str:
14
+ simulation = getattr(holder, "simulation", None)
15
+ user_input_contexts = getattr(simulation, "_user_input_contexts", None)
16
+ if user_input_contexts:
17
+ return user_input_contexts[-1]
18
+ return "default"
19
+
20
+
21
+ def get_stored_array(holder: Holder, period: Period, branch_name: str) -> ArrayLike:
22
+ return holder._get_array_from_storage(period, branch_name)
23
+
24
+
13
25
  def set_input_dispatch_by_period(holder: Holder, period: Period, array: ArrayLike):
14
26
  """
15
27
  This function can be declared as a ``set_input`` attribute of a variable.
@@ -35,11 +47,12 @@ def set_input_dispatch_by_period(holder: Holder, period: Period, array: ArrayLik
35
47
  after_instant = period.start.offset(period_size, period_unit)
36
48
 
37
49
  # Cache the input data, skipping the existing cached months
50
+ branch_name = get_input_branch(holder)
38
51
  sub_period = period.start.period(cached_period_unit)
39
52
  while sub_period.start < after_instant:
40
- existing_array = holder.get_array(sub_period)
53
+ existing_array = get_stored_array(holder, sub_period, branch_name)
41
54
  if existing_array is None:
42
- holder._set(sub_period, array)
55
+ holder._set(sub_period, array, branch_name)
43
56
  else:
44
57
  # The array of the current sub-period is reused for the next ones.
45
58
  # TODO: refactor or document this behavior
@@ -72,11 +85,12 @@ def set_input_divide_by_period(holder: Holder, period: Period, array: ArrayLike)
72
85
  after_instant = period.start.offset(period_size, period_unit)
73
86
 
74
87
  # Count the number of elementary periods to change, and the difference with what is already known.
88
+ branch_name = get_input_branch(holder)
75
89
  remaining_array = array.copy()
76
90
  sub_period = period.start.period(cached_period_unit)
77
91
  sub_periods_count = 0
78
92
  while sub_period.start < after_instant:
79
- existing_array = holder.get_array(sub_period)
93
+ existing_array = get_stored_array(holder, sub_period, branch_name)
80
94
  if existing_array is not None:
81
95
  remaining_array -= existing_array
82
96
  else:
@@ -88,8 +102,8 @@ def set_input_divide_by_period(holder: Holder, period: Period, array: ArrayLike)
88
102
  divided_array = remaining_array / sub_periods_count
89
103
  sub_period = period.start.period(cached_period_unit)
90
104
  while sub_period.start < after_instant:
91
- if holder.get_array(sub_period) is None:
92
- holder._set(sub_period, divided_array)
105
+ if get_stored_array(holder, sub_period, branch_name) is None:
106
+ holder._set(sub_period, divided_array, branch_name)
93
107
  sub_period = sub_period.offset(1)
94
108
  elif not (remaining_array == 0).all():
95
109
  raise ValueError(
@@ -94,6 +94,14 @@ class Holder:
94
94
  if self._disk_storage:
95
95
  self._disk_storage.delete(period, branch_name)
96
96
 
97
+ def _get_array_from_storage(
98
+ self, period: Period, branch_name: str = "default"
99
+ ) -> ArrayLike:
100
+ value = self._memory_storage.get(period, branch_name)
101
+ if value is None and self._disk_storage:
102
+ value = self._disk_storage.get(period, branch_name)
103
+ return value
104
+
97
105
  def get_array(self, period: Period, branch_name: str = "default") -> ArrayLike:
98
106
  """
99
107
  Get the value of the variable for the given period.
@@ -102,7 +110,9 @@ class Holder:
102
110
  """
103
111
  if self.variable.is_neutralized:
104
112
  return self.default_array()
105
- value = self._memory_storage.get(period, branch_name)
113
+ value = self._get_array_from_storage(period, branch_name)
114
+ if value is not None:
115
+ return value
106
116
  if value is None and branch_name != "default":
107
117
  # Walk up ``simulation.parent_branch`` so nested branches inherit
108
118
  # values from their parent (e.g. a ``no_salt`` branch cloned
@@ -121,17 +131,16 @@ class Holder:
121
131
  else None
122
132
  )
123
133
  while parent is not None:
124
- ancestor_value = self._memory_storage.get(period, parent.branch_name)
134
+ ancestor_value = self._get_array_from_storage(
135
+ period,
136
+ parent.branch_name,
137
+ )
125
138
  if ancestor_value is not None:
126
139
  return ancestor_value
127
140
  parent = getattr(parent, "parent_branch", None)
128
- default_value = self._memory_storage.get(period, "default")
141
+ default_value = self._get_array_from_storage(period, "default")
129
142
  if default_value is not None:
130
143
  return default_value
131
- if value is not None:
132
- return value
133
- if self._disk_storage:
134
- return self._disk_storage.get(period, branch_name)
135
144
 
136
145
  def get_memory_usage(self) -> dict:
137
146
  """
@@ -241,21 +250,23 @@ class Holder:
241
250
  return warnings.warn(warning_message, Warning)
242
251
  if self.variable.value_type in (float, int) and isinstance(array, str):
243
252
  array = tools.eval_expression(array)
244
- # Track user-provided inputs on the simulation so
245
- # ``Simulation._invalidate_all_caches`` can preserve them across
246
- # ``apply_reform``. ``Simulation.set_input`` also records this, but
247
- # ``SimulationBuilder.finalize_variables_init`` (the situation-dict
248
- # path) and country-package dataset loaders call
249
- # ``holder.set_input`` directly, bypassing the simulation-level hook.
250
- # Recording here covers both paths.
251
253
  simulation = getattr(self, "simulation", None)
252
254
  if simulation is not None:
253
255
  if not hasattr(simulation, "_user_input_keys"):
254
256
  simulation._user_input_keys = set()
255
- simulation._user_input_keys.add((self.variable.name, branch_name, period))
256
- if self.variable.set_input and period.unit != self.variable.definition_period:
257
- return self.variable.set_input(self, period, array)
258
- return self._set(period, array, branch_name)
257
+ if not hasattr(simulation, "_user_input_contexts"):
258
+ simulation._user_input_contexts = []
259
+ simulation._user_input_contexts.append(branch_name)
260
+ try:
261
+ if (
262
+ self.variable.set_input
263
+ and period.unit != self.variable.definition_period
264
+ ):
265
+ return self.variable.set_input(self, period, array)
266
+ return self._set(period, array, branch_name)
267
+ finally:
268
+ if simulation is not None:
269
+ simulation._user_input_contexts.pop()
259
270
 
260
271
  def _to_array(self, value: Any) -> ArrayLike:
261
272
  if not isinstance(value, numpy.ndarray):
@@ -295,6 +306,10 @@ class Holder:
295
306
  def _set(
296
307
  self, period: Period, value: ArrayLike, branch_name: str = "default"
297
308
  ) -> None:
309
+ simulation = getattr(self, "simulation", None)
310
+ user_input_contexts = getattr(simulation, "_user_input_contexts", None)
311
+ if user_input_contexts and branch_name == "default":
312
+ branch_name = user_input_contexts[-1]
298
313
  value = self._to_array(value)
299
314
  if self.variable.definition_period != periods.ETERNITY:
300
315
  if period is None:
@@ -313,6 +328,10 @@ class Holder:
313
328
  self._disk_storage.put(value, period, branch_name)
314
329
  else:
315
330
  self._memory_storage.put(value, period, branch_name)
331
+ if user_input_contexts:
332
+ if not hasattr(simulation, "_user_input_keys"):
333
+ simulation._user_input_keys = set()
334
+ simulation._user_input_keys.add((self.variable.name, branch_name, period))
316
335
 
317
336
  def put_in_cache(
318
337
  self, value: ArrayLike, period: Period, branch_name: str = "default"
@@ -6,6 +6,7 @@ from dateutil import rrule
6
6
  from dateutil.relativedelta import relativedelta
7
7
  from dateutil.parser import parse
8
8
  from datetime import datetime
9
+ from typing import Optional, Union
9
10
 
10
11
  from policyengine_core.parameters.operations.get_parameter import get_parameter
11
12
  from policyengine_core.parameters.parameter import Parameter
@@ -13,8 +14,7 @@ from policyengine_core.parameters.parameter_at_instant import (
13
14
  ParameterAtInstant,
14
15
  )
15
16
  from policyengine_core.parameters.parameter_node import ParameterNode
16
- from policyengine_core.parameters.parameter_scale import ParameterScale
17
- from policyengine_core.periods import instant, Instant
17
+ from policyengine_core.periods import instant
18
18
 
19
19
 
20
20
  def uprate_parameters(root: ParameterNode) -> ParameterNode:
@@ -27,135 +27,179 @@ def uprate_parameters(root: ParameterNode) -> ParameterNode:
27
27
  ParameterNode: The same root, with uprating applied to descendants.
28
28
  """
29
29
 
30
- descendants = list(root.get_descendants())
31
-
32
- scales = list(filter(lambda p: isinstance(p, ParameterScale), descendants))
33
- for scale in scales:
34
- for bracket in scale.brackets:
35
- for allowed_key in bracket._allowed_keys:
36
- if hasattr(bracket, allowed_key):
37
- descendants.append(getattr(bracket, allowed_key))
38
-
39
- for parameter in descendants:
40
- if isinstance(parameter, Parameter):
41
- if parameter.metadata.get("uprating") is not None:
42
- # Pull the uprating definition dict
43
- meta = parameter.metadata["uprating"]
44
-
45
- # If defined in short method (i.e. "uprating: PARAM"),
46
- # redefine this as dict with param key
47
- if meta == "self":
48
- meta = dict(parameter="self")
49
- elif isinstance(meta, str):
50
- meta = dict(parameter=meta)
51
-
52
- # If param is "self", construct the uprating table
53
- if meta["parameter"] == "self":
54
- uprating_parameter = construct_uprater_self(
55
- parameter,
56
- meta,
57
- )
58
- # Otherwise, pull uprating table from YAML
59
- else:
60
- uprating_parameter = get_parameter(root, meta["parameter"])
61
-
62
- # If uprating with a set candence, ensure that all
63
- # required values are present
64
- cadence_meta = meta.get("at_defined_interval")
65
- cadence_options = {}
66
- if cadence_meta:
67
- cadence_options_test = [
68
- cadence_meta.get("start"),
69
- cadence_meta.get("end"),
70
- cadence_meta.get("enactment"),
71
- ]
72
-
73
- # Ensure that all options are properly defined
74
- if not all(cadence_options_test):
75
- raise SyntaxError(
76
- f"Failed to uprate {parameter.name} using cadence; start, end, and enactment must all be provided"
77
- )
78
-
79
- # Construct cadence options object
80
- cadence_options = construct_cadence_options(cadence_meta, parameter)
81
-
82
- # Ensure that end comes after start and enactment comes after end
83
- if cadence_options["end"] <= cadence_options["start"]:
84
- raise ValueError(
85
- f"Failed to uprate {parameter.name} using {uprating_parameter.name}: end must come after start"
86
- )
87
- if cadence_options["enactment"] <= cadence_options["end"]:
88
- raise ValueError(
89
- f"Failed to uprate {parameter.name} using {uprating_parameter.name}: enactment must come after end"
90
- )
91
-
92
- # Determine the first date from which to start uprating -
93
- # this should be the first application date (month, day)
94
- # following the last defined param value (not including the
95
- # final value)
96
- uprating_first_date: datetime = find_cadence_first(
97
- parameter, cadence_options
98
- )
99
- uprating_last_date: datetime = find_cadence_last(
100
- uprating_parameter, cadence_options
101
- )
102
-
103
- # Uprate data
104
- uprated_data = uprate_by_cadence(
105
- parameter,
106
- uprating_parameter,
107
- cadence_options,
108
- uprating_first_date,
109
- uprating_last_date,
110
- meta,
111
- )
30
+ parameters = [
31
+ parameter
32
+ for parameter in root.get_descendants()
33
+ if isinstance(parameter, Parameter)
34
+ ]
112
35
 
113
- # Append uprated data to parameter values list
114
- parameter.values_list.extend(uprated_data)
115
-
116
- else:
117
- # Start from the latest value
118
- if "start_instant" in meta:
119
- last_instant = instant(meta["start_instant"])
120
- else:
121
- last_instant = instant(parameter.values_list[0].instant_str)
122
-
123
- # Pre-compute values that don't change in the loop
124
- last_instant_str = str(last_instant)
125
- value_at_start = parameter(last_instant)
126
- uprater_at_start = uprating_parameter(last_instant)
127
-
128
- if uprater_at_start is None:
129
- raise ValueError(
130
- f"Failed to uprate using {uprating_parameter.name} at {last_instant} for {parameter.name} because the uprating parameter is not defined at {last_instant}."
131
- )
132
-
133
- # Pre-compute uprater values for all entries to avoid repeated lookups
134
- has_rounding = "rounding" in meta
135
-
136
- # For each defined instant in the uprating parameter
137
- for entry in uprating_parameter.values_list[::-1]:
138
- entry_instant = instant(entry.instant_str)
139
- # If the uprater instant is defined after the last parameter instant
140
- if entry_instant > last_instant:
141
- # Apply the uprater and add to the parameter
142
- uprater_at_entry = uprating_parameter(entry_instant)
143
- uprater_change = uprater_at_entry / uprater_at_start
144
- uprated_value = value_at_start * uprater_change
145
- if has_rounding:
146
- uprated_value = round_uprated_value(meta, uprated_value)
147
- parameter.values_list.append(
148
- ParameterAtInstant(
149
- parameter.name,
150
- entry.instant_str,
151
- data=uprated_value,
152
- )
153
- )
154
- # Whether using cadence or not, sort the parameter values_list
155
- parameter.values_list.sort(key=lambda x: x.instant_str, reverse=True)
36
+ for parameter in sort_parameters_by_uprating_dependencies(parameters):
37
+ uprate_parameter(parameter, root)
156
38
  return root
157
39
 
158
40
 
41
+ def normalize_uprating_metadata(meta: Union[dict, str]) -> dict:
42
+ if meta == "self":
43
+ return dict(parameter="self")
44
+ if isinstance(meta, str):
45
+ return dict(parameter=meta)
46
+ return meta
47
+
48
+
49
+ def get_uprating_dependency_name(parameter: Parameter) -> Optional[str]:
50
+ meta = parameter.metadata.get("uprating")
51
+ if meta is None:
52
+ return None
53
+ meta = normalize_uprating_metadata(meta)
54
+ dependency_name = meta["parameter"]
55
+ if dependency_name == "self":
56
+ return None
57
+ return dependency_name
58
+
59
+
60
+ def sort_parameters_by_uprating_dependencies(
61
+ parameters: list[Parameter],
62
+ ) -> list[Parameter]:
63
+ parameters_to_uprate = [
64
+ parameter
65
+ for parameter in parameters
66
+ if parameter.metadata.get("uprating") is not None
67
+ ]
68
+ parameter_by_name = {
69
+ parameter.name: parameter for parameter in parameters_to_uprate
70
+ }
71
+ ordered_parameters = []
72
+ visited = set()
73
+ visiting = []
74
+
75
+ def visit(parameter: Parameter):
76
+ if parameter.name in visited:
77
+ return
78
+ if parameter.name in visiting:
79
+ cycle = visiting[visiting.index(parameter.name) :] + [parameter.name]
80
+ raise ValueError(
81
+ "Cyclic uprating dependency detected: " + " -> ".join(cycle)
82
+ )
83
+ visiting.append(parameter.name)
84
+ dependency_name = get_uprating_dependency_name(parameter)
85
+ if dependency_name in parameter_by_name:
86
+ visit(parameter_by_name[dependency_name])
87
+ visiting.pop()
88
+ visited.add(parameter.name)
89
+ ordered_parameters.append(parameter)
90
+
91
+ for parameter in sorted(parameters_to_uprate, key=lambda p: p.name):
92
+ visit(parameter)
93
+
94
+ return ordered_parameters
95
+
96
+
97
+ def uprate_parameter(parameter: Parameter, root: ParameterNode) -> None:
98
+ # Pull the uprating definition dict
99
+ meta = normalize_uprating_metadata(parameter.metadata["uprating"])
100
+
101
+ # If param is "self", construct the uprating table
102
+ if meta["parameter"] == "self":
103
+ uprating_parameter = construct_uprater_self(
104
+ parameter,
105
+ meta,
106
+ )
107
+ # Otherwise, pull uprating table from YAML
108
+ else:
109
+ uprating_parameter = get_parameter(root, meta["parameter"])
110
+
111
+ # If uprating with a set candence, ensure that all
112
+ # required values are present
113
+ cadence_meta = meta.get("at_defined_interval")
114
+ cadence_options = {}
115
+ if cadence_meta:
116
+ cadence_options_test = [
117
+ cadence_meta.get("start"),
118
+ cadence_meta.get("end"),
119
+ cadence_meta.get("enactment"),
120
+ ]
121
+
122
+ # Ensure that all options are properly defined
123
+ if not all(cadence_options_test):
124
+ raise SyntaxError(
125
+ f"Failed to uprate {parameter.name} using cadence; start, end, and enactment must all be provided"
126
+ )
127
+
128
+ # Construct cadence options object
129
+ cadence_options = construct_cadence_options(cadence_meta, parameter)
130
+
131
+ # Ensure that end comes after start and enactment comes after end
132
+ if cadence_options["end"] <= cadence_options["start"]:
133
+ raise ValueError(
134
+ f"Failed to uprate {parameter.name} using {uprating_parameter.name}: end must come after start"
135
+ )
136
+ if cadence_options["enactment"] <= cadence_options["end"]:
137
+ raise ValueError(
138
+ f"Failed to uprate {parameter.name} using {uprating_parameter.name}: enactment must come after end"
139
+ )
140
+
141
+ # Determine the first date from which to start uprating -
142
+ # this should be the first application date (month, day)
143
+ # following the last defined param value (not including the
144
+ # final value)
145
+ uprating_first_date: datetime = find_cadence_first(parameter, cadence_options)
146
+ uprating_last_date: datetime = find_cadence_last(
147
+ uprating_parameter, cadence_options
148
+ )
149
+
150
+ # Uprate data
151
+ uprated_data = uprate_by_cadence(
152
+ parameter,
153
+ uprating_parameter,
154
+ cadence_options,
155
+ uprating_first_date,
156
+ uprating_last_date,
157
+ meta,
158
+ )
159
+
160
+ # Append uprated data to parameter values list
161
+ parameter.values_list.extend(uprated_data)
162
+
163
+ else:
164
+ # Start from the latest value
165
+ if "start_instant" in meta:
166
+ last_instant = instant(meta["start_instant"])
167
+ else:
168
+ last_instant = instant(parameter.values_list[0].instant_str)
169
+
170
+ # Pre-compute values that don't change in the loop
171
+ value_at_start = parameter(last_instant)
172
+ uprater_at_start = uprating_parameter(last_instant)
173
+
174
+ if uprater_at_start is None:
175
+ raise ValueError(
176
+ f"Failed to uprate using {uprating_parameter.name} at {last_instant} for {parameter.name} because the uprating parameter is not defined at {last_instant}."
177
+ )
178
+
179
+ has_rounding = "rounding" in meta
180
+
181
+ # For each defined instant in the uprating parameter
182
+ for entry in uprating_parameter.values_list[::-1]:
183
+ entry_instant = instant(entry.instant_str)
184
+ # If the uprater instant is defined after the last parameter instant
185
+ if entry_instant > last_instant:
186
+ # Apply the uprater and add to the parameter
187
+ uprater_at_entry = uprating_parameter(entry_instant)
188
+ uprater_change = uprater_at_entry / uprater_at_start
189
+ uprated_value = value_at_start * uprater_change
190
+ if has_rounding:
191
+ uprated_value = round_uprated_value(meta, uprated_value)
192
+ parameter.values_list.append(
193
+ ParameterAtInstant(
194
+ parameter.name,
195
+ entry.instant_str,
196
+ data=uprated_value,
197
+ )
198
+ )
199
+ # Whether using cadence or not, sort the parameter values_list
200
+ parameter.values_list.sort(key=lambda x: x.instant_str, reverse=True)
201
+
202
+
159
203
  def round_uprated_value(meta: dict, uprated_value: float) -> float:
160
204
  rounding_config = meta["rounding"]
161
205
  if isinstance(rounding_config, float):
@@ -89,7 +89,7 @@ class ParameterNode(AtInstantLike):
89
89
 
90
90
  if directory_path:
91
91
  self.file_path = directory_path
92
- for child_name in os.listdir(directory_path):
92
+ for child_name in sorted(os.listdir(directory_path)):
93
93
  child_path = os.path.join(directory_path, child_name)
94
94
  if os.path.isfile(child_path):
95
95
  child_name, ext = os.path.splitext(child_name)
@@ -7,7 +7,7 @@ class ParameterScaleBracket(ParameterNode):
7
7
  A parameter scale bracket.
8
8
  """
9
9
 
10
- _allowed_keys = set(["amount", "threshold", "rate", "average_rate", "base"])
10
+ _allowed_keys = ("amount", "threshold", "rate", "average_rate", "base")
11
11
 
12
12
  @staticmethod
13
13
  def allowed_unit_keys():
@@ -1,7 +1,7 @@
1
1
  import hashlib
2
2
  import tempfile
3
3
  from dataclasses import dataclass
4
- from typing import TYPE_CHECKING, Any, Dict, List, Type, Union
4
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, Union
5
5
 
6
6
  import numpy as np
7
7
  import pandas as pd
@@ -64,6 +64,10 @@ class PreservedUserInput:
64
64
  branch_name: str
65
65
  period: Period
66
66
  value: object
67
+ storage: str
68
+ disk_key: Optional[str] = None
69
+ disk_file: Optional[str] = None
70
+ disk_enum: object = None
67
71
 
68
72
 
69
73
  class Simulation:
@@ -297,8 +301,31 @@ class Simulation:
297
301
  branch_name=branch_name,
298
302
  period=period,
299
303
  value=stored_value,
304
+ storage="memory",
300
305
  )
301
306
  )
307
+ continue
308
+ if holder._disk_storage is not None:
309
+ disk_period = (
310
+ periods.period(periods.ETERNITY)
311
+ if holder._disk_storage.is_eternal
312
+ else periods.period(period)
313
+ )
314
+ disk_key = f"{branch_name}_{disk_period}"
315
+ disk_file = holder._disk_storage._files.get(disk_key)
316
+ if disk_file is not None:
317
+ preserved.append(
318
+ PreservedUserInput(
319
+ variable_name=variable_name,
320
+ branch_name=branch_name,
321
+ period=period,
322
+ value=None,
323
+ storage="disk",
324
+ disk_key=disk_key,
325
+ disk_file=disk_file,
326
+ disk_enum=holder._disk_storage._enums.get(disk_file),
327
+ )
328
+ )
302
329
  # Iterate only over holders that already exist on each population —
303
330
  # lazy-creating a holder for every variable in the tax-benefit
304
331
  # system (thousands in policyengine-us) inflated the cost of
@@ -313,11 +340,18 @@ class Simulation:
313
340
  # Replay preserved user inputs so ``calculate`` still sees them.
314
341
  for user_input in preserved:
315
342
  holder = self.get_holder(user_input.variable_name)
316
- holder._memory_storage.put(
317
- user_input.value,
318
- user_input.period,
319
- user_input.branch_name,
320
- )
343
+ if user_input.storage == "disk" and holder._disk_storage is not None:
344
+ holder._disk_storage._files[user_input.disk_key] = user_input.disk_file
345
+ if user_input.disk_enum is not None:
346
+ holder._disk_storage._enums[user_input.disk_file] = (
347
+ user_input.disk_enum
348
+ )
349
+ else:
350
+ holder._memory_storage.put(
351
+ user_input.value,
352
+ user_input.period,
353
+ user_input.branch_name,
354
+ )
321
355
  for branch in self.branches.values():
322
356
  branch._invalidate_all_caches()
323
357
 
@@ -1302,12 +1336,6 @@ class Simulation:
1302
1336
  if (variable.end is not None) and (period.start.date > variable.end):
1303
1337
  return
1304
1338
  self.get_holder(variable_name).set_input(period, value, self.branch_name)
1305
- # Lazy-init ``_user_input_keys`` so country-package subclasses that
1306
- # override ``__init__`` without calling ``super().__init__`` still
1307
- # benefit from the set-input preservation across ``apply_reform``.
1308
- if not hasattr(self, "_user_input_keys"):
1309
- self._user_input_keys = set()
1310
- self._user_input_keys.add((variable_name, self.branch_name, period))
1311
1339
  _fast_cache = getattr(self, "_fast_cache", None)
1312
1340
  if _fast_cache is not None:
1313
1341
  _fast_cache.pop((variable_name, period), None)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "policyengine-core"
3
- version = "3.26.2"
3
+ version = "3.26.3"
4
4
  description = "Core microsimulation engine enabling country-specific policy models."
5
5
  readme = "README.md"
6
6
  authors = [