policyengine-core 3.34.0__tar.gz → 3.34.2__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 (505) hide show
  1. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/CHANGELOG.md +14 -0
  2. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/PKG-INFO +1 -1
  3. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/usage/parameters.md +10 -0
  4. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/operations/interpolate_parameters.py +15 -4
  5. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/parameter.py +8 -1
  6. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/parameter_at_instant.py +3 -1
  7. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/parameter_node.py +2 -1
  8. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/parameter_scale.py +2 -1
  9. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tools/test_runner.py +65 -12
  10. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/pyproject.toml +1 -1
  11. policyengine_core-3.34.2/tests/core/parameters/test_parameter_metadata_clone.py +385 -0
  12. policyengine_core-3.34.2/tests/core/parameters/test_parameter_metadata_clone_property.py +216 -0
  13. policyengine_core-3.34.2/tests/core/tools/test_runner/test_gc_pause.py +443 -0
  14. policyengine_core-3.34.2/tests/fixtures/parameter_metadata_clones.py +257 -0
  15. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/.github/ISSUE_TEMPLATE.md +0 -0
  16. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  17. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/.github/actionlint.yaml +0 -0
  18. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/.github/bump_version.py +0 -0
  19. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/.github/changelog_template.md +0 -0
  20. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/.github/get-changelog-diff.sh +0 -0
  21. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/.github/has-functional-changes.sh +0 -0
  22. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/.github/is-version-number-acceptable.sh +0 -0
  23. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/.github/publish-git-tag.sh +0 -0
  24. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/.github/requirements/legacy-country-smoke.txt +0 -0
  25. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/.github/workflows/pr.yaml +0 -0
  26. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/.github/workflows/push.yaml +0 -0
  27. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/.gitignore +0 -0
  28. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/.python-version +0 -0
  29. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/AGENTS.md +0 -0
  30. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/CLAUDE.md +0 -0
  31. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/CONTRIBUTING.md +0 -0
  32. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/LICENSE +0 -0
  33. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/MANIFEST.in +0 -0
  34. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/Makefile +0 -0
  35. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/README.md +0 -0
  36. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/_build/logs/myst.build.json +0 -0
  37. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/changelog.d/.gitkeep +0 -0
  38. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/_config.yml +0 -0
  39. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/_static/style.css +0 -0
  40. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/_toc.yml +0 -0
  41. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/add_plotly_to_book.py +0 -0
  42. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/contributing/intro.md +0 -0
  43. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/engineering/skills/README.md +0 -0
  44. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/engineering/skills/documentation_review.md +0 -0
  45. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/engineering/skills/github-prs.md +0 -0
  46. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/engineering/skills/testing.md +0 -0
  47. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/intro.md +0 -0
  48. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/logo.png +0 -0
  49. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/commons.md +0 -0
  50. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/country_template.md +0 -0
  51. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/data.md +0 -0
  52. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/data_storage.md +0 -0
  53. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/entities.md +0 -0
  54. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/enums.md +0 -0
  55. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/errors.md +0 -0
  56. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/experimental.md +0 -0
  57. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/extension_template.md +0 -0
  58. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/holders.md +0 -0
  59. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/parameters.md +0 -0
  60. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/periods.md +0 -0
  61. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/populations.md +0 -0
  62. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/projectors.md +0 -0
  63. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/reforms.md +0 -0
  64. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/scripts.md +0 -0
  65. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/simulations.md +0 -0
  66. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/taxbenefitsystems.md +0 -0
  67. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/taxscales.md +0 -0
  68. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/tools.md +0 -0
  69. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/tracers.md +0 -0
  70. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/types.md +0 -0
  71. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/variables.md +0 -0
  72. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/python_api/warnings.md +0 -0
  73. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/usage/branches.md +0 -0
  74. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/usage/country.ipynb +0 -0
  75. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/usage/datasets.ipynb +0 -0
  76. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/usage/reforms.ipynb +0 -0
  77. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/docs/usage/simulation.ipynb +0 -0
  78. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/mypy.ini +0 -0
  79. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/__init__.py +0 -0
  80. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/build_metadata.py +0 -0
  81. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/charts/__init__.py +0 -0
  82. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/charts/bar.py +0 -0
  83. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/charts/formatting.py +0 -0
  84. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/commons/__init__.py +0 -0
  85. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/commons/formulas.py +0 -0
  86. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/commons/misc.py +0 -0
  87. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/commons/rates.py +0 -0
  88. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/__init__.py +0 -0
  89. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/constants.py +0 -0
  90. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/data/__init__.py +0 -0
  91. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/data/datasets/__init__.py +0 -0
  92. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/data/datasets/country_template_dataset.py +0 -0
  93. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/entities.py +0 -0
  94. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/modelled_policies.yaml +0 -0
  95. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/parameters/benefits/basic_income.yaml +0 -0
  96. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/parameters/benefits/housing_allowance.yaml +0 -0
  97. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/parameters/benefits/index.yaml +0 -0
  98. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/parameters/benefits/parenting_allowance/amount.yaml +0 -0
  99. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/parameters/benefits/parenting_allowance/income_threshold.yaml +0 -0
  100. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/parameters/general/age_of_majority.yaml +0 -0
  101. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/parameters/general/age_of_retirement.yaml +0 -0
  102. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/parameters/taxes/housing_tax.yaml +0 -0
  103. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/parameters/taxes/income_tax_rate.yaml +0 -0
  104. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/parameters/taxes/social_security_contribution.yaml +0 -0
  105. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/reforms/__init__.py +0 -0
  106. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/reforms/add_dynamic_variable.py +0 -0
  107. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/reforms/add_new_tax.py +0 -0
  108. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/reforms/flat_social_security_contribution.py +0 -0
  109. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/reforms/modify_social_security_taxation.py +0 -0
  110. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/reforms/removal_basic_income.py +0 -0
  111. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/situation_examples/__init__.py +0 -0
  112. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/situation_examples/couple.json +0 -0
  113. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/situation_examples/housing.json +0 -0
  114. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/situation_examples/single.json +0 -0
  115. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/tests/age.yaml +0 -0
  116. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/tests/basic_income.yaml +0 -0
  117. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/tests/disposable_income.yaml +0 -0
  118. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/tests/housing_allowance.yaml +0 -0
  119. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/tests/housing_tax.yaml +0 -0
  120. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/tests/income_tax.yaml +0 -0
  121. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/tests/reforms/add_dynamic_variable.yaml +0 -0
  122. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/tests/reforms/add_new_tax.yaml +0 -0
  123. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/tests/reforms/modify_social_security_taxation.yaml +0 -0
  124. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/tests/situations/income_tax.yaml +0 -0
  125. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/tests/situations/parenting_allowance.yaml +0 -0
  126. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/tests/social_security_contribution.yaml +0 -0
  127. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/tests/test_microsimulation.py +0 -0
  128. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/variables/__init__.py +0 -0
  129. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/variables/benefits.py +0 -0
  130. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/variables/demographics.py +0 -0
  131. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/variables/housing.py +0 -0
  132. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/variables/ids.py +0 -0
  133. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/variables/income.py +0 -0
  134. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/variables/stats.py +0 -0
  135. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/country_template/variables/taxes.py +0 -0
  136. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/data/__init__.py +0 -0
  137. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/data/dataset.py +0 -0
  138. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/data_storage/__init__.py +0 -0
  139. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/data_storage/in_memory_storage.py +0 -0
  140. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/data_storage/on_disk_storage.py +0 -0
  141. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/data_storage/storage_directory.py +0 -0
  142. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/data_storage/store_history.py +0 -0
  143. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/data_structures/__init__.py +0 -0
  144. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/data_structures/parameter_metadata.py +0 -0
  145. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/data_structures/parameter_node_metadata.py +0 -0
  146. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/data_structures/reference.py +0 -0
  147. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/data_structures/unit.py +0 -0
  148. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/entities/__init__.py +0 -0
  149. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/entities/entity.py +0 -0
  150. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/entities/group_entity.py +0 -0
  151. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/entities/helpers.py +0 -0
  152. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/entities/role.py +0 -0
  153. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/enums/__init__.py +0 -0
  154. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/enums/config.py +0 -0
  155. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/enums/enum.py +0 -0
  156. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/enums/enum_array.py +0 -0
  157. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/errors/__init__.py +0 -0
  158. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/errors/cycle_error.py +0 -0
  159. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/errors/empty_argument_error.py +0 -0
  160. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/errors/nan_creation_error.py +0 -0
  161. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/errors/non_deterministic_formula_error.py +0 -0
  162. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/errors/parameter_not_found_error.py +0 -0
  163. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/errors/parameter_parsing_error.py +0 -0
  164. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/errors/period_mismatch_error.py +0 -0
  165. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/errors/situation_parsing_error.py +0 -0
  166. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/errors/spiral_error.py +0 -0
  167. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/errors/variable_name_conflict_error.py +0 -0
  168. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/errors/variable_not_found_error.py +0 -0
  169. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/experimental/__init__.py +0 -0
  170. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/experimental/memory_config.py +0 -0
  171. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/extension_template/__init__.py +0 -0
  172. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/extension_template/local_benefit.py +0 -0
  173. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/extension_template/parameters/local_town/child_allowance/amount.yaml +0 -0
  174. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/extension_template/parameters/local_town/child_allowance/index.yaml +0 -0
  175. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/extension_template/parameters/local_town/index.yaml +0 -0
  176. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/extension_template/tests/local_benefit.yaml +0 -0
  177. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/holders/__init__.py +0 -0
  178. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/holders/helpers.py +0 -0
  179. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/holders/holder.py +0 -0
  180. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/model_api.py +0 -0
  181. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/__init__.py +0 -0
  182. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/at_instant_like.py +0 -0
  183. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/config.py +0 -0
  184. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/helpers.py +0 -0
  185. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/operations/__init__.py +0 -0
  186. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/operations/get_parameter.py +0 -0
  187. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/operations/homogenize_parameters.py +0 -0
  188. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/operations/propagate_parameter_metadata.py +0 -0
  189. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/operations/uprate_parameters.py +0 -0
  190. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/parameter_node_at_instant.py +0 -0
  191. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/parameter_scale_bracket.py +0 -0
  192. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/parameters/vectorial_parameter_node_at_instant.py +0 -0
  193. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/periods/__init__.py +0 -0
  194. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/periods/config.py +0 -0
  195. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/periods/helpers.py +0 -0
  196. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/periods/instant_.py +0 -0
  197. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/periods/period_.py +0 -0
  198. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/populations/__init__.py +0 -0
  199. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/populations/config.py +0 -0
  200. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/populations/group_population.py +0 -0
  201. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/populations/population.py +0 -0
  202. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/projectors/__init__.py +0 -0
  203. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/projectors/entity_to_person_projector.py +0 -0
  204. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/projectors/first_person_to_entity_projector.py +0 -0
  205. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/projectors/helpers.py +0 -0
  206. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/projectors/projector.py +0 -0
  207. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/projectors/unique_role_to_entity_projector.py +0 -0
  208. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/reforms/__init__.py +0 -0
  209. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/reforms/reform.py +0 -0
  210. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/scripts/__init__.py +0 -0
  211. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/scripts/assets/__init__.py +0 -0
  212. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/scripts/assets/index.html +0 -0
  213. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/scripts/policyengine_command.py +0 -0
  214. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/scripts/run_data.py +0 -0
  215. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/scripts/run_test.py +0 -0
  216. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/scripts/simulation_generator.py +0 -0
  217. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/simulations/__init__.py +0 -0
  218. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/simulations/helpers.py +0 -0
  219. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/simulations/individual_sim.py +0 -0
  220. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/simulations/microsimulation.py +0 -0
  221. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/simulations/simulation.py +0 -0
  222. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/simulations/simulation_builder.py +0 -0
  223. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/simulations/simulation_macro_cache.py +0 -0
  224. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/taxbenefitsystems/__init__.py +0 -0
  225. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/taxbenefitsystems/tax_benefit_system.py +0 -0
  226. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/taxscales/__init__.py +0 -0
  227. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/taxscales/abstract_rate_tax_scale.py +0 -0
  228. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/taxscales/abstract_tax_scale.py +0 -0
  229. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/taxscales/amount_tax_scale_like.py +0 -0
  230. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/taxscales/helpers.py +0 -0
  231. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/taxscales/linear_average_rate_tax_scale.py +0 -0
  232. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/taxscales/marginal_amount_tax_scale.py +0 -0
  233. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/taxscales/marginal_rate_tax_scale.py +0 -0
  234. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/taxscales/rate_tax_scale_like.py +0 -0
  235. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/taxscales/single_amount_tax_scale.py +0 -0
  236. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/taxscales/tax_scale_like.py +0 -0
  237. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tools/__init__.py +0 -0
  238. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tools/google_cloud.py +0 -0
  239. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tools/hugging_face.py +0 -0
  240. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tools/simulation_dumper.py +0 -0
  241. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tools/test_from_situation.py +0 -0
  242. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tools/win_file_manager.py +0 -0
  243. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tracers/__init__.py +0 -0
  244. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tracers/computation_log.py +0 -0
  245. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tracers/flat_trace.py +0 -0
  246. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tracers/full_tracer.py +0 -0
  247. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tracers/performance_log.py +0 -0
  248. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tracers/simple_tracer.py +0 -0
  249. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tracers/trace_node.py +0 -0
  250. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tracers/tracing_parameter_node_at_instant.py +0 -0
  251. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/tracers/variable_graph.py +0 -0
  252. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/types/__init__.py +0 -0
  253. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/types/data_types/__init__.py +0 -0
  254. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/types/data_types/arrays.py +0 -0
  255. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/variables/__init__.py +0 -0
  256. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/variables/config.py +0 -0
  257. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/variables/defined_for.py +0 -0
  258. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/variables/formula_randomness.py +0 -0
  259. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/variables/helpers.py +0 -0
  260. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/variables/typing.py +0 -0
  261. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/variables/variable.py +0 -0
  262. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/warnings/__init__.py +0 -0
  263. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/warnings/libyaml_warning.py +0 -0
  264. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/warnings/memory_config_warning.py +0 -0
  265. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/warnings/parameter_key_warning.py +0 -0
  266. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/policyengine_core/warnings/tempfile_warning.py +0 -0
  267. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/pytest.ini +0 -0
  268. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/__init__.py +0 -0
  269. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/conftest.py +0 -0
  270. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/__init__.py +0 -0
  271. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/commons/__init__.py +0 -0
  272. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/commons/test_between_function.py +0 -0
  273. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/commons/test_formulas.py +0 -0
  274. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/commons/test_is_in_function.py +0 -0
  275. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/commons/test_random_seed.py +0 -0
  276. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/commons/test_rates.py +0 -0
  277. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/data/test_dataset.py +0 -0
  278. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/enums/test_enum.py +0 -0
  279. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/model_api/test_index_.py +0 -0
  280. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/__init__.py +0 -0
  281. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/array_type.yaml +0 -0
  282. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/duplicate_key.yaml +0 -0
  283. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/filesystem_hierarchy/empty_index_file/index.yaml +0 -0
  284. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/filesystem_hierarchy/node1/param.yaml +0 -0
  285. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/indentation.yaml +0 -0
  286. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/missing_value.yaml +0 -0
  287. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/parameter_for_unit_propagation.yaml +0 -0
  288. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/test_parameter_clone.py +0 -0
  289. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/test_parameter_validation.py +0 -0
  290. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/test_propagate_units.py +0 -0
  291. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/test_unknown_keys.py +0 -0
  292. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/unexpected_key_in_parameter.yaml +0 -0
  293. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/unexpected_key_in_scale.yaml +0 -0
  294. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/unexpected_key_in_value_at_instant.yaml +0 -0
  295. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/unexpected_key_in_value_history.yaml +0 -0
  296. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/unknown_key_beside_values.yaml +0 -0
  297. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/uprating_under_metadata.yaml +0 -0
  298. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/wrong_date.yaml +0 -0
  299. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/wrong_scale.yaml +0 -0
  300. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/wrong_type_in_bracket.yaml +0 -0
  301. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/wrong_type_in_brackets.yaml +0 -0
  302. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/wrong_type_in_parameter.yaml +0 -0
  303. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/wrong_type_in_scale.yaml +0 -0
  304. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/wrong_type_in_value_history.yaml +0 -0
  305. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/wrong_value.yaml +0 -0
  306. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameter_validation/yaml_hierarchy/node1.yaml +0 -0
  307. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameters/operations/test_interpolation.py +0 -0
  308. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameters/operations/test_nesting.py +0 -0
  309. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameters/operations/test_propagation.py +0 -0
  310. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameters/operations/test_scale_threshold_uprating.py +0 -0
  311. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameters/operations/test_uprating.py +0 -0
  312. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameters/test_numpy2_structured_arrays.py +0 -0
  313. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameters/test_vectorial_parameter_node_copy.py +0 -0
  314. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameters/test_vectorial_parameter_node_copy_property.py +0 -0
  315. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameters_fancy_indexing/__init__.py +0 -0
  316. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameters_fancy_indexing/bareme.yaml +0 -0
  317. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameters_fancy_indexing/local_tax.yaml +0 -0
  318. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameters_fancy_indexing/rate.yaml +0 -0
  319. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameters_fancy_indexing/test_fancy_indexing.py +0 -0
  320. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/parameters_fancy_indexing/test_fancy_indexing_property.py +0 -0
  321. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/simulations/test_formula_randomness_concurrency.py +0 -0
  322. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tax_scales/__init__.py +0 -0
  323. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tax_scales/test_abstract_rate_tax_scale.py +0 -0
  324. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tax_scales/test_abstract_tax_scale.py +0 -0
  325. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tax_scales/test_linear_average_rate_tax_scale.py +0 -0
  326. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tax_scales/test_linear_average_rate_tax_scale_property.py +0 -0
  327. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tax_scales/test_marginal_amount_tax_scale.py +0 -0
  328. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tax_scales/test_marginal_rate_tax_scale.py +0 -0
  329. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tax_scales/test_rate_scale_conversion_property.py +0 -0
  330. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tax_scales/test_rate_tax_scale_like.py +0 -0
  331. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tax_scales/test_single_amount_tax_scale.py +0 -0
  332. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tax_scales/test_tax_scales_commons.py +0 -0
  333. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_apply_reform_invalidates_cache.py +0 -0
  334. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_apply_reform_preserves_user_inputs.py +0 -0
  335. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_assert_near_precision.py +0 -0
  336. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_axes.py +0 -0
  337. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_bincount_minlength.py +0 -0
  338. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_branch_helper_invalidation.py +0 -0
  339. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_branch_input_fixed_point.py +0 -0
  340. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_branch_input_fixed_point_property.py +0 -0
  341. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_branch_input_invalidation.py +0 -0
  342. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_branch_input_invalidation_property.py +0 -0
  343. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_branch_scoped_delete_arrays.py +0 -0
  344. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_branch_shared_arrays.py +0 -0
  345. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_branch_shared_arrays_differential.py +0 -0
  346. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_build_metadata.py +0 -0
  347. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_calculate_output.py +0 -0
  348. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_carry_over_order.py +0 -0
  349. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_carry_over_order_property.py +0 -0
  350. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_clone_invalidated_caches.py +0 -0
  351. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_clone_rebinding.py +0 -0
  352. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_clone_rebinding_property.py +0 -0
  353. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_clone_reform_baseline.py +0 -0
  354. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_clone_reform_baseline_property.py +0 -0
  355. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_countries.py +0 -0
  356. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_cycles.py +0 -0
  357. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_data_storage_dir.py +0 -0
  358. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_data_storage_dir_property.py +0 -0
  359. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_dataset_default_role.py +0 -0
  360. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_dataset_default_role_property.py +0 -0
  361. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_dataset_getattr.py +0 -0
  362. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_dataset_unknown_column_warning.py +0 -0
  363. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_default_simulation_count_property.py +0 -0
  364. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_disk_period_filenames.py +0 -0
  365. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_disk_storage_differential.py +0 -0
  366. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_disk_storage_ownership.py +0 -0
  367. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_docs_deployment.py +0 -0
  368. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_dump_restore.py +0 -0
  369. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_dump_restore_property.py +0 -0
  370. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_entities.py +0 -0
  371. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_eternity_subperiods.py +0 -0
  372. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_extensions.py +0 -0
  373. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_fast_cache.py +0 -0
  374. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_fast_cache_contained_periods.py +0 -0
  375. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_fast_cache_contained_periods_property.py +0 -0
  376. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_fast_cache_guards.py +0 -0
  377. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_formulas.py +0 -0
  378. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_group_population_empty.py +0 -0
  379. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_group_population_reductions_property.py +0 -0
  380. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_holder_branch_fallback.py +0 -0
  381. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_holder_write_fast_cache.py +0 -0
  382. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_holder_write_fast_cache_property.py +0 -0
  383. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_holders.py +0 -0
  384. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_input_tier_invalidation.py +0 -0
  385. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_join_with_persons_identity.py +0 -0
  386. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_join_with_persons_identity_property.py +0 -0
  387. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_macro_cache_not_singleton.py +0 -0
  388. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_medium_fixes.py +0 -0
  389. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_microsimulation_person_accessor.py +0 -0
  390. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_microsimulation_weights.py +0 -0
  391. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_on_disk_storage_clones.py +0 -0
  392. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_opt_out_cache.py +0 -0
  393. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_option_result_cache.py +0 -0
  394. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_option_result_cache_property.py +0 -0
  395. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_option_result_input_provenance.py +0 -0
  396. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_own_period_input_overlapping_cache.py +0 -0
  397. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_pandas3_compatibility.py +0 -0
  398. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_parameter_security.py +0 -0
  399. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_parameters.py +0 -0
  400. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_periods.py +0 -0
  401. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_projectors.py +0 -0
  402. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_reform_baseline_system.py +0 -0
  403. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_reform_parameter_isolation.py +0 -0
  404. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_reform_period_keys.py +0 -0
  405. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_reforms.py +0 -0
  406. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_registered_input_deletion.py +0 -0
  407. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_release_tagging.py +0 -0
  408. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_rerun_fixture_isolation.py +0 -0
  409. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_restore_input_provenance.py +0 -0
  410. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_restore_input_registry.py +0 -0
  411. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_restore_input_registry_property.py +0 -0
  412. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_set_input_helper_order.py +0 -0
  413. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_set_input_helper_order_property.py +0 -0
  414. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_simulation_builder.py +0 -0
  415. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_simulation_copy_pickle.py +0 -0
  416. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_simulation_copy_pickle_property.py +0 -0
  417. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_simulations.py +0 -0
  418. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_stable_hash_seed.py +0 -0
  419. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_stale_frame_cache.py +0 -0
  420. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_storage_anchored_periods.py +0 -0
  421. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_storage_delete_branch.py +0 -0
  422. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_storage_input_index.py +0 -0
  423. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_storage_shared_index.py +0 -0
  424. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_storage_shared_index_differential.py +0 -0
  425. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_subsample_baseline_branch.py +0 -0
  426. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_subsample_computed_values.py +0 -0
  427. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_subsample_computed_values_property.py +0 -0
  428. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_subsample_deleted_inputs.py +0 -0
  429. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_subsample_entity_weight_totals.py +0 -0
  430. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_subsample_inputs_only.py +0 -0
  431. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_subsample_inputs_only_property.py +0 -0
  432. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_subsample_invalidates_cache.py +0 -0
  433. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_subsample_membership_ids.py +0 -0
  434. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_subsample_restore_inputs.py +0 -0
  435. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_subsample_sampling_period.py +0 -0
  436. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_subsample_sampling_period_property.py +0 -0
  437. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_subsample_structural_ids.py +0 -0
  438. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_subsample_weight_fallback.py +0 -0
  439. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_tax_benefit_system_cache_identity.py +0 -0
  440. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_tracers.py +0 -0
  441. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_tracing_parameter_isolation.py +0 -0
  442. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_tracing_parameter_isolation_properties.py +0 -0
  443. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_uprating_order.py +0 -0
  444. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_uprating_order_property.py +0 -0
  445. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_user_input_keys.py +0 -0
  446. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_user_input_keys_property.py +0 -0
  447. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_user_input_keys_soundness.py +0 -0
  448. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_variable_code_sharing.py +0 -0
  449. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_variable_code_sharing_property.py +0 -0
  450. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/test_yaml.py +0 -0
  451. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tools/__init__.py +0 -0
  452. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tools/test_assert_near.py +0 -0
  453. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tools/test_google_cloud.py +0 -0
  454. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tools/test_hugging_face.py +0 -0
  455. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/tools/test_runner/test_yaml_runner.py +0 -0
  456. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/variables/test_adds.py +0 -0
  457. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/variables/test_annualize.py +0 -0
  458. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/variables/test_bounds.py +0 -0
  459. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/variables/test_defined_for.py +0 -0
  460. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/variables/test_formula_randomness.py +0 -0
  461. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/variables/test_non_numeric_uprating_and_defined_for.py +0 -0
  462. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/variables/test_subtracts.py +0 -0
  463. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/variables/test_subtracts_sign.py +0 -0
  464. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/variables/test_variable_clone.py +0 -0
  465. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/variables/test_variable_formula_determinism.py +0 -0
  466. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/variables/test_variable_uprating.py +0 -0
  467. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/core/variables/test_variables.py +0 -0
  468. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/__init__.py +0 -0
  469. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/appclient.py +0 -0
  470. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/branch_input_invalidation.py +0 -0
  471. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/branch_shared_arrays.py +0 -0
  472. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/carry_over.py +0 -0
  473. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/data_storage_dir.py +0 -0
  474. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/disk_storage.py +0 -0
  475. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/entities.py +0 -0
  476. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/fast_cache_contained_periods.py +0 -0
  477. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/option_caches.py +0 -0
  478. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/set_input_helper_order.py +0 -0
  479. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/simulation_copy.py +0 -0
  480. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/simulations.py +0 -0
  481. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/subsample_inputs.py +0 -0
  482. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/taxbenefitsystems.py +0 -0
  483. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/tracing.py +0 -0
  484. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/uprated_inputs.py +0 -0
  485. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/uprating_order.py +0 -0
  486. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/variables.py +0 -0
  487. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/vectorial_parameter_nodes.py +0 -0
  488. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/__init__.py +0 -0
  489. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/directory/subdirectory/test_4.yaml +0 -0
  490. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/directory/test_1.yaml +0 -0
  491. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/directory/test_2.yaml +0 -0
  492. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/failing_test_absolute_error_margin.yaml +0 -0
  493. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/failing_test_relative_error_margin.yaml +0 -0
  494. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/test_absolute_error_margin.yaml +0 -0
  495. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/test_failure.yaml +0 -0
  496. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/test_name_filter.yaml +0 -0
  497. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/test_relative_error_margin.yaml +0 -0
  498. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/test_success.yml +0 -0
  499. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/test_with_anchors.yaml +0 -0
  500. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/test_with_extension.yaml +0 -0
  501. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/test_with_reform.yaml +0 -0
  502. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/fixtures/yaml_tests/test_with_reform_2.yaml +0 -0
  503. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/smoke/test_country_init.py +0 -0
  504. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/tests/smoke/test_us.py +0 -0
  505. {policyengine_core-3.34.0 → policyengine_core-3.34.2}/uv.lock +0 -0
@@ -1,3 +1,17 @@
1
+ ## [3.34.2] - 2026-10-31
2
+
3
+ ### Changed
4
+
5
+ - Pause automatic garbage collection while the YAML test runner builds the system for a reform combination, run one full collection when the build returns while the cache holds fewer than three systems, and restore the caller's setting, so a cache-miss build no longer spends most of its time in repeated full collections that free almost nothing.
6
+
7
+
8
+ ## [3.34.1] - 2026-10-31
9
+
10
+ ### Changed
11
+
12
+ - Parameter clones copy each metadata dict without deep-copying the values in it, which makes cloning a large tax-benefit system faster and smaller. `interpolate_parameters` now records its work in `Parameter.interpolated` instead of writing `completed` into the `interpolation` metadata, so it interpolates every parameter a node propagates `interpolation` to, not only the first.
13
+
14
+
1
15
  ## [3.34.0] - 2026-10-30
2
16
 
3
17
  ### Removed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: policyengine-core
3
- Version: 3.34.0
3
+ Version: 3.34.2
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>
@@ -57,6 +57,16 @@ metadata:
57
57
  href: https://www.gov.uk/government/publications/child-benefit-rates-and-thresholds/child-benefit-rates-and-thresholds
58
58
  ```
59
59
 
60
+ ### Metadata in copies
61
+
62
+ `clone()` on a parameter tree, which `TaxBenefitSystem.clone()`, reforms and simulation clones use, gives every node, parameter, dated value and scale in the copy its own metadata dict. The values in that dict are the same objects as in the source. Setting, updating or removing a key changes only the tree it is made on. To change a nested value, such as one entry of a `reference` list, replace the key with a new value instead of editing the list or dict in place, which would change every copy that shares it:
63
+
64
+ ```python
65
+ parameter.metadata["reference"] = [*parameter.metadata["reference"], new_reference]
66
+ ```
67
+
68
+ The same holds within one tree: a dated value written in dictionary form (`value:`, with or without `metadata:`) holds its parameter's metadata values, and `propagate_parameter_metadata` gives a node's descendants the node's values.
69
+
60
70
  ### Metadata for parameters
61
71
 
62
72
  ```{eval-rst}
@@ -9,6 +9,10 @@ from policyengine_core.periods import instant
9
9
  def interpolate_parameters(root: ParameterNode) -> ParameterNode:
10
10
  """Interpolates parameters according to their metadata.
11
11
 
12
+ Each parameter interpolates once, however many times this runs. To
13
+ interpolate one again, set its ``interpolated`` attribute to ``False`` and
14
+ give it ``interpolation`` metadata without a true ``completed`` key.
15
+
12
16
  Args:
13
17
  root (ParameterNode): The root of the parameter tree.
14
18
 
@@ -17,9 +21,13 @@ def interpolate_parameters(root: ParameterNode) -> ParameterNode:
17
21
  """
18
22
  for parameter in root.get_descendants():
19
23
  if isinstance(parameter, Parameter):
20
- if "interpolation" in parameter.metadata and not parameter.metadata[
21
- "interpolation"
22
- ].get("completed", False):
24
+ if (
25
+ "interpolation" in parameter.metadata
26
+ and not parameter.interpolated
27
+ # Core no longer writes this key, but a tree pickled by an
28
+ # older Core has it, and so can metadata written by hand.
29
+ and not parameter.metadata["interpolation"].get("completed", False)
30
+ ):
23
31
  interpolated_entries = []
24
32
  for i in range(len(parameter.values_list) - 1):
25
33
  # For each gap in parameter values
@@ -56,5 +64,8 @@ def interpolate_parameters(root: ParameterNode) -> ParameterNode:
56
64
  for entry in interpolated_entries:
57
65
  parameter.values_list.append(entry)
58
66
  parameter.values_list.sort(key=lambda x: x.instant_str, reverse=True)
59
- parameter.metadata["interpolation"]["completed"] = True
67
+ # Mark the parameter, not its ``interpolation`` dict. Its clones
68
+ # and every parameter under a propagating node share that dict,
69
+ # and propagating metadata again replaces this parameter's.
70
+ parameter.interpolated = True
60
71
  return root
@@ -19,6 +19,8 @@ class Parameter(AtInstantLike):
19
19
 
20
20
  Attributes:
21
21
  values_list: List of the values, in reverse chronological order.
22
+ interpolated: Whether :func:`interpolate_parameters` has filled in this
23
+ parameter's values.
22
24
 
23
25
 
24
26
  Args:
@@ -45,6 +47,10 @@ class Parameter(AtInstantLike):
45
47
 
46
48
  """
47
49
 
50
+ # A class default rather than an ``__init__`` assignment, so a subclass that
51
+ # skips ``__init__`` and a tree pickled before this existed can read it.
52
+ interpolated: bool = False
53
+
48
54
  def __init__(self, name: str, data: dict, file_path: Optional[str] = None) -> None:
49
55
  self.name: str = name
50
56
  self.file_path: Optional[str] = file_path
@@ -124,7 +130,8 @@ class Parameter(AtInstantLike):
124
130
  clone = empty_clone(self)
125
131
  clone.__dict__ = self.__dict__.copy()
126
132
 
127
- clone.metadata = copy.deepcopy(self.metadata)
133
+ # Own dict, shared values: see ParameterAtInstant.clone.
134
+ clone.metadata = copy.copy(self.metadata)
128
135
  clone.values_list = [
129
136
  parameter_at_instant.clone() for parameter_at_instant in self.values_list
130
137
  ]
@@ -76,5 +76,7 @@ class ParameterAtInstant:
76
76
  def clone(self) -> "ParameterAtInstant":
77
77
  clone = commons.empty_clone(self)
78
78
  clone.__dict__ = self.__dict__.copy()
79
- clone.metadata = copy.deepcopy(self.metadata)
79
+ # The clone gets its own metadata dict, but shares the values in it
80
+ # with this one. To change a nested value, replace its key.
81
+ clone.metadata = copy.copy(self.metadata)
80
82
  return clone
@@ -204,7 +204,8 @@ class ParameterNode(AtInstantLike):
204
204
  clone = commons.empty_clone(self)
205
205
  clone.__dict__ = self.__dict__.copy()
206
206
 
207
- clone.metadata = copy.deepcopy(self.metadata)
207
+ # Own dict, shared values: see ParameterAtInstant.clone.
208
+ clone.metadata = copy.copy(self.metadata)
208
209
  clone.children = {key: child.clone() for key, child in self.children.items()}
209
210
  for child_key, child in clone.children.items():
210
211
  setattr(clone, child_key, child)
@@ -122,7 +122,8 @@ class ParameterScale(AtInstantLike):
122
122
  clone.brackets = [bracket.clone() for bracket in self.brackets]
123
123
  for bracket in clone.brackets:
124
124
  bracket.parent = clone
125
- clone.metadata = copy.deepcopy(self.metadata)
125
+ # Own dict, shared values: see ParameterAtInstant.clone.
126
+ clone.metadata = copy.copy(self.metadata)
126
127
 
127
128
  return clone
128
129
 
@@ -1,10 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ import gc
3
4
  import logging
4
5
  import sys
5
6
  import os
6
7
  import traceback
7
8
  import textwrap
9
+ from contextlib import contextmanager
8
10
  from typing import Dict, List
9
11
 
10
12
  import pytest
@@ -419,6 +421,53 @@ class OpenFiscaPlugin(object):
419
421
  )
420
422
 
421
423
 
424
+ # A cache miss forces a full collection only while the cache holds fewer than
425
+ # this many systems. That collection walks every object in the process, so
426
+ # each cached system makes it dearer, while the automatic collector's full
427
+ # collections grow rarer as the heap grows. In PR #643's model of
428
+ # policyengine-us-sized systems, 3 gave the least collection CPU over 16 and
429
+ # 32 misses; limits from 1 to 8 came within 20%, and no limit cost about three
430
+ # times as much.
431
+ _FULL_COLLECTION_CACHE_LIMIT = 3
432
+
433
+
434
+ @contextmanager
435
+ def _automatic_gc_paused(collect=True):
436
+ """Pause automatic garbage collection for a build, then maybe collect once.
437
+
438
+ Building a reform system copies the whole baseline. On policyengine-us
439
+ the copy's allocations set off six or seven full collections per build,
440
+ each walking every object in the process and freeing almost nothing.
441
+ Pausing collection skips them. When collection resumes, the copy's
442
+ objects pass through a young and a middle collection, and through a full
443
+ one only when CPython's growth rule allows it: an automatic full
444
+ collection waits until the objects moved into the oldest generation since
445
+ the last full collection number at least a quarter of those that survived
446
+ it.
447
+
448
+ With ``collect``, a build that returns ends with one ``gc.collect()``. That
449
+ full collection bypasses the growth rule and moves the copy straight into
450
+ the oldest generation, so its objects skip the young and middle
451
+ collections. It pays only while the copy is a large share of the heap, so
452
+ ``_get_tax_benefit_system`` asks for it only while the cache holds fewer
453
+ than ``_FULL_COLLECTION_CACHE_LIMIT`` systems and otherwise leaves the copy
454
+ to the automatic collector.
455
+
456
+ The caller's setting is restored when the build returns or raises. A
457
+ caller that had disabled collection gets no collection and keeps it
458
+ disabled, and a build that raises gets none.
459
+ """
460
+ was_enabled = gc.isenabled()
461
+ gc.disable()
462
+ try:
463
+ yield
464
+ if was_enabled and collect:
465
+ gc.collect()
466
+ finally:
467
+ if was_enabled:
468
+ gc.enable()
469
+
470
+
422
471
  def _get_tax_benefit_system(
423
472
  baseline,
424
473
  reforms,
@@ -444,20 +493,24 @@ def _get_tax_benefit_system(
444
493
  if cached is not None:
445
494
  return cached
446
495
 
447
- current_tax_benefit_system = baseline.clone()
496
+ # Only a cache miss builds a system, so only a miss touches collection.
497
+ # The count covers every baseline's entries.
498
+ cached_systems = sum(len(entry) for entry in _tax_benefit_system_cache.values())
499
+ with _automatic_gc_paused(collect=cached_systems < _FULL_COLLECTION_CACHE_LIMIT):
500
+ current_tax_benefit_system = baseline.clone()
448
501
 
449
- for reform_path in reforms:
450
- if isinstance(reform_path, str):
451
- current_tax_benefit_system = current_tax_benefit_system.apply_reform(
452
- reform_path
453
- )
454
- else:
455
- current_tax_benefit_system = reform_path(current_tax_benefit_system)
456
- current_tax_benefit_system._parameters_at_instant_cache = {}
502
+ for reform_path in reforms:
503
+ if isinstance(reform_path, str):
504
+ current_tax_benefit_system = current_tax_benefit_system.apply_reform(
505
+ reform_path
506
+ )
507
+ else:
508
+ current_tax_benefit_system = reform_path(current_tax_benefit_system)
509
+ current_tax_benefit_system._parameters_at_instant_cache = {}
457
510
 
458
- for extension in extensions:
459
- current_tax_benefit_system = current_tax_benefit_system.clone()
460
- current_tax_benefit_system.load_extension(extension)
511
+ for extension in extensions:
512
+ current_tax_benefit_system = current_tax_benefit_system.clone()
513
+ current_tax_benefit_system.load_extension(extension)
461
514
 
462
515
  if baseline_entry is None:
463
516
  baseline_entry = {}
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "policyengine-core"
3
- version = "3.34.0"
3
+ version = "3.34.2"
4
4
  description = "Core microsimulation engine enabling country-specific policy models."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -0,0 +1,385 @@
1
+ """A clone of a parameter tree owns its metadata dicts and shares their values.
2
+
3
+ ``clone`` on a node, parameter, dated value, scale or bracket gives every
4
+ object in the copy its own metadata dict, holding the same values as the
5
+ source's. So a key set, updated, popped or replaced on one side never shows
6
+ on the other, while a nested value (a list of references, a dict) is one
7
+ object for both until a key is replaced. ``interpolate_parameters`` marks the
8
+ parameter it has interpolated, not the ``interpolation`` dict, for that reason.
9
+
10
+ ``test_parameter_metadata_clone_property.py`` checks the same over random
11
+ trees and edits, against a reference clone that deep-copies metadata.
12
+ """
13
+
14
+ import copy
15
+
16
+ import pytest
17
+
18
+ from policyengine_core.country_template import CountryTaxBenefitSystem
19
+ from policyengine_core.country_template import entities as template_entities
20
+ from policyengine_core.parameters import (
21
+ Parameter,
22
+ ParameterAtInstant,
23
+ ParameterNode,
24
+ interpolate_parameters,
25
+ propagate_parameter_metadata,
26
+ )
27
+ from policyengine_core.reforms import Reform
28
+ from policyengine_core.taxbenefitsystems import TaxBenefitSystem
29
+ from tests.fixtures.parameter_metadata_clones import build, snapshot
30
+
31
+ # Each kind of object that carries metadata, and how to reach it in the
32
+ # tree from ``build``.
33
+ KINDS = {
34
+ "node": lambda root: root.benefit,
35
+ "parameter": lambda root: root.benefit.amount,
36
+ "value": lambda root: root.benefit.amount.values_list[-1],
37
+ "scale": lambda root: root.tax,
38
+ "bracket": lambda root: root.tax.brackets[0],
39
+ "bracket component": lambda root: root.tax.brackets[0].rate,
40
+ }
41
+
42
+ # Each way to change a metadata dict through its own methods, or by
43
+ # replacing it.
44
+ EDITS = {
45
+ "set a key": lambda metadata: metadata.__setitem__("label", "Edited"),
46
+ "replace a nested value": lambda metadata: metadata.__setitem__(
47
+ "reference", [{"title": "Edited", "href": "https://example.gov/edited"}]
48
+ ),
49
+ "update": lambda metadata: metadata.update(label="Edited", added=[1]),
50
+ "setdefault": lambda metadata: metadata.setdefault("added", {"x": 1}),
51
+ "pop": lambda metadata: metadata.pop("reference", None),
52
+ "delete": lambda metadata: metadata.__delitem__(next(iter(metadata))),
53
+ "clear": lambda metadata: metadata.clear(),
54
+ }
55
+
56
+
57
+ def _metadata_of(item):
58
+ if not item.metadata:
59
+ # Give the object something to edit and to share.
60
+ item.metadata.update(label="Label", reference=[{"title": "Act"}])
61
+ return item.metadata
62
+
63
+
64
+ @pytest.mark.parametrize("edit", EDITS)
65
+ @pytest.mark.parametrize("kind", KINDS)
66
+ @pytest.mark.parametrize("edited_side", ["clone", "source"])
67
+ def test_a_metadata_edit_stays_on_its_side(kind, edit, edited_side):
68
+ source = build()
69
+ _metadata_of(KINDS[kind](source))
70
+ clone = source.clone()
71
+ edited, other = (clone, source) if edited_side == "clone" else (source, clone)
72
+ other_before = snapshot(other)
73
+ edited_metadata = KINDS[kind](edited).metadata
74
+ expected = copy.deepcopy(edited_metadata)
75
+ EDITS[edit](expected)
76
+
77
+ EDITS[edit](edited_metadata)
78
+
79
+ assert KINDS[kind](edited).metadata == expected
80
+ assert snapshot(other) == other_before
81
+
82
+
83
+ @pytest.mark.parametrize("kind", KINDS)
84
+ def test_a_clone_shares_nested_metadata_values_with_its_source(kind):
85
+ """The documented rule: own dict, shared values (no deep copy)."""
86
+ source = build()
87
+ item = KINDS[kind](source)
88
+ _metadata_of(item)
89
+ cloned = KINDS[kind](source.clone())
90
+
91
+ assert cloned.metadata is not item.metadata
92
+ assert cloned.metadata == item.metadata
93
+ for key, value in item.metadata.items():
94
+ assert cloned.metadata[key] is value
95
+
96
+
97
+ @pytest.mark.parametrize(
98
+ "make",
99
+ [
100
+ lambda: Parameter("p", {"2015-01-01": 1}),
101
+ lambda: ParameterAtInstant("p", "2015-01-01", data=1),
102
+ lambda: ParameterNode("n", data={"p": {"2015-01-01": 1}}),
103
+ ],
104
+ ids=["parameter", "value", "node"],
105
+ )
106
+ def test_a_clone_copies_metadata_as_copy_copy_does(make):
107
+ """``None`` stays ``None`` and a dict subclass keeps its type, as before."""
108
+
109
+ class Metadata(dict):
110
+ pass
111
+
112
+ item = make()
113
+ item.metadata = None
114
+ assert item.clone().metadata is None
115
+
116
+ item.metadata = Metadata(label="Label")
117
+ cloned = item.clone()
118
+ assert type(cloned.metadata) is Metadata
119
+ assert cloned.metadata == {"label": "Label"}
120
+ assert cloned.metadata is not item.metadata
121
+
122
+
123
+ def test_interpolating_a_tree_interpolates_the_clone_it_holds():
124
+ """The shape ``TaxBenefitSystem.__init__`` builds.
125
+
126
+ It adds a clone of the tree as ``parameters.baseline``, then interpolates
127
+ the whole tree. The clone shares the source's ``interpolation`` dict, so
128
+ marking that dict complete in place would skip whichever copy came second.
129
+ """
130
+ root = build()
131
+ root.add_child("baseline", root.clone())
132
+
133
+ interpolate_parameters(root)
134
+
135
+ for amount in (root.benefit.amount, root.baseline.benefit.amount):
136
+ assert amount("2016-06-01") == 110
137
+ assert amount("2018-06-01") == 130
138
+ assert amount.interpolated
139
+
140
+
141
+ def test_a_tax_benefit_system_interpolates_its_baseline_copy(tmp_path):
142
+ (tmp_path / "amount.yaml").write_text(
143
+ "description: An interpolated amount.\n"
144
+ "metadata:\n"
145
+ " interpolation:\n"
146
+ " interval: year\n"
147
+ "values:\n"
148
+ " 2015-01-01: 100\n"
149
+ " 2019-01-01: 140\n"
150
+ )
151
+
152
+ class System(TaxBenefitSystem):
153
+ entities = template_entities.entities
154
+ parameters_dir = str(tmp_path)
155
+
156
+ system = System()
157
+
158
+ assert system.parameters.amount("2016-06-01") == 110
159
+ assert system.parameters.baseline.amount("2016-06-01") == 110
160
+
161
+
162
+ def test_a_tax_benefit_system_interpolates_each_parameter_once(tmp_path):
163
+ """``TaxBenefitSystem.__init__`` propagates metadata again after interpolating.
164
+
165
+ That gives each parameter the node's ``interpolation`` dict again, so a
166
+ mark on the parameter's own copy of the dict would be lost, and the next
167
+ interpolation would add every entry a second time.
168
+ """
169
+ node = tmp_path / "node"
170
+ node.mkdir()
171
+ (node / "index.yaml").write_text(
172
+ "metadata:\n"
173
+ " propagate_metadata_to_children: true\n"
174
+ " interpolation:\n"
175
+ " interval: year\n"
176
+ )
177
+ for name, start, end in (("a", 100, 140), ("b", 200, 280)):
178
+ (node / f"{name}.yaml").write_text(
179
+ "description: An amount.\n"
180
+ "values:\n"
181
+ f" 2015-01-01: {start}\n"
182
+ f" 2019-01-01: {end}\n"
183
+ )
184
+
185
+ class System(TaxBenefitSystem):
186
+ entities = template_entities.entities
187
+ parameters_dir = str(tmp_path)
188
+
189
+ system = System()
190
+ before = snapshot(system.parameters)
191
+
192
+ interpolate_parameters(system.parameters)
193
+
194
+ assert snapshot(system.parameters) == before
195
+ for tree in (system.parameters, system.parameters.baseline):
196
+ assert len(tree.node.a.values_list) == 5
197
+ assert tree.node.a("2016-06-01") == 110
198
+ assert tree.node.b("2016-06-01") == 220
199
+
200
+
201
+ def test_interpolating_writes_no_metadata():
202
+ root = propagate_parameter_metadata(build())
203
+ root.add_child("baseline", root.clone())
204
+ metadata_before = [
205
+ (item, copy.deepcopy(item.metadata)) for item in root.get_descendants()
206
+ ]
207
+
208
+ interpolate_parameters(root)
209
+
210
+ assert root.allowance.couple("2016-06-01") == 220
211
+ for item, metadata in metadata_before:
212
+ assert item.metadata == metadata
213
+
214
+
215
+ def test_every_parameter_a_node_propagates_interpolation_to_is_interpolated():
216
+ """Propagation gives each child the node's ``interpolation`` dict.
217
+
218
+ Marking that one dict complete skipped every child after the first.
219
+ """
220
+ root = ParameterNode(
221
+ data={
222
+ "node": {
223
+ "metadata": {
224
+ "propagate_metadata_to_children": True,
225
+ "interpolation": {"interval": "year"},
226
+ },
227
+ "a": {"values": {"2015-01-01": 100, "2019-01-01": 140}},
228
+ "b": {"values": {"2015-01-01": 200, "2019-01-01": 280}},
229
+ }
230
+ }
231
+ )
232
+
233
+ interpolate_parameters(propagate_parameter_metadata(root))
234
+
235
+ assert root.node.a("2016-06-01") == 110
236
+ assert root.node.b("2016-06-01") == 220
237
+
238
+
239
+ def test_interpolating_a_clone_leaves_its_source_uninterpolated():
240
+ source = build()
241
+ clone = source.clone()
242
+ source_before = snapshot(source)
243
+
244
+ interpolate_parameters(clone)
245
+
246
+ assert clone.benefit.amount("2016-06-01") == 110
247
+ assert snapshot(source) == source_before
248
+ assert not source.benefit.amount.interpolated
249
+ # And the source still interpolates when asked.
250
+ interpolate_parameters(source)
251
+ assert source.benefit.amount("2016-06-01") == 110
252
+
253
+
254
+ def test_a_parameter_interpolates_again_once_its_flag_is_cleared():
255
+ root = ParameterNode(
256
+ data={
257
+ "amount": {
258
+ "metadata": {"interpolation": {"interval": "year"}},
259
+ "values": {"2015-01-01": 100, "2015-07-01": 200},
260
+ }
261
+ }
262
+ )
263
+ interpolate_parameters(root)
264
+ assert len(root.amount.values_list) == 2
265
+
266
+ root.amount.metadata["interpolation"] = {"interval": "month"}
267
+ root.amount.interpolated = False
268
+ interpolate_parameters(root)
269
+
270
+ assert len(root.amount.values_list) == 7
271
+ assert root.amount("2015-06-01") == pytest.approx(100 + 100 * 5 / 6)
272
+
273
+
274
+ def test_a_completed_key_in_the_metadata_still_stops_interpolation():
275
+ """A tree pickled by an older Core carries the key its interpolation wrote."""
276
+ root = ParameterNode(
277
+ data={
278
+ "amount": {
279
+ "metadata": {"interpolation": {"interval": "year", "completed": True}},
280
+ "values": {"2015-01-01": 100, "2019-01-01": 140},
281
+ }
282
+ }
283
+ )
284
+
285
+ interpolate_parameters(root)
286
+
287
+ assert len(root.amount.values_list) == 2
288
+
289
+
290
+ def test_a_parameter_that_skipped_init_interpolates():
291
+ """A subclass can skip ``Parameter.__init__``.
292
+
293
+ So can a parameter pickled before ``interpolated`` existed. Neither has
294
+ the attribute on the instance.
295
+ """
296
+ source = build().benefit.amount
297
+ parameter = Parameter.__new__(Parameter)
298
+ parameter.__dict__.update(
299
+ {key: value for key, value in vars(source).items() if key != "interpolated"}
300
+ )
301
+ root = ParameterNode(data={})
302
+ root.add_child("amount", parameter)
303
+
304
+ interpolate_parameters(root)
305
+
306
+ assert parameter("2016-06-01") == 110
307
+
308
+
309
+ @pytest.mark.parametrize(
310
+ "copy_tree",
311
+ [lambda tree: tree.clone(), copy.deepcopy],
312
+ ids=["clone", "deepcopy"],
313
+ )
314
+ def test_a_copy_of_an_interpolated_tree_is_not_interpolated_again(copy_tree):
315
+ source = interpolate_parameters(build())
316
+ clone = copy_tree(source)
317
+ values_before = snapshot(clone)
318
+
319
+ interpolate_parameters(clone)
320
+
321
+ assert snapshot(clone) == values_before
322
+
323
+
324
+ @pytest.mark.parametrize("edited_side", ["clone", "source"])
325
+ def test_propagating_metadata_on_one_side_leaves_the_other_alone(edited_side):
326
+ source = build()
327
+ clone = source.clone()
328
+ edited, other = (clone, source) if edited_side == "clone" else (source, clone)
329
+ other_before = snapshot(other)
330
+
331
+ propagate_parameter_metadata(edited)
332
+
333
+ assert edited.benefit.amount.metadata["notes"] == {"sources": ["benefit.pdf"]}
334
+ assert snapshot(other) == other_before
335
+
336
+
337
+ @pytest.mark.parametrize("edited_side", ["clone", "source"])
338
+ def test_tax_benefit_system_clones_keep_their_own_metadata(edited_side):
339
+ source = CountryTaxBenefitSystem()
340
+ clone = source.clone()
341
+ edited, other = (clone, source) if edited_side == "clone" else (source, clone)
342
+ other_before = snapshot(other.parameters)
343
+ tree = edited.parameters
344
+
345
+ tree.taxes.income_tax_rate.metadata["label"] = "Edited"
346
+ tree.taxes.income_tax_rate.values_list[0].metadata["note"] = "Edited"
347
+ tree.taxes.social_security_contribution.metadata.pop("reference", None)
348
+ tree.benefits.metadata.update(label="Edited", reference=[])
349
+
350
+ assert snapshot(other.parameters) == other_before
351
+ assert tree.taxes.income_tax_rate.metadata["label"] == "Edited"
352
+
353
+
354
+ def test_a_reform_that_edits_metadata_leaves_its_baseline_alone():
355
+ baseline = CountryTaxBenefitSystem()
356
+ baseline_before = snapshot(baseline.parameters)
357
+
358
+ class EditMetadata(Reform):
359
+ def apply(self):
360
+ rate = self.parameters.taxes.income_tax_rate
361
+ rate.metadata["label"] = "Reformed"
362
+ rate.values_list[0].metadata["note"] = "Reformed"
363
+ rate.update(period="year:2017:1", value=0.3)
364
+
365
+ reformed = EditMetadata(baseline)
366
+
367
+ assert reformed.parameters.taxes.income_tax_rate.metadata["label"] == "Reformed"
368
+ assert snapshot(baseline.parameters) == baseline_before
369
+
370
+
371
+ def test_cloning_a_parameter_tree_deep_copies_no_metadata(monkeypatch):
372
+ """The copy that dominated the cost of cloning a large tree is gone."""
373
+ tree = CountryTaxBenefitSystem().parameters
374
+ calls = []
375
+ deepcopy = copy.deepcopy
376
+
377
+ def counting_deepcopy(*args, **kwargs):
378
+ calls.append(args[0])
379
+ return deepcopy(*args, **kwargs)
380
+
381
+ monkeypatch.setattr(copy, "deepcopy", counting_deepcopy)
382
+ clone = tree.clone()
383
+
384
+ assert calls == []
385
+ assert snapshot(clone) == snapshot(tree)