policyengine-core 3.26.3__tar.gz → 3.26.4__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 (386) hide show
  1. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/CHANGELOG.md +7 -0
  2. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/PKG-INFO +1 -1
  3. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_structures/parameter_node_metadata.py +2 -2
  4. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/config.py +24 -9
  5. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/homogenize_parameters.py +90 -2
  6. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/test_runner.py +16 -3
  7. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/pyproject.toml +1 -1
  8. policyengine_core-3.26.4/tests/core/test_parameter_security.py +130 -0
  9. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tools/test_runner/test_yaml_runner.py +107 -0
  10. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/ISSUE_TEMPLATE.md +0 -0
  11. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  12. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/bump_version.py +0 -0
  13. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/changelog_template.md +0 -0
  14. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/get-changelog-diff.sh +0 -0
  15. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/has-functional-changes.sh +0 -0
  16. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/is-version-number-acceptable.sh +0 -0
  17. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/publish-git-tag.sh +0 -0
  18. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/workflows/pr.yaml +0 -0
  19. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/workflows/push.yaml +0 -0
  20. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.gitignore +0 -0
  21. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.python-version +0 -0
  22. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/AGENTS.md +0 -0
  23. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/CLAUDE.md +0 -0
  24. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/CONTRIBUTING.md +0 -0
  25. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/LICENSE +0 -0
  26. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/MANIFEST.in +0 -0
  27. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/Makefile +0 -0
  28. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/README.md +0 -0
  29. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/_build/logs/myst.build.json +0 -0
  30. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/changelog.d/.gitkeep +0 -0
  31. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/_config.yml +0 -0
  32. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/_static/style.css +0 -0
  33. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/_toc.yml +0 -0
  34. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/add_plotly_to_book.py +0 -0
  35. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/contributing/intro.md +0 -0
  36. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/engineering/skills/README.md +0 -0
  37. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/engineering/skills/documentation_review.md +0 -0
  38. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/engineering/skills/github-prs.md +0 -0
  39. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/engineering/skills/testing.md +0 -0
  40. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/intro.md +0 -0
  41. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/logo.png +0 -0
  42. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/commons.md +0 -0
  43. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/country_template.md +0 -0
  44. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/data.md +0 -0
  45. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/data_storage.md +0 -0
  46. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/entities.md +0 -0
  47. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/enums.md +0 -0
  48. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/errors.md +0 -0
  49. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/experimental.md +0 -0
  50. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/extension_template.md +0 -0
  51. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/holders.md +0 -0
  52. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/parameters.md +0 -0
  53. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/periods.md +0 -0
  54. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/populations.md +0 -0
  55. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/projectors.md +0 -0
  56. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/reforms.md +0 -0
  57. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/scripts.md +0 -0
  58. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/simulations.md +0 -0
  59. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/taxbenefitsystems.md +0 -0
  60. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/taxscales.md +0 -0
  61. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/tools.md +0 -0
  62. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/tracers.md +0 -0
  63. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/types.md +0 -0
  64. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/variables.md +0 -0
  65. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/warnings.md +0 -0
  66. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/usage/country.ipynb +0 -0
  67. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/usage/datasets.ipynb +0 -0
  68. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/usage/parameters.md +0 -0
  69. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/usage/reforms.ipynb +0 -0
  70. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/usage/simulation.ipynb +0 -0
  71. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/mypy.ini +0 -0
  72. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/__init__.py +0 -0
  73. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/build_metadata.py +0 -0
  74. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/charts/__init__.py +0 -0
  75. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/charts/api.py +0 -0
  76. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/charts/bar.py +0 -0
  77. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/charts/formatting.py +0 -0
  78. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/commons/__init__.py +0 -0
  79. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/commons/formulas.py +0 -0
  80. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/commons/misc.py +0 -0
  81. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/commons/rates.py +0 -0
  82. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/__init__.py +0 -0
  83. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/constants.py +0 -0
  84. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/data/__init__.py +0 -0
  85. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/data/datasets/__init__.py +0 -0
  86. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/data/datasets/country_template_dataset.py +0 -0
  87. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/entities.py +0 -0
  88. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/modelled_policies.yaml +0 -0
  89. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/basic_income.yaml +0 -0
  90. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/housing_allowance.yaml +0 -0
  91. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/index.yaml +0 -0
  92. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/parenting_allowance/amount.yaml +0 -0
  93. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/parenting_allowance/income_threshold.yaml +0 -0
  94. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/general/age_of_majority.yaml +0 -0
  95. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/general/age_of_retirement.yaml +0 -0
  96. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/taxes/housing_tax.yaml +0 -0
  97. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/taxes/income_tax_rate.yaml +0 -0
  98. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/taxes/social_security_contribution.yaml +0 -0
  99. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/__init__.py +0 -0
  100. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/add_dynamic_variable.py +0 -0
  101. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/add_new_tax.py +0 -0
  102. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/flat_social_security_contribution.py +0 -0
  103. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/modify_social_security_taxation.py +0 -0
  104. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/removal_basic_income.py +0 -0
  105. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/situation_examples/__init__.py +0 -0
  106. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/situation_examples/couple.json +0 -0
  107. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/situation_examples/housing.json +0 -0
  108. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/situation_examples/single.json +0 -0
  109. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/age.yaml +0 -0
  110. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/basic_income.yaml +0 -0
  111. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/disposable_income.yaml +0 -0
  112. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/housing_allowance.yaml +0 -0
  113. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/housing_tax.yaml +0 -0
  114. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/income_tax.yaml +0 -0
  115. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/reforms/add_dynamic_variable.yaml +0 -0
  116. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/reforms/add_new_tax.yaml +0 -0
  117. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/reforms/modify_social_security_taxation.yaml +0 -0
  118. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/situations/income_tax.yaml +0 -0
  119. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/situations/parenting_allowance.yaml +0 -0
  120. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/social_security_contribution.yaml +0 -0
  121. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/test_microsimulation.py +0 -0
  122. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/__init__.py +0 -0
  123. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/benefits.py +0 -0
  124. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/demographics.py +0 -0
  125. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/housing.py +0 -0
  126. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/ids.py +0 -0
  127. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/income.py +0 -0
  128. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/stats.py +0 -0
  129. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/taxes.py +0 -0
  130. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data/__init__.py +0 -0
  131. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data/dataset.py +0 -0
  132. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_storage/__init__.py +0 -0
  133. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_storage/in_memory_storage.py +0 -0
  134. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_storage/on_disk_storage.py +0 -0
  135. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_structures/__init__.py +0 -0
  136. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_structures/parameter_metadata.py +0 -0
  137. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_structures/reference.py +0 -0
  138. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_structures/unit.py +0 -0
  139. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/entities/__init__.py +0 -0
  140. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/entities/entity.py +0 -0
  141. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/entities/group_entity.py +0 -0
  142. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/entities/helpers.py +0 -0
  143. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/entities/role.py +0 -0
  144. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/enums/__init__.py +0 -0
  145. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/enums/config.py +0 -0
  146. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/enums/enum.py +0 -0
  147. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/enums/enum_array.py +0 -0
  148. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/__init__.py +0 -0
  149. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/cycle_error.py +0 -0
  150. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/empty_argument_error.py +0 -0
  151. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/nan_creation_error.py +0 -0
  152. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/parameter_not_found_error.py +0 -0
  153. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/parameter_parsing_error.py +0 -0
  154. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/period_mismatch_error.py +0 -0
  155. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/situation_parsing_error.py +0 -0
  156. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/spiral_error.py +0 -0
  157. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/variable_name_conflict_error.py +0 -0
  158. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/variable_not_found_error.py +0 -0
  159. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/experimental/__init__.py +0 -0
  160. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/experimental/memory_config.py +0 -0
  161. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/extension_template/__init__.py +0 -0
  162. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/extension_template/local_benefit.py +0 -0
  163. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/extension_template/parameters/local_town/child_allowance/amount.yaml +0 -0
  164. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/extension_template/parameters/local_town/child_allowance/index.yaml +0 -0
  165. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/extension_template/parameters/local_town/index.yaml +0 -0
  166. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/extension_template/tests/local_benefit.yaml +0 -0
  167. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/holders/__init__.py +0 -0
  168. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/holders/helpers.py +0 -0
  169. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/holders/holder.py +0 -0
  170. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/model_api.py +0 -0
  171. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/__init__.py +0 -0
  172. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/at_instant_like.py +0 -0
  173. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/helpers.py +0 -0
  174. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/__init__.py +0 -0
  175. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/get_parameter.py +0 -0
  176. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/interpolate_parameters.py +0 -0
  177. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/propagate_parameter_metadata.py +0 -0
  178. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/uprate_parameters.py +0 -0
  179. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter.py +0 -0
  180. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_at_instant.py +0 -0
  181. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_node.py +0 -0
  182. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_node_at_instant.py +0 -0
  183. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_scale.py +0 -0
  184. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_scale_bracket.py +0 -0
  185. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/vectorial_parameter_node_at_instant.py +0 -0
  186. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/periods/__init__.py +0 -0
  187. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/periods/config.py +0 -0
  188. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/periods/helpers.py +0 -0
  189. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/periods/instant_.py +0 -0
  190. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/periods/period_.py +0 -0
  191. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/populations/__init__.py +0 -0
  192. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/populations/config.py +0 -0
  193. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/populations/group_population.py +0 -0
  194. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/populations/population.py +0 -0
  195. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/projectors/__init__.py +0 -0
  196. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/projectors/entity_to_person_projector.py +0 -0
  197. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/projectors/first_person_to_entity_projector.py +0 -0
  198. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/projectors/helpers.py +0 -0
  199. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/projectors/projector.py +0 -0
  200. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/projectors/unique_role_to_entity_projector.py +0 -0
  201. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/reforms/__init__.py +0 -0
  202. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/reforms/reform.py +0 -0
  203. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/scripts/__init__.py +0 -0
  204. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/scripts/assets/__init__.py +0 -0
  205. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/scripts/assets/index.html +0 -0
  206. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/scripts/policyengine_command.py +0 -0
  207. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/scripts/run_data.py +0 -0
  208. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/scripts/run_test.py +0 -0
  209. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/scripts/simulation_generator.py +0 -0
  210. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/simulations/__init__.py +0 -0
  211. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/simulations/helpers.py +0 -0
  212. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/simulations/individual_sim.py +0 -0
  213. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/simulations/microsimulation.py +0 -0
  214. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/simulations/simulation.py +0 -0
  215. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/simulations/simulation_builder.py +0 -0
  216. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/simulations/simulation_macro_cache.py +0 -0
  217. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxbenefitsystems/__init__.py +0 -0
  218. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxbenefitsystems/tax_benefit_system.py +0 -0
  219. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/__init__.py +0 -0
  220. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/abstract_rate_tax_scale.py +0 -0
  221. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/abstract_tax_scale.py +0 -0
  222. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/amount_tax_scale_like.py +0 -0
  223. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/helpers.py +0 -0
  224. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/linear_average_rate_tax_scale.py +0 -0
  225. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/marginal_amount_tax_scale.py +0 -0
  226. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/marginal_rate_tax_scale.py +0 -0
  227. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/rate_tax_scale_like.py +0 -0
  228. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/single_amount_tax_scale.py +0 -0
  229. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/tax_scale_like.py +0 -0
  230. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/__init__.py +0 -0
  231. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/google_cloud.py +0 -0
  232. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/hugging_face.py +0 -0
  233. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/simulation_dumper.py +0 -0
  234. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/test_from_situation.py +0 -0
  235. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/win_file_manager.py +0 -0
  236. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/__init__.py +0 -0
  237. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/computation_log.py +0 -0
  238. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/flat_trace.py +0 -0
  239. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/full_tracer.py +0 -0
  240. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/performance_log.py +0 -0
  241. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/simple_tracer.py +0 -0
  242. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/trace_node.py +0 -0
  243. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/tracing_parameter_node_at_instant.py +0 -0
  244. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/variable_graph.py +0 -0
  245. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/types/__init__.py +0 -0
  246. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/types/data_types/__init__.py +0 -0
  247. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/types/data_types/arrays.py +0 -0
  248. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/variables/__init__.py +0 -0
  249. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/variables/config.py +0 -0
  250. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/variables/defined_for.py +0 -0
  251. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/variables/helpers.py +0 -0
  252. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/variables/typing.py +0 -0
  253. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/variables/variable.py +0 -0
  254. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/warnings/__init__.py +0 -0
  255. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/warnings/libyaml_warning.py +0 -0
  256. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/warnings/memory_config_warning.py +0 -0
  257. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/warnings/tempfile_warning.py +0 -0
  258. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/pytest.ini +0 -0
  259. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/test.ipynb +0 -0
  260. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/__init__.py +0 -0
  261. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/conftest.py +0 -0
  262. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/__init__.py +0 -0
  263. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/commons/__init__.py +0 -0
  264. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/commons/test_between_function.py +0 -0
  265. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/commons/test_formulas.py +0 -0
  266. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/commons/test_is_in_function.py +0 -0
  267. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/commons/test_random_seed.py +0 -0
  268. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/commons/test_rates.py +0 -0
  269. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/data/test_dataset.py +0 -0
  270. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/enums/test_enum.py +0 -0
  271. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/model_api/test_index_.py +0 -0
  272. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/__init__.py +0 -0
  273. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/array_type.yaml +0 -0
  274. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/duplicate_key.yaml +0 -0
  275. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/filesystem_hierarchy/empty_index_file/index.yaml +0 -0
  276. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/filesystem_hierarchy/node1/param.yaml +0 -0
  277. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/indentation.yaml +0 -0
  278. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/missing_value.yaml +0 -0
  279. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/parameter_for_unit_propagation.yaml +0 -0
  280. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/test_parameter_clone.py +0 -0
  281. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/test_parameter_validation.py +0 -0
  282. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/test_propagate_units.py +0 -0
  283. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/unexpected_key_in_parameter.yaml +0 -0
  284. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/unexpected_key_in_scale.yaml +0 -0
  285. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/unexpected_key_in_value_at_instant.yaml +0 -0
  286. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/unexpected_key_in_value_history.yaml +0 -0
  287. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_date.yaml +0 -0
  288. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_scale.yaml +0 -0
  289. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_bracket.yaml +0 -0
  290. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_brackets.yaml +0 -0
  291. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_parameter.yaml +0 -0
  292. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_scale.yaml +0 -0
  293. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_value_history.yaml +0 -0
  294. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_value.yaml +0 -0
  295. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/yaml_hierarchy/node1.yaml +0 -0
  296. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters/operations/test_interpolation.py +0 -0
  297. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters/operations/test_nesting.py +0 -0
  298. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters/operations/test_propagation.py +0 -0
  299. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters/operations/test_uprating.py +0 -0
  300. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters/test_numpy2_structured_arrays.py +0 -0
  301. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/__init__.py +0 -0
  302. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/bareme.yaml +0 -0
  303. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/local_tax.yaml +0 -0
  304. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/rate.yaml +0 -0
  305. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/test_fancy_indexing.py +0 -0
  306. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/__init__.py +0 -0
  307. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_abstract_rate_tax_scale.py +0 -0
  308. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_abstract_tax_scale.py +0 -0
  309. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_linear_average_rate_tax_scale.py +0 -0
  310. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_marginal_amount_tax_scale.py +0 -0
  311. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_marginal_rate_tax_scale.py +0 -0
  312. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_rate_tax_scale_like.py +0 -0
  313. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_single_amount_tax_scale.py +0 -0
  314. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_tax_scales_commons.py +0 -0
  315. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_apply_reform_invalidates_cache.py +0 -0
  316. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_apply_reform_preserves_user_inputs.py +0 -0
  317. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_assert_near_precision.py +0 -0
  318. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_axes.py +0 -0
  319. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_bincount_minlength.py +0 -0
  320. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_build_metadata.py +0 -0
  321. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_calculate_output.py +0 -0
  322. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_countries.py +0 -0
  323. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_cycles.py +0 -0
  324. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_dataset_getattr.py +0 -0
  325. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_dump_restore.py +0 -0
  326. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_entities.py +0 -0
  327. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_eternity_subperiods.py +0 -0
  328. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_extensions.py +0 -0
  329. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_fast_cache.py +0 -0
  330. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_fast_cache_guards.py +0 -0
  331. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_formulas.py +0 -0
  332. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_holder_branch_fallback.py +0 -0
  333. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_holders.py +0 -0
  334. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_macro_cache_not_singleton.py +0 -0
  335. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_medium_fixes.py +0 -0
  336. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_microsimulation_person_accessor.py +0 -0
  337. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_opt_out_cache.py +0 -0
  338. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_pandas3_compatibility.py +0 -0
  339. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_parameters.py +0 -0
  340. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_periods.py +0 -0
  341. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_projectors.py +0 -0
  342. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_reform_parameter_isolation.py +0 -0
  343. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_reforms.py +0 -0
  344. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_simulation_builder.py +0 -0
  345. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_simulations.py +0 -0
  346. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_stable_hash_seed.py +0 -0
  347. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_storage_delete_branch.py +0 -0
  348. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_subsample_invalidates_cache.py +0 -0
  349. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_tax_benefit_system_cache_identity.py +0 -0
  350. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_tracers.py +0 -0
  351. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_yaml.py +0 -0
  352. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tools/__init__.py +0 -0
  353. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tools/test_assert_near.py +0 -0
  354. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tools/test_google_cloud.py +0 -0
  355. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tools/test_hugging_face.py +0 -0
  356. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/variables/test_adds.py +0 -0
  357. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/variables/test_annualize.py +0 -0
  358. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/variables/test_bounds.py +0 -0
  359. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/variables/test_defined_for.py +0 -0
  360. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/variables/test_subtracts.py +0 -0
  361. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/variables/test_subtracts_sign.py +0 -0
  362. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/variables/test_variables.py +0 -0
  363. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/__init__.py +0 -0
  364. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/appclient.py +0 -0
  365. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/entities.py +0 -0
  366. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/simulations.py +0 -0
  367. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/taxbenefitsystems.py +0 -0
  368. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/variables.py +0 -0
  369. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/__init__.py +0 -0
  370. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/directory/subdirectory/test_4.yaml +0 -0
  371. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/directory/test_1.yaml +0 -0
  372. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/directory/test_2.yaml +0 -0
  373. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/failing_test_absolute_error_margin.yaml +0 -0
  374. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/failing_test_relative_error_margin.yaml +0 -0
  375. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_absolute_error_margin.yaml +0 -0
  376. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_failure.yaml +0 -0
  377. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_name_filter.yaml +0 -0
  378. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_relative_error_margin.yaml +0 -0
  379. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_success.yml +0 -0
  380. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_with_anchors.yaml +0 -0
  381. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_with_extension.yaml +0 -0
  382. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_with_reform.yaml +0 -0
  383. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_with_reform_2.yaml +0 -0
  384. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/smoke/test_country_init.py +0 -0
  385. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/smoke/test_us.py +0 -0
  386. {policyengine_core-3.26.3 → policyengine_core-3.26.4}/uv.lock +0 -0
@@ -1,3 +1,10 @@
1
+ ## [3.26.4] - 2026-05-14
2
+
3
+ ### Fixed
4
+
5
+ - Use safe YAML loaders and remove dynamic eval from parameter breakdown handling.
6
+
7
+
1
8
  ## [3.26.3] - 2026-05-14
2
9
 
3
10
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: policyengine-core
3
- Version: 3.26.3
3
+ Version: 3.26.4
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>
@@ -37,8 +37,8 @@ class ParameterNodeMetadata:
37
37
  metadata:
38
38
  breakdown:
39
39
  - region # If `region` is an Enum-type variable with possible values `[ENGLAND, WALES]` then these children will be added.
40
- - range(1, 7) # This code is `eval`uated to produce the list `[1, 2, 3, 4, 5, 6]` which are then added as grandchildren.
41
- - [True, False] # This list is added as great-grandchildren (using the same `eval` method as above).
40
+ - range(1, 7) # Safe dynamic form producing `[1, 2, 3, 4, 5, 6]`, which are then added as grandchildren.
41
+ - [True, False] # Literal collection form added as great-grandchildren.
42
42
 
43
43
  """
44
44
 
@@ -7,7 +7,7 @@ import yaml
7
7
  from policyengine_core.warnings import LibYAMLWarning
8
8
 
9
9
  try:
10
- from yaml import CLoader as Loader
10
+ from yaml import CSafeLoader as Loader
11
11
  except ImportError:
12
12
  message = [
13
13
  "libyaml is not installed in your environment.",
@@ -17,7 +17,7 @@ except ImportError:
17
17
  ]
18
18
  warnings.warn(" ".join(message), LibYAMLWarning)
19
19
  from yaml import (
20
- Loader,
20
+ SafeLoader as Loader,
21
21
  ) # type: ignore # (see https://github.com/python/mypy/issues/1153#issuecomment-455802270)
22
22
 
23
23
  ALLOWED_PARAM_TYPES = (float, int, bool, type(None), typing.List)
@@ -33,15 +33,30 @@ yaml.add_constructor("tag:yaml.org,2002:timestamp", date_constructor, Loader=Loa
33
33
 
34
34
 
35
35
  def dict_no_duplicate_constructor(loader, node, deep=False):
36
- keys = [key.value for key, value in node.value]
36
+ explicit_keys = {}
37
+ for key_node, _value_node in node.value:
38
+ if key_node.tag == "tag:yaml.org,2002:merge":
39
+ continue
40
+ key = loader.construct_object(key_node, deep=deep)
41
+ try:
42
+ if key in explicit_keys:
43
+ raise yaml.parser.ParserError(
44
+ "", node.start_mark, f"Found duplicate key '{key}'"
45
+ )
46
+ except TypeError as exc:
47
+ raise yaml.constructor.ConstructorError(
48
+ "", node.start_mark, f"Found unhashable key '{key}'"
49
+ ) from exc
50
+ explicit_keys[key] = True
37
51
 
38
- if len(keys) != len(set(keys)):
39
- duplicate = next((key for key in keys if keys.count(key) > 1))
40
- raise yaml.parser.ParserError(
41
- "", node.start_mark, f"Found duplicate key '{duplicate}'"
42
- )
52
+ loader.flatten_mapping(node)
53
+ pairs = loader.construct_pairs(node, deep=deep)
54
+ mapping = {}
43
55
 
44
- return loader.construct_mapping(node, deep)
56
+ for key, value in pairs:
57
+ mapping[key] = value
58
+
59
+ return mapping
45
60
 
46
61
 
47
62
  yaml.add_constructor(
@@ -1,3 +1,4 @@
1
+ import ast
1
2
  import logging
2
3
  from typing import Any, Dict, List, Type
3
4
 
@@ -6,6 +7,8 @@ from policyengine_core.parameters.parameter import Parameter
6
7
  from policyengine_core.parameters.parameter_node import ParameterNode
7
8
  from policyengine_core.variables import Variable
8
9
 
10
+ MAX_DYNAMIC_BREAKDOWN_VALUES = 10_000
11
+
9
12
 
10
13
  def homogenize_parameter_structures(
11
14
  root: ParameterNode, variables: Dict[str, Variable], default_value: Any = 0
@@ -43,6 +46,11 @@ def get_breakdown_variables(node: ParameterNode) -> List[str]:
43
46
  f"Invalid breakdown metadata for parameter {node.name}: {type(breakdown)}"
44
47
  )
45
48
  return None
49
+ if len(breakdown) == 0:
50
+ logging.warning(
51
+ f"Invalid breakdown metadata for parameter {node.name}: empty list"
52
+ )
53
+ return None
46
54
  return breakdown
47
55
  else:
48
56
  return None
@@ -71,8 +79,7 @@ def homogenize_parameter_node(
71
79
  elif dtype == bool:
72
80
  possible_values = [True, False]
73
81
  else:
74
- # Try to execute the breakdown as Python code
75
- possible_values = list(eval(first_breakdown))
82
+ possible_values = evaluate_dynamic_breakdown(first_breakdown)
76
83
  if not hasattr(node, "children"):
77
84
  node = ParameterNode(
78
85
  node.name,
@@ -119,3 +126,84 @@ def homogenize_parameter_node(
119
126
  node.children[child], breakdown[1:], variables, default_value
120
127
  )
121
128
  return node
129
+
130
+
131
+ def evaluate_dynamic_breakdown(expression: str) -> List[Any]:
132
+ """Safely evaluate a dynamic breakdown expression.
133
+
134
+ The parameter metadata only needs literal collections and the documented
135
+ ``range(...)`` / ``list(range(...))`` forms. Anything else is rejected.
136
+ """
137
+
138
+ parsed = ast.parse(expression, mode="eval")
139
+ evaluated = evaluate_dynamic_breakdown_node(parsed.body)
140
+ if isinstance(evaluated, range):
141
+ validate_dynamic_breakdown_range_cardinality(evaluated, expression)
142
+ return list(evaluated)
143
+ if isinstance(evaluated, (list, tuple)):
144
+ validate_dynamic_breakdown_cardinality(len(evaluated), expression)
145
+ return list(evaluated)
146
+ if isinstance(evaluated, set):
147
+ validate_dynamic_breakdown_cardinality(len(evaluated), expression)
148
+ return list(evaluated)
149
+ raise ValueError(
150
+ f"Invalid dynamic breakdown expression '{expression}'. "
151
+ "Only literal collections and range() calls are allowed."
152
+ )
153
+
154
+
155
+ def validate_dynamic_breakdown_cardinality(count: int, expression: str) -> None:
156
+ if count > MAX_DYNAMIC_BREAKDOWN_VALUES:
157
+ raise ValueError(
158
+ f"Dynamic breakdown expression '{expression}' produces {count} values, "
159
+ f"which exceeds the maximum of {MAX_DYNAMIC_BREAKDOWN_VALUES}."
160
+ )
161
+
162
+
163
+ def validate_dynamic_breakdown_range_cardinality(
164
+ values: range, expression: str
165
+ ) -> None:
166
+ try:
167
+ count = len(values)
168
+ except OverflowError as exc:
169
+ raise ValueError(
170
+ f"Dynamic breakdown expression '{expression}' produces too many values."
171
+ ) from exc
172
+ validate_dynamic_breakdown_cardinality(count, expression)
173
+
174
+
175
+ def evaluate_dynamic_breakdown_node(node: ast.AST) -> Any:
176
+ if isinstance(node, ast.Constant):
177
+ return node.value
178
+ if isinstance(node, ast.List):
179
+ validate_dynamic_breakdown_cardinality(len(node.elts), ast.unparse(node))
180
+ return [evaluate_dynamic_breakdown_node(element) for element in node.elts]
181
+ if isinstance(node, ast.Tuple):
182
+ validate_dynamic_breakdown_cardinality(len(node.elts), ast.unparse(node))
183
+ return tuple(evaluate_dynamic_breakdown_node(element) for element in node.elts)
184
+ if isinstance(node, ast.Set):
185
+ validate_dynamic_breakdown_cardinality(len(node.elts), ast.unparse(node))
186
+ return {evaluate_dynamic_breakdown_node(element) for element in node.elts}
187
+ if isinstance(node, ast.UnaryOp) and isinstance(node.op, (ast.UAdd, ast.USub)):
188
+ operand = evaluate_dynamic_breakdown_node(node.operand)
189
+ return operand if isinstance(node.op, ast.UAdd) else -operand
190
+ if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):
191
+ if node.func.id == "range":
192
+ args = [evaluate_dynamic_breakdown_node(arg) for arg in node.args]
193
+ if node.keywords:
194
+ raise ValueError("range() keyword arguments are not allowed")
195
+ result = range(*args)
196
+ validate_dynamic_breakdown_range_cardinality(result, ast.unparse(node))
197
+ return result
198
+ if node.func.id == "list":
199
+ if len(node.args) != 1 or node.keywords:
200
+ raise ValueError("list() must contain a single positional argument")
201
+ evaluated = evaluate_dynamic_breakdown_node(node.args[0])
202
+ if isinstance(evaluated, (range, list, tuple, set)):
203
+ return evaluated
204
+ raise ValueError(
205
+ "list() only supports range() and literal collection expressions"
206
+ )
207
+ raise ValueError(
208
+ f"Unsupported dynamic breakdown expression: {ast.unparse(node) if hasattr(ast, 'unparse') else type(node).__name__}"
209
+ )
@@ -31,7 +31,7 @@ def import_yaml():
31
31
  import yaml
32
32
 
33
33
  try:
34
- from yaml import CLoader as Loader
34
+ from yaml import CSafeLoader as Loader
35
35
  except ImportError:
36
36
  log.warning(
37
37
  " "
@@ -126,7 +126,7 @@ class YamlFile(pytest.File):
126
126
  def collect(self):
127
127
  try:
128
128
  tests = yaml.load(self.path.open(), Loader=Loader)
129
- except (yaml.scanner.ScannerError, yaml.parser.ParserError, TypeError):
129
+ except (yaml.YAMLError, TypeError):
130
130
  message = os.linesep.join(
131
131
  [
132
132
  traceback.format_exc(),
@@ -139,6 +139,11 @@ class YamlFile(pytest.File):
139
139
  tests: List[Dict] = [tests]
140
140
 
141
141
  for test in tests:
142
+ if not isinstance(test, dict):
143
+ raise ValueError(
144
+ f"'{self.path}' is not a valid YAML test file. "
145
+ "Expected a mapping or a list of mappings."
146
+ )
142
147
  if not self.should_ignore(test):
143
148
  yield YamlItem.from_parent(
144
149
  self,
@@ -150,11 +155,19 @@ class YamlFile(pytest.File):
150
155
 
151
156
  def should_ignore(self, test):
152
157
  name_filter = self.options.get("name_filter")
158
+ keywords = test.get("keywords", [])
159
+ if keywords is None:
160
+ keywords = []
161
+ if not isinstance(keywords, list):
162
+ raise ValueError(
163
+ f"'{self.path}' is not a valid YAML test file. "
164
+ "'keywords' must be a list."
165
+ )
153
166
  return (
154
167
  name_filter is not None
155
168
  and name_filter not in os.path.splitext(self.fspath.basename)[0]
156
169
  and name_filter not in test.get("name", "")
157
- and name_filter not in test.get("keywords", [])
170
+ and name_filter not in keywords
158
171
  )
159
172
 
160
173
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "policyengine-core"
3
- version = "3.26.3"
3
+ version = "3.26.4"
4
4
  description = "Core microsimulation engine enabling country-specific policy models."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -0,0 +1,130 @@
1
+ import pytest
2
+
3
+ from policyengine_core.errors import ParameterParsingError
4
+ from policyengine_core.parameters import ParameterNode, homogenize_parameter_structures
5
+ from policyengine_core.parameters.helpers import _load_yaml_file
6
+ from policyengine_core.parameters.operations.homogenize_parameters import (
7
+ MAX_DYNAMIC_BREAKDOWN_VALUES,
8
+ evaluate_dynamic_breakdown,
9
+ )
10
+
11
+
12
+ def test_parameter_yaml_loader_rejects_python_object_tags(tmp_path, monkeypatch):
13
+ calls = []
14
+
15
+ monkeypatch.setattr(
16
+ "os.system",
17
+ lambda command: calls.append(command) or 0,
18
+ )
19
+
20
+ yaml_path = tmp_path / "malicious.yaml"
21
+ yaml_path.write_text(
22
+ '!!python/object/apply:os.system ["echo pwned"]\n',
23
+ encoding="utf-8",
24
+ )
25
+
26
+ with pytest.raises(ParameterParsingError):
27
+ _load_yaml_file(str(yaml_path))
28
+
29
+ assert calls == []
30
+
31
+
32
+ def test_homogenize_parameter_structures_rejects_dynamic_breakdown_code(
33
+ monkeypatch,
34
+ ):
35
+ eval_calls = []
36
+
37
+ monkeypatch.setattr(
38
+ "builtins.eval",
39
+ lambda expression, globals=None, locals=None: (
40
+ eval_calls.append(expression) or range(1, 4)
41
+ ),
42
+ )
43
+
44
+ root = ParameterNode(
45
+ data={
46
+ "value_by_category": {
47
+ "metadata": {
48
+ "breakdown": ['__import__("os").system("echo pwned")'],
49
+ },
50
+ }
51
+ }
52
+ )
53
+
54
+ with pytest.raises(ValueError, match="breakdown"):
55
+ homogenize_parameter_structures(root, {}, default_value=0)
56
+
57
+ assert eval_calls == []
58
+
59
+
60
+ def test_homogenize_parameter_structures_rejects_oversized_dynamic_breakdown():
61
+ root = ParameterNode(
62
+ data={
63
+ "value_by_category": {
64
+ "metadata": {
65
+ "breakdown": [f"list(range({MAX_DYNAMIC_BREAKDOWN_VALUES + 1}))"],
66
+ },
67
+ }
68
+ }
69
+ )
70
+
71
+ with pytest.raises(ValueError, match="exceeds the maximum"):
72
+ homogenize_parameter_structures(root, {}, default_value=0)
73
+
74
+
75
+ def test_homogenize_parameter_structures_rejects_overflowing_dynamic_breakdown():
76
+ huge_stop = "1" + ("0" * 100)
77
+ root = ParameterNode(
78
+ data={
79
+ "value_by_category": {
80
+ "metadata": {
81
+ "breakdown": [f"range(0, {huge_stop})"],
82
+ },
83
+ }
84
+ }
85
+ )
86
+
87
+ with pytest.raises(ValueError, match="too many values"):
88
+ homogenize_parameter_structures(root, {}, default_value=0)
89
+
90
+
91
+ def test_parameter_yaml_loader_rejects_implicit_duplicate_keys(tmp_path):
92
+ yaml_path = tmp_path / "duplicate-bools.yaml"
93
+ yaml_path.write_text("true: 1\nTrue: 2\n", encoding="utf-8")
94
+
95
+ with pytest.raises(ParameterParsingError, match="duplicate key"):
96
+ _load_yaml_file(str(yaml_path))
97
+
98
+
99
+ def test_parameter_yaml_loader_allows_merge_key_overrides(tmp_path):
100
+ yaml_path = tmp_path / "merge-override.yaml"
101
+ yaml_path.write_text(
102
+ "defaults: &defaults\n value: 1\nmerged:\n <<: *defaults\n value: 2\n",
103
+ encoding="utf-8",
104
+ )
105
+
106
+ result = _load_yaml_file(str(yaml_path))
107
+
108
+ assert result["merged"]["value"] == 2
109
+
110
+
111
+ def test_evaluate_dynamic_breakdown_allows_documented_safe_forms():
112
+ assert evaluate_dynamic_breakdown("list(range(1, 4))") == [1, 2, 3]
113
+ assert evaluate_dynamic_breakdown("[1, 2, -3]") == [1, 2, -3]
114
+ assert evaluate_dynamic_breakdown('("a", "b")') == ["a", "b"]
115
+
116
+
117
+ def test_homogenize_parameter_structures_ignores_empty_breakdown_lists():
118
+ root = ParameterNode(
119
+ data={
120
+ "value_by_category": {
121
+ "metadata": {
122
+ "breakdown": [],
123
+ },
124
+ }
125
+ }
126
+ )
127
+
128
+ result = homogenize_parameter_structures(root, {}, default_value=0)
129
+
130
+ assert result is root
@@ -203,6 +203,113 @@ def test_performance_tables_option_output():
203
203
  clean_performance_files(paths)
204
204
 
205
205
 
206
+ def test_yaml_runner_rejects_python_object_tags(tmp_path, monkeypatch):
207
+ calls = []
208
+ yaml_path = tmp_path / "malicious.yaml"
209
+ yaml_path.write_text(
210
+ '!!python/object/apply:os.system ["echo pwned"]\n',
211
+ encoding="utf-8",
212
+ )
213
+
214
+ monkeypatch.setattr(
215
+ "os.system",
216
+ lambda command: calls.append(command) or 0,
217
+ )
218
+
219
+ malicious_yaml_file = object.__new__(YamlFile)
220
+ malicious_yaml_file.path = yaml_path
221
+ malicious_yaml_file.options = {}
222
+ malicious_yaml_file.tax_benefit_system = TaxBenefitSystem()
223
+
224
+ with pytest.raises(ValueError):
225
+ list(malicious_yaml_file.collect())
226
+
227
+ assert calls == []
228
+
229
+
230
+ def test_yaml_runner_wraps_composer_errors(tmp_path):
231
+ yaml_path = tmp_path / "invalid-anchor.yaml"
232
+ yaml_path.write_text("value: *missing_anchor\n", encoding="utf-8")
233
+
234
+ invalid_yaml_file = object.__new__(YamlFile)
235
+ invalid_yaml_file.path = yaml_path
236
+ invalid_yaml_file.options = {}
237
+ invalid_yaml_file.tax_benefit_system = TaxBenefitSystem()
238
+
239
+ with pytest.raises(ValueError, match="not a valid YAML file"):
240
+ list(invalid_yaml_file.collect())
241
+
242
+
243
+ def test_yaml_runner_rejects_scalar_roots(tmp_path):
244
+ yaml_path = tmp_path / "scalar.yaml"
245
+ yaml_path.write_text("foo\n", encoding="utf-8")
246
+
247
+ scalar_yaml_file = object.__new__(YamlFile)
248
+ scalar_yaml_file.path = yaml_path
249
+ scalar_yaml_file.options = {}
250
+ scalar_yaml_file.tax_benefit_system = TaxBenefitSystem()
251
+
252
+ with pytest.raises(ValueError, match="list of mappings"):
253
+ list(scalar_yaml_file.collect())
254
+
255
+
256
+ def test_yaml_runner_rejects_scalar_keywords(tmp_path):
257
+ yaml_path = tmp_path / "invalid-keywords.yaml"
258
+ yaml_path.write_text(
259
+ "name: Example\nkeywords: 0\noutput: {}\n",
260
+ encoding="utf-8",
261
+ )
262
+
263
+ invalid_yaml_file = object.__new__(YamlFile)
264
+ invalid_yaml_file.path = yaml_path
265
+ invalid_yaml_file.options = {"name_filter": "missing"}
266
+ invalid_yaml_file.tax_benefit_system = TaxBenefitSystem()
267
+
268
+ with pytest.raises(ValueError, match="'keywords' must be a list"):
269
+ list(invalid_yaml_file.collect())
270
+
271
+
272
+ def test_yaml_runner_allows_yaml_merge_anchors(tmp_path):
273
+ yaml_path = tmp_path / "anchors.yaml"
274
+ yaml_path.write_text(
275
+ """
276
+ - name: define anchor
277
+ input:
278
+ persons: &persons
279
+ Alicia:
280
+ salary: 4000
281
+ households:
282
+ household:
283
+ parents: [Alicia]
284
+ output:
285
+ salary: 4000
286
+
287
+ - name: merge anchor
288
+ input:
289
+ persons:
290
+ <<: *persons
291
+ households:
292
+ household:
293
+ parents: [Alicia]
294
+ output:
295
+ salary: 4000
296
+ """.strip(),
297
+ encoding="utf-8",
298
+ )
299
+
300
+ yaml_file = object.__new__(YamlFile)
301
+ yaml_file.config = None
302
+ yaml_file.session = None
303
+ yaml_file._nodeid = "anchors"
304
+ yaml_file.path = yaml_path
305
+ yaml_file.options = {}
306
+ yaml_file.tax_benefit_system = TaxBenefitSystem()
307
+
308
+ collected = list(yaml_file.collect())
309
+
310
+ assert len(collected) == 2
311
+
312
+
206
313
  def clean_performance_files(paths: List[str]):
207
314
  for path in paths:
208
315
  if os.path.isfile(path):