policyengine-core 3.26.2__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.
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/CHANGELOG.md +15 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/PKG-INFO +1 -1
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/data_structures/parameter_node_metadata.py +2 -2
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/holders/helpers.py +19 -5
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/holders/holder.py +37 -18
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/config.py +24 -9
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/homogenize_parameters.py +90 -2
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/uprate_parameters.py +171 -127
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_node.py +1 -1
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_scale_bracket.py +1 -1
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/simulations/simulation.py +40 -12
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tools/test_runner.py +16 -3
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/pyproject.toml +1 -1
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameters/operations/test_uprating.py +100 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_apply_reform_preserves_user_inputs.py +111 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_holder_branch_fallback.py +15 -0
- policyengine_core-3.26.4/tests/core/test_parameter_security.py +130 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/tools/test_runner/test_yaml_runner.py +107 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/.github/ISSUE_TEMPLATE.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/.github/bump_version.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/.github/changelog_template.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/.github/get-changelog-diff.sh +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/.github/has-functional-changes.sh +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/.github/is-version-number-acceptable.sh +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/.github/publish-git-tag.sh +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/.github/workflows/pr.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/.github/workflows/push.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/.gitignore +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/.python-version +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/AGENTS.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/CLAUDE.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/CONTRIBUTING.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/LICENSE +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/MANIFEST.in +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/Makefile +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/README.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/_build/logs/myst.build.json +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/changelog.d/.gitkeep +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/_config.yml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/_static/style.css +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/_toc.yml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/add_plotly_to_book.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/contributing/intro.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/engineering/skills/README.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/engineering/skills/documentation_review.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/engineering/skills/github-prs.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/engineering/skills/testing.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/intro.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/logo.png +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/commons.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/country_template.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/data.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/data_storage.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/entities.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/enums.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/errors.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/experimental.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/extension_template.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/holders.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/parameters.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/periods.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/populations.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/projectors.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/reforms.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/scripts.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/simulations.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/taxbenefitsystems.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/taxscales.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/tools.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/tracers.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/types.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/variables.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/python_api/warnings.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/usage/country.ipynb +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/usage/datasets.ipynb +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/usage/parameters.md +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/usage/reforms.ipynb +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/docs/usage/simulation.ipynb +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/mypy.ini +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/build_metadata.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/charts/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/charts/api.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/charts/bar.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/charts/formatting.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/commons/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/commons/formulas.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/commons/misc.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/commons/rates.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/constants.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/data/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/data/datasets/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/data/datasets/country_template_dataset.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/entities.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/modelled_policies.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/basic_income.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/housing_allowance.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/index.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/parenting_allowance/amount.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/parenting_allowance/income_threshold.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/general/age_of_majority.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/general/age_of_retirement.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/taxes/housing_tax.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/taxes/income_tax_rate.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/taxes/social_security_contribution.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/add_dynamic_variable.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/add_new_tax.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/flat_social_security_contribution.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/modify_social_security_taxation.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/removal_basic_income.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/situation_examples/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/situation_examples/couple.json +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/situation_examples/housing.json +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/situation_examples/single.json +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/age.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/basic_income.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/disposable_income.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/housing_allowance.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/housing_tax.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/income_tax.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/reforms/add_dynamic_variable.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/reforms/add_new_tax.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/reforms/modify_social_security_taxation.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/situations/income_tax.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/situations/parenting_allowance.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/social_security_contribution.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/test_microsimulation.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/benefits.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/demographics.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/housing.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/ids.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/income.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/stats.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/taxes.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/data/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/data/dataset.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/data_storage/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/data_storage/in_memory_storage.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/data_storage/on_disk_storage.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/data_structures/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/data_structures/parameter_metadata.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/data_structures/reference.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/data_structures/unit.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/entities/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/entities/entity.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/entities/group_entity.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/entities/helpers.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/entities/role.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/enums/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/enums/config.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/enums/enum.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/enums/enum_array.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/errors/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/errors/cycle_error.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/errors/empty_argument_error.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/errors/nan_creation_error.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/errors/parameter_not_found_error.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/errors/parameter_parsing_error.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/errors/period_mismatch_error.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/errors/situation_parsing_error.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/errors/spiral_error.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/errors/variable_name_conflict_error.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/errors/variable_not_found_error.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/experimental/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/experimental/memory_config.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/extension_template/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/extension_template/local_benefit.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/extension_template/parameters/local_town/child_allowance/amount.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/extension_template/parameters/local_town/child_allowance/index.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/extension_template/parameters/local_town/index.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/extension_template/tests/local_benefit.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/holders/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/model_api.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/at_instant_like.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/helpers.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/get_parameter.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/interpolate_parameters.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/propagate_parameter_metadata.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_at_instant.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_node_at_instant.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_scale.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/vectorial_parameter_node_at_instant.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/periods/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/periods/config.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/periods/helpers.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/periods/instant_.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/periods/period_.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/populations/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/populations/config.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/populations/group_population.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/populations/population.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/projectors/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/projectors/entity_to_person_projector.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/projectors/first_person_to_entity_projector.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/projectors/helpers.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/projectors/projector.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/projectors/unique_role_to_entity_projector.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/reforms/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/reforms/reform.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/scripts/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/scripts/assets/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/scripts/assets/index.html +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/scripts/policyengine_command.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/scripts/run_data.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/scripts/run_test.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/scripts/simulation_generator.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/simulations/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/simulations/helpers.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/simulations/individual_sim.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/simulations/microsimulation.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/simulations/simulation_builder.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/simulations/simulation_macro_cache.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/taxbenefitsystems/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/taxbenefitsystems/tax_benefit_system.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/taxscales/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/taxscales/abstract_rate_tax_scale.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/taxscales/abstract_tax_scale.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/taxscales/amount_tax_scale_like.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/taxscales/helpers.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/taxscales/linear_average_rate_tax_scale.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/taxscales/marginal_amount_tax_scale.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/taxscales/marginal_rate_tax_scale.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/taxscales/rate_tax_scale_like.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/taxscales/single_amount_tax_scale.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/taxscales/tax_scale_like.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tools/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tools/google_cloud.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tools/hugging_face.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tools/simulation_dumper.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tools/test_from_situation.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tools/win_file_manager.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tracers/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tracers/computation_log.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tracers/flat_trace.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tracers/full_tracer.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tracers/performance_log.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tracers/simple_tracer.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tracers/trace_node.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tracers/tracing_parameter_node_at_instant.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/tracers/variable_graph.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/types/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/types/data_types/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/types/data_types/arrays.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/variables/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/variables/config.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/variables/defined_for.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/variables/helpers.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/variables/typing.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/variables/variable.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/warnings/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/warnings/libyaml_warning.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/warnings/memory_config_warning.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/warnings/tempfile_warning.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/pytest.ini +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/test.ipynb +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/conftest.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/commons/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/commons/test_between_function.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/commons/test_formulas.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/commons/test_is_in_function.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/commons/test_random_seed.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/commons/test_rates.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/data/test_dataset.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/enums/test_enum.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/model_api/test_index_.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/array_type.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/duplicate_key.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/filesystem_hierarchy/empty_index_file/index.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/filesystem_hierarchy/node1/param.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/indentation.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/missing_value.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/parameter_for_unit_propagation.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/test_parameter_clone.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/test_parameter_validation.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/test_propagate_units.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/unexpected_key_in_parameter.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/unexpected_key_in_scale.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/unexpected_key_in_value_at_instant.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/unexpected_key_in_value_history.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_date.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_scale.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_bracket.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_brackets.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_parameter.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_scale.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_value_history.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_value.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameter_validation/yaml_hierarchy/node1.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameters/operations/test_interpolation.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameters/operations/test_nesting.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameters/operations/test_propagation.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameters/test_numpy2_structured_arrays.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/bareme.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/local_tax.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/rate.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/test_fancy_indexing.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/tax_scales/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/tax_scales/test_abstract_rate_tax_scale.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/tax_scales/test_abstract_tax_scale.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/tax_scales/test_linear_average_rate_tax_scale.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/tax_scales/test_marginal_amount_tax_scale.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/tax_scales/test_marginal_rate_tax_scale.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/tax_scales/test_rate_tax_scale_like.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/tax_scales/test_single_amount_tax_scale.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/tax_scales/test_tax_scales_commons.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_apply_reform_invalidates_cache.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_assert_near_precision.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_axes.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_bincount_minlength.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_build_metadata.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_calculate_output.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_countries.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_cycles.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_dataset_getattr.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_dump_restore.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_entities.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_eternity_subperiods.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_extensions.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_fast_cache.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_fast_cache_guards.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_formulas.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_holders.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_macro_cache_not_singleton.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_medium_fixes.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_microsimulation_person_accessor.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_opt_out_cache.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_pandas3_compatibility.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_parameters.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_periods.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_projectors.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_reform_parameter_isolation.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_reforms.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_simulation_builder.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_simulations.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_stable_hash_seed.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_storage_delete_branch.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_subsample_invalidates_cache.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_tax_benefit_system_cache_identity.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_tracers.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/test_yaml.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/tools/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/tools/test_assert_near.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/tools/test_google_cloud.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/tools/test_hugging_face.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/variables/test_adds.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/variables/test_annualize.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/variables/test_bounds.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/variables/test_defined_for.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/variables/test_subtracts.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/variables/test_subtracts_sign.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/core/variables/test_variables.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/appclient.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/entities.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/simulations.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/taxbenefitsystems.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/variables.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/__init__.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/directory/subdirectory/test_4.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/directory/test_1.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/directory/test_2.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/failing_test_absolute_error_margin.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/failing_test_relative_error_margin.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_absolute_error_margin.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_failure.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_name_filter.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_relative_error_margin.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_success.yml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_with_anchors.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_with_extension.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_with_reform.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_with_reform_2.yaml +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/smoke/test_country_init.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/tests/smoke/test_us.py +0 -0
- {policyengine_core-3.26.2 → policyengine_core-3.26.4}/uv.lock +0 -0
|
@@ -1,3 +1,18 @@
|
|
|
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
|
+
|
|
8
|
+
## [3.26.3] - 2026-05-14
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Preserve values passed through dispatched `set_input` handlers across cache invalidation.
|
|
13
|
+
- Apply chained parameter uprating dependencies in deterministic dependency order.
|
|
14
|
+
|
|
15
|
+
|
|
1
16
|
## [3.26.2] - 2026-05-14
|
|
2
17
|
|
|
3
18
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: policyengine-core
|
|
3
|
-
Version: 3.26.
|
|
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) #
|
|
41
|
-
- [True, False] #
|
|
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
|
|
|
@@ -10,6 +10,18 @@ from policyengine_core.periods import Period
|
|
|
10
10
|
log = logging.getLogger(__name__)
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
def get_input_branch(holder: Holder) -> str:
|
|
14
|
+
simulation = getattr(holder, "simulation", None)
|
|
15
|
+
user_input_contexts = getattr(simulation, "_user_input_contexts", None)
|
|
16
|
+
if user_input_contexts:
|
|
17
|
+
return user_input_contexts[-1]
|
|
18
|
+
return "default"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_stored_array(holder: Holder, period: Period, branch_name: str) -> ArrayLike:
|
|
22
|
+
return holder._get_array_from_storage(period, branch_name)
|
|
23
|
+
|
|
24
|
+
|
|
13
25
|
def set_input_dispatch_by_period(holder: Holder, period: Period, array: ArrayLike):
|
|
14
26
|
"""
|
|
15
27
|
This function can be declared as a ``set_input`` attribute of a variable.
|
|
@@ -35,11 +47,12 @@ def set_input_dispatch_by_period(holder: Holder, period: Period, array: ArrayLik
|
|
|
35
47
|
after_instant = period.start.offset(period_size, period_unit)
|
|
36
48
|
|
|
37
49
|
# Cache the input data, skipping the existing cached months
|
|
50
|
+
branch_name = get_input_branch(holder)
|
|
38
51
|
sub_period = period.start.period(cached_period_unit)
|
|
39
52
|
while sub_period.start < after_instant:
|
|
40
|
-
existing_array = holder
|
|
53
|
+
existing_array = get_stored_array(holder, sub_period, branch_name)
|
|
41
54
|
if existing_array is None:
|
|
42
|
-
holder._set(sub_period, array)
|
|
55
|
+
holder._set(sub_period, array, branch_name)
|
|
43
56
|
else:
|
|
44
57
|
# The array of the current sub-period is reused for the next ones.
|
|
45
58
|
# TODO: refactor or document this behavior
|
|
@@ -72,11 +85,12 @@ def set_input_divide_by_period(holder: Holder, period: Period, array: ArrayLike)
|
|
|
72
85
|
after_instant = period.start.offset(period_size, period_unit)
|
|
73
86
|
|
|
74
87
|
# Count the number of elementary periods to change, and the difference with what is already known.
|
|
88
|
+
branch_name = get_input_branch(holder)
|
|
75
89
|
remaining_array = array.copy()
|
|
76
90
|
sub_period = period.start.period(cached_period_unit)
|
|
77
91
|
sub_periods_count = 0
|
|
78
92
|
while sub_period.start < after_instant:
|
|
79
|
-
existing_array = holder
|
|
93
|
+
existing_array = get_stored_array(holder, sub_period, branch_name)
|
|
80
94
|
if existing_array is not None:
|
|
81
95
|
remaining_array -= existing_array
|
|
82
96
|
else:
|
|
@@ -88,8 +102,8 @@ def set_input_divide_by_period(holder: Holder, period: Period, array: ArrayLike)
|
|
|
88
102
|
divided_array = remaining_array / sub_periods_count
|
|
89
103
|
sub_period = period.start.period(cached_period_unit)
|
|
90
104
|
while sub_period.start < after_instant:
|
|
91
|
-
if holder
|
|
92
|
-
holder._set(sub_period, divided_array)
|
|
105
|
+
if get_stored_array(holder, sub_period, branch_name) is None:
|
|
106
|
+
holder._set(sub_period, divided_array, branch_name)
|
|
93
107
|
sub_period = sub_period.offset(1)
|
|
94
108
|
elif not (remaining_array == 0).all():
|
|
95
109
|
raise ValueError(
|
|
@@ -94,6 +94,14 @@ class Holder:
|
|
|
94
94
|
if self._disk_storage:
|
|
95
95
|
self._disk_storage.delete(period, branch_name)
|
|
96
96
|
|
|
97
|
+
def _get_array_from_storage(
|
|
98
|
+
self, period: Period, branch_name: str = "default"
|
|
99
|
+
) -> ArrayLike:
|
|
100
|
+
value = self._memory_storage.get(period, branch_name)
|
|
101
|
+
if value is None and self._disk_storage:
|
|
102
|
+
value = self._disk_storage.get(period, branch_name)
|
|
103
|
+
return value
|
|
104
|
+
|
|
97
105
|
def get_array(self, period: Period, branch_name: str = "default") -> ArrayLike:
|
|
98
106
|
"""
|
|
99
107
|
Get the value of the variable for the given period.
|
|
@@ -102,7 +110,9 @@ class Holder:
|
|
|
102
110
|
"""
|
|
103
111
|
if self.variable.is_neutralized:
|
|
104
112
|
return self.default_array()
|
|
105
|
-
value = self.
|
|
113
|
+
value = self._get_array_from_storage(period, branch_name)
|
|
114
|
+
if value is not None:
|
|
115
|
+
return value
|
|
106
116
|
if value is None and branch_name != "default":
|
|
107
117
|
# Walk up ``simulation.parent_branch`` so nested branches inherit
|
|
108
118
|
# values from their parent (e.g. a ``no_salt`` branch cloned
|
|
@@ -121,17 +131,16 @@ class Holder:
|
|
|
121
131
|
else None
|
|
122
132
|
)
|
|
123
133
|
while parent is not None:
|
|
124
|
-
ancestor_value = self.
|
|
134
|
+
ancestor_value = self._get_array_from_storage(
|
|
135
|
+
period,
|
|
136
|
+
parent.branch_name,
|
|
137
|
+
)
|
|
125
138
|
if ancestor_value is not None:
|
|
126
139
|
return ancestor_value
|
|
127
140
|
parent = getattr(parent, "parent_branch", None)
|
|
128
|
-
default_value = self.
|
|
141
|
+
default_value = self._get_array_from_storage(period, "default")
|
|
129
142
|
if default_value is not None:
|
|
130
143
|
return default_value
|
|
131
|
-
if value is not None:
|
|
132
|
-
return value
|
|
133
|
-
if self._disk_storage:
|
|
134
|
-
return self._disk_storage.get(period, branch_name)
|
|
135
144
|
|
|
136
145
|
def get_memory_usage(self) -> dict:
|
|
137
146
|
"""
|
|
@@ -241,21 +250,23 @@ class Holder:
|
|
|
241
250
|
return warnings.warn(warning_message, Warning)
|
|
242
251
|
if self.variable.value_type in (float, int) and isinstance(array, str):
|
|
243
252
|
array = tools.eval_expression(array)
|
|
244
|
-
# Track user-provided inputs on the simulation so
|
|
245
|
-
# ``Simulation._invalidate_all_caches`` can preserve them across
|
|
246
|
-
# ``apply_reform``. ``Simulation.set_input`` also records this, but
|
|
247
|
-
# ``SimulationBuilder.finalize_variables_init`` (the situation-dict
|
|
248
|
-
# path) and country-package dataset loaders call
|
|
249
|
-
# ``holder.set_input`` directly, bypassing the simulation-level hook.
|
|
250
|
-
# Recording here covers both paths.
|
|
251
253
|
simulation = getattr(self, "simulation", None)
|
|
252
254
|
if simulation is not None:
|
|
253
255
|
if not hasattr(simulation, "_user_input_keys"):
|
|
254
256
|
simulation._user_input_keys = set()
|
|
255
|
-
simulation
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
257
|
+
if not hasattr(simulation, "_user_input_contexts"):
|
|
258
|
+
simulation._user_input_contexts = []
|
|
259
|
+
simulation._user_input_contexts.append(branch_name)
|
|
260
|
+
try:
|
|
261
|
+
if (
|
|
262
|
+
self.variable.set_input
|
|
263
|
+
and period.unit != self.variable.definition_period
|
|
264
|
+
):
|
|
265
|
+
return self.variable.set_input(self, period, array)
|
|
266
|
+
return self._set(period, array, branch_name)
|
|
267
|
+
finally:
|
|
268
|
+
if simulation is not None:
|
|
269
|
+
simulation._user_input_contexts.pop()
|
|
259
270
|
|
|
260
271
|
def _to_array(self, value: Any) -> ArrayLike:
|
|
261
272
|
if not isinstance(value, numpy.ndarray):
|
|
@@ -295,6 +306,10 @@ class Holder:
|
|
|
295
306
|
def _set(
|
|
296
307
|
self, period: Period, value: ArrayLike, branch_name: str = "default"
|
|
297
308
|
) -> None:
|
|
309
|
+
simulation = getattr(self, "simulation", None)
|
|
310
|
+
user_input_contexts = getattr(simulation, "_user_input_contexts", None)
|
|
311
|
+
if user_input_contexts and branch_name == "default":
|
|
312
|
+
branch_name = user_input_contexts[-1]
|
|
298
313
|
value = self._to_array(value)
|
|
299
314
|
if self.variable.definition_period != periods.ETERNITY:
|
|
300
315
|
if period is None:
|
|
@@ -313,6 +328,10 @@ class Holder:
|
|
|
313
328
|
self._disk_storage.put(value, period, branch_name)
|
|
314
329
|
else:
|
|
315
330
|
self._memory_storage.put(value, period, branch_name)
|
|
331
|
+
if user_input_contexts:
|
|
332
|
+
if not hasattr(simulation, "_user_input_keys"):
|
|
333
|
+
simulation._user_input_keys = set()
|
|
334
|
+
simulation._user_input_keys.add((self.variable.name, branch_name, period))
|
|
316
335
|
|
|
317
336
|
def put_in_cache(
|
|
318
337
|
self, value: ArrayLike, period: Period, branch_name: str = "default"
|
{policyengine_core-3.26.2 → policyengine_core-3.26.4}/policyengine_core/parameters/config.py
RENAMED
|
@@ -7,7 +7,7 @@ import yaml
|
|
|
7
7
|
from policyengine_core.warnings import LibYAMLWarning
|
|
8
8
|
|
|
9
9
|
try:
|
|
10
|
-
from yaml import
|
|
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
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
)
|