policyengine-core 3.26.3__tar.gz → 3.26.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/CHANGELOG.md +7 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/PKG-INFO +1 -1
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_structures/parameter_node_metadata.py +2 -2
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/config.py +24 -9
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/homogenize_parameters.py +90 -2
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/test_runner.py +16 -3
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/pyproject.toml +1 -1
- policyengine_core-3.26.4/tests/core/test_parameter_security.py +130 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tools/test_runner/test_yaml_runner.py +107 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/ISSUE_TEMPLATE.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/bump_version.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/changelog_template.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/get-changelog-diff.sh +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/has-functional-changes.sh +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/is-version-number-acceptable.sh +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/publish-git-tag.sh +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/workflows/pr.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/workflows/push.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.gitignore +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/.python-version +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/AGENTS.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/CLAUDE.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/CONTRIBUTING.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/LICENSE +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/MANIFEST.in +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/Makefile +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/README.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/_build/logs/myst.build.json +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/changelog.d/.gitkeep +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/_config.yml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/_static/style.css +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/_toc.yml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/add_plotly_to_book.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/contributing/intro.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/engineering/skills/README.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/engineering/skills/documentation_review.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/engineering/skills/github-prs.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/engineering/skills/testing.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/intro.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/logo.png +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/commons.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/country_template.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/data.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/data_storage.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/entities.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/enums.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/errors.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/experimental.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/extension_template.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/holders.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/parameters.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/periods.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/populations.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/projectors.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/reforms.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/scripts.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/simulations.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/taxbenefitsystems.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/taxscales.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/tools.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/tracers.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/types.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/variables.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/python_api/warnings.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/usage/country.ipynb +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/usage/datasets.ipynb +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/usage/parameters.md +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/usage/reforms.ipynb +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/docs/usage/simulation.ipynb +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/mypy.ini +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/build_metadata.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/charts/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/charts/api.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/charts/bar.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/charts/formatting.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/commons/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/commons/formulas.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/commons/misc.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/commons/rates.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/constants.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/data/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/data/datasets/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/data/datasets/country_template_dataset.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/entities.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/modelled_policies.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/basic_income.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/housing_allowance.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/index.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/parenting_allowance/amount.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/benefits/parenting_allowance/income_threshold.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/general/age_of_majority.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/general/age_of_retirement.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/taxes/housing_tax.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/taxes/income_tax_rate.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/parameters/taxes/social_security_contribution.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/add_dynamic_variable.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/add_new_tax.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/flat_social_security_contribution.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/modify_social_security_taxation.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/reforms/removal_basic_income.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/situation_examples/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/situation_examples/couple.json +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/situation_examples/housing.json +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/situation_examples/single.json +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/age.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/basic_income.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/disposable_income.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/housing_allowance.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/housing_tax.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/income_tax.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/reforms/add_dynamic_variable.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/reforms/add_new_tax.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/reforms/modify_social_security_taxation.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/situations/income_tax.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/situations/parenting_allowance.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/social_security_contribution.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/tests/test_microsimulation.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/benefits.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/demographics.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/housing.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/ids.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/income.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/stats.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/country_template/variables/taxes.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data/dataset.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_storage/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_storage/in_memory_storage.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_storage/on_disk_storage.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_structures/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_structures/parameter_metadata.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_structures/reference.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/data_structures/unit.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/entities/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/entities/entity.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/entities/group_entity.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/entities/helpers.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/entities/role.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/enums/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/enums/config.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/enums/enum.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/enums/enum_array.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/cycle_error.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/empty_argument_error.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/nan_creation_error.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/parameter_not_found_error.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/parameter_parsing_error.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/period_mismatch_error.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/situation_parsing_error.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/spiral_error.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/variable_name_conflict_error.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/errors/variable_not_found_error.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/experimental/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/experimental/memory_config.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/extension_template/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/extension_template/local_benefit.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/extension_template/parameters/local_town/child_allowance/amount.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/extension_template/parameters/local_town/child_allowance/index.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/extension_template/parameters/local_town/index.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/extension_template/tests/local_benefit.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/holders/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/holders/helpers.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/holders/holder.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/model_api.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/at_instant_like.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/helpers.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/get_parameter.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/interpolate_parameters.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/propagate_parameter_metadata.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/operations/uprate_parameters.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_at_instant.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_node.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_node_at_instant.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_scale.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/parameter_scale_bracket.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/parameters/vectorial_parameter_node_at_instant.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/periods/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/periods/config.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/periods/helpers.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/periods/instant_.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/periods/period_.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/populations/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/populations/config.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/populations/group_population.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/populations/population.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/projectors/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/projectors/entity_to_person_projector.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/projectors/first_person_to_entity_projector.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/projectors/helpers.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/projectors/projector.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/projectors/unique_role_to_entity_projector.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/reforms/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/reforms/reform.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/scripts/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/scripts/assets/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/scripts/assets/index.html +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/scripts/policyengine_command.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/scripts/run_data.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/scripts/run_test.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/scripts/simulation_generator.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/simulations/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/simulations/helpers.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/simulations/individual_sim.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/simulations/microsimulation.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/simulations/simulation.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/simulations/simulation_builder.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/simulations/simulation_macro_cache.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxbenefitsystems/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxbenefitsystems/tax_benefit_system.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/abstract_rate_tax_scale.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/abstract_tax_scale.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/amount_tax_scale_like.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/helpers.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/linear_average_rate_tax_scale.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/marginal_amount_tax_scale.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/marginal_rate_tax_scale.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/rate_tax_scale_like.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/single_amount_tax_scale.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/taxscales/tax_scale_like.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/google_cloud.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/hugging_face.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/simulation_dumper.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/test_from_situation.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/win_file_manager.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/computation_log.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/flat_trace.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/full_tracer.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/performance_log.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/simple_tracer.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/trace_node.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/tracing_parameter_node_at_instant.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tracers/variable_graph.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/types/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/types/data_types/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/types/data_types/arrays.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/variables/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/variables/config.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/variables/defined_for.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/variables/helpers.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/variables/typing.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/variables/variable.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/warnings/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/warnings/libyaml_warning.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/warnings/memory_config_warning.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/warnings/tempfile_warning.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/pytest.ini +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/test.ipynb +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/conftest.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/commons/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/commons/test_between_function.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/commons/test_formulas.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/commons/test_is_in_function.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/commons/test_random_seed.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/commons/test_rates.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/data/test_dataset.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/enums/test_enum.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/model_api/test_index_.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/array_type.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/duplicate_key.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/filesystem_hierarchy/empty_index_file/index.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/filesystem_hierarchy/node1/param.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/indentation.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/missing_value.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/parameter_for_unit_propagation.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/test_parameter_clone.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/test_parameter_validation.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/test_propagate_units.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/unexpected_key_in_parameter.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/unexpected_key_in_scale.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/unexpected_key_in_value_at_instant.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/unexpected_key_in_value_history.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_date.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_scale.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_bracket.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_brackets.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_parameter.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_scale.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_type_in_value_history.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/wrong_value.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameter_validation/yaml_hierarchy/node1.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters/operations/test_interpolation.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters/operations/test_nesting.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters/operations/test_propagation.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters/operations/test_uprating.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters/test_numpy2_structured_arrays.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/bareme.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/local_tax.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/rate.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/parameters_fancy_indexing/test_fancy_indexing.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_abstract_rate_tax_scale.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_abstract_tax_scale.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_linear_average_rate_tax_scale.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_marginal_amount_tax_scale.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_marginal_rate_tax_scale.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_rate_tax_scale_like.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_single_amount_tax_scale.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tax_scales/test_tax_scales_commons.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_apply_reform_invalidates_cache.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_apply_reform_preserves_user_inputs.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_assert_near_precision.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_axes.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_bincount_minlength.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_build_metadata.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_calculate_output.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_countries.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_cycles.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_dataset_getattr.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_dump_restore.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_entities.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_eternity_subperiods.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_extensions.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_fast_cache.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_fast_cache_guards.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_formulas.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_holder_branch_fallback.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_holders.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_macro_cache_not_singleton.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_medium_fixes.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_microsimulation_person_accessor.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_opt_out_cache.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_pandas3_compatibility.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_parameters.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_periods.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_projectors.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_reform_parameter_isolation.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_reforms.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_simulation_builder.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_simulations.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_stable_hash_seed.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_storage_delete_branch.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_subsample_invalidates_cache.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_tax_benefit_system_cache_identity.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_tracers.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/test_yaml.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tools/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tools/test_assert_near.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tools/test_google_cloud.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/tools/test_hugging_face.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/variables/test_adds.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/variables/test_annualize.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/variables/test_bounds.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/variables/test_defined_for.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/variables/test_subtracts.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/variables/test_subtracts_sign.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/core/variables/test_variables.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/appclient.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/entities.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/simulations.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/taxbenefitsystems.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/variables.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/__init__.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/directory/subdirectory/test_4.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/directory/test_1.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/directory/test_2.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/failing_test_absolute_error_margin.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/failing_test_relative_error_margin.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_absolute_error_margin.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_failure.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_name_filter.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_relative_error_margin.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_success.yml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_with_anchors.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_with_extension.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_with_reform.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/fixtures/yaml_tests/test_with_reform_2.yaml +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/smoke/test_country_init.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/tests/smoke/test_us.py +0 -0
- {policyengine_core-3.26.3 → policyengine_core-3.26.4}/uv.lock +0 -0
|
@@ -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
|
|
{policyengine_core-3.26.3 → 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
|
+
)
|
{policyengine_core-3.26.3 → policyengine_core-3.26.4}/policyengine_core/tools/test_runner.py
RENAMED
|
@@ -31,7 +31,7 @@ def import_yaml():
|
|
|
31
31
|
import yaml
|
|
32
32
|
|
|
33
33
|
try:
|
|
34
|
-
from yaml import
|
|
34
|
+
from yaml import CSafeLoader as Loader
|
|
35
35
|
except ImportError:
|
|
36
36
|
log.warning(
|
|
37
37
|
" "
|
|
@@ -126,7 +126,7 @@ class YamlFile(pytest.File):
|
|
|
126
126
|
def collect(self):
|
|
127
127
|
try:
|
|
128
128
|
tests = yaml.load(self.path.open(), Loader=Loader)
|
|
129
|
-
except (yaml.
|
|
129
|
+
except (yaml.YAMLError, TypeError):
|
|
130
130
|
message = os.linesep.join(
|
|
131
131
|
[
|
|
132
132
|
traceback.format_exc(),
|
|
@@ -139,6 +139,11 @@ class YamlFile(pytest.File):
|
|
|
139
139
|
tests: List[Dict] = [tests]
|
|
140
140
|
|
|
141
141
|
for test in tests:
|
|
142
|
+
if not isinstance(test, dict):
|
|
143
|
+
raise ValueError(
|
|
144
|
+
f"'{self.path}' is not a valid YAML test file. "
|
|
145
|
+
"Expected a mapping or a list of mappings."
|
|
146
|
+
)
|
|
142
147
|
if not self.should_ignore(test):
|
|
143
148
|
yield YamlItem.from_parent(
|
|
144
149
|
self,
|
|
@@ -150,11 +155,19 @@ class YamlFile(pytest.File):
|
|
|
150
155
|
|
|
151
156
|
def should_ignore(self, test):
|
|
152
157
|
name_filter = self.options.get("name_filter")
|
|
158
|
+
keywords = test.get("keywords", [])
|
|
159
|
+
if keywords is None:
|
|
160
|
+
keywords = []
|
|
161
|
+
if not isinstance(keywords, list):
|
|
162
|
+
raise ValueError(
|
|
163
|
+
f"'{self.path}' is not a valid YAML test file. "
|
|
164
|
+
"'keywords' must be a list."
|
|
165
|
+
)
|
|
153
166
|
return (
|
|
154
167
|
name_filter is not None
|
|
155
168
|
and name_filter not in os.path.splitext(self.fspath.basename)[0]
|
|
156
169
|
and name_filter not in test.get("name", "")
|
|
157
|
-
and name_filter not in
|
|
170
|
+
and name_filter not in keywords
|
|
158
171
|
)
|
|
159
172
|
|
|
160
173
|
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from policyengine_core.errors import ParameterParsingError
|
|
4
|
+
from policyengine_core.parameters import ParameterNode, homogenize_parameter_structures
|
|
5
|
+
from policyengine_core.parameters.helpers import _load_yaml_file
|
|
6
|
+
from policyengine_core.parameters.operations.homogenize_parameters import (
|
|
7
|
+
MAX_DYNAMIC_BREAKDOWN_VALUES,
|
|
8
|
+
evaluate_dynamic_breakdown,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_parameter_yaml_loader_rejects_python_object_tags(tmp_path, monkeypatch):
|
|
13
|
+
calls = []
|
|
14
|
+
|
|
15
|
+
monkeypatch.setattr(
|
|
16
|
+
"os.system",
|
|
17
|
+
lambda command: calls.append(command) or 0,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
yaml_path = tmp_path / "malicious.yaml"
|
|
21
|
+
yaml_path.write_text(
|
|
22
|
+
'!!python/object/apply:os.system ["echo pwned"]\n',
|
|
23
|
+
encoding="utf-8",
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
with pytest.raises(ParameterParsingError):
|
|
27
|
+
_load_yaml_file(str(yaml_path))
|
|
28
|
+
|
|
29
|
+
assert calls == []
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_homogenize_parameter_structures_rejects_dynamic_breakdown_code(
|
|
33
|
+
monkeypatch,
|
|
34
|
+
):
|
|
35
|
+
eval_calls = []
|
|
36
|
+
|
|
37
|
+
monkeypatch.setattr(
|
|
38
|
+
"builtins.eval",
|
|
39
|
+
lambda expression, globals=None, locals=None: (
|
|
40
|
+
eval_calls.append(expression) or range(1, 4)
|
|
41
|
+
),
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
root = ParameterNode(
|
|
45
|
+
data={
|
|
46
|
+
"value_by_category": {
|
|
47
|
+
"metadata": {
|
|
48
|
+
"breakdown": ['__import__("os").system("echo pwned")'],
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
with pytest.raises(ValueError, match="breakdown"):
|
|
55
|
+
homogenize_parameter_structures(root, {}, default_value=0)
|
|
56
|
+
|
|
57
|
+
assert eval_calls == []
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_homogenize_parameter_structures_rejects_oversized_dynamic_breakdown():
|
|
61
|
+
root = ParameterNode(
|
|
62
|
+
data={
|
|
63
|
+
"value_by_category": {
|
|
64
|
+
"metadata": {
|
|
65
|
+
"breakdown": [f"list(range({MAX_DYNAMIC_BREAKDOWN_VALUES + 1}))"],
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
with pytest.raises(ValueError, match="exceeds the maximum"):
|
|
72
|
+
homogenize_parameter_structures(root, {}, default_value=0)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_homogenize_parameter_structures_rejects_overflowing_dynamic_breakdown():
|
|
76
|
+
huge_stop = "1" + ("0" * 100)
|
|
77
|
+
root = ParameterNode(
|
|
78
|
+
data={
|
|
79
|
+
"value_by_category": {
|
|
80
|
+
"metadata": {
|
|
81
|
+
"breakdown": [f"range(0, {huge_stop})"],
|
|
82
|
+
},
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
with pytest.raises(ValueError, match="too many values"):
|
|
88
|
+
homogenize_parameter_structures(root, {}, default_value=0)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def test_parameter_yaml_loader_rejects_implicit_duplicate_keys(tmp_path):
|
|
92
|
+
yaml_path = tmp_path / "duplicate-bools.yaml"
|
|
93
|
+
yaml_path.write_text("true: 1\nTrue: 2\n", encoding="utf-8")
|
|
94
|
+
|
|
95
|
+
with pytest.raises(ParameterParsingError, match="duplicate key"):
|
|
96
|
+
_load_yaml_file(str(yaml_path))
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def test_parameter_yaml_loader_allows_merge_key_overrides(tmp_path):
|
|
100
|
+
yaml_path = tmp_path / "merge-override.yaml"
|
|
101
|
+
yaml_path.write_text(
|
|
102
|
+
"defaults: &defaults\n value: 1\nmerged:\n <<: *defaults\n value: 2\n",
|
|
103
|
+
encoding="utf-8",
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
result = _load_yaml_file(str(yaml_path))
|
|
107
|
+
|
|
108
|
+
assert result["merged"]["value"] == 2
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def test_evaluate_dynamic_breakdown_allows_documented_safe_forms():
|
|
112
|
+
assert evaluate_dynamic_breakdown("list(range(1, 4))") == [1, 2, 3]
|
|
113
|
+
assert evaluate_dynamic_breakdown("[1, 2, -3]") == [1, 2, -3]
|
|
114
|
+
assert evaluate_dynamic_breakdown('("a", "b")') == ["a", "b"]
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def test_homogenize_parameter_structures_ignores_empty_breakdown_lists():
|
|
118
|
+
root = ParameterNode(
|
|
119
|
+
data={
|
|
120
|
+
"value_by_category": {
|
|
121
|
+
"metadata": {
|
|
122
|
+
"breakdown": [],
|
|
123
|
+
},
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
result = homogenize_parameter_structures(root, {}, default_value=0)
|
|
129
|
+
|
|
130
|
+
assert result is root
|
|
@@ -203,6 +203,113 @@ def test_performance_tables_option_output():
|
|
|
203
203
|
clean_performance_files(paths)
|
|
204
204
|
|
|
205
205
|
|
|
206
|
+
def test_yaml_runner_rejects_python_object_tags(tmp_path, monkeypatch):
|
|
207
|
+
calls = []
|
|
208
|
+
yaml_path = tmp_path / "malicious.yaml"
|
|
209
|
+
yaml_path.write_text(
|
|
210
|
+
'!!python/object/apply:os.system ["echo pwned"]\n',
|
|
211
|
+
encoding="utf-8",
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
monkeypatch.setattr(
|
|
215
|
+
"os.system",
|
|
216
|
+
lambda command: calls.append(command) or 0,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
malicious_yaml_file = object.__new__(YamlFile)
|
|
220
|
+
malicious_yaml_file.path = yaml_path
|
|
221
|
+
malicious_yaml_file.options = {}
|
|
222
|
+
malicious_yaml_file.tax_benefit_system = TaxBenefitSystem()
|
|
223
|
+
|
|
224
|
+
with pytest.raises(ValueError):
|
|
225
|
+
list(malicious_yaml_file.collect())
|
|
226
|
+
|
|
227
|
+
assert calls == []
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def test_yaml_runner_wraps_composer_errors(tmp_path):
|
|
231
|
+
yaml_path = tmp_path / "invalid-anchor.yaml"
|
|
232
|
+
yaml_path.write_text("value: *missing_anchor\n", encoding="utf-8")
|
|
233
|
+
|
|
234
|
+
invalid_yaml_file = object.__new__(YamlFile)
|
|
235
|
+
invalid_yaml_file.path = yaml_path
|
|
236
|
+
invalid_yaml_file.options = {}
|
|
237
|
+
invalid_yaml_file.tax_benefit_system = TaxBenefitSystem()
|
|
238
|
+
|
|
239
|
+
with pytest.raises(ValueError, match="not a valid YAML file"):
|
|
240
|
+
list(invalid_yaml_file.collect())
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def test_yaml_runner_rejects_scalar_roots(tmp_path):
|
|
244
|
+
yaml_path = tmp_path / "scalar.yaml"
|
|
245
|
+
yaml_path.write_text("foo\n", encoding="utf-8")
|
|
246
|
+
|
|
247
|
+
scalar_yaml_file = object.__new__(YamlFile)
|
|
248
|
+
scalar_yaml_file.path = yaml_path
|
|
249
|
+
scalar_yaml_file.options = {}
|
|
250
|
+
scalar_yaml_file.tax_benefit_system = TaxBenefitSystem()
|
|
251
|
+
|
|
252
|
+
with pytest.raises(ValueError, match="list of mappings"):
|
|
253
|
+
list(scalar_yaml_file.collect())
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def test_yaml_runner_rejects_scalar_keywords(tmp_path):
|
|
257
|
+
yaml_path = tmp_path / "invalid-keywords.yaml"
|
|
258
|
+
yaml_path.write_text(
|
|
259
|
+
"name: Example\nkeywords: 0\noutput: {}\n",
|
|
260
|
+
encoding="utf-8",
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
invalid_yaml_file = object.__new__(YamlFile)
|
|
264
|
+
invalid_yaml_file.path = yaml_path
|
|
265
|
+
invalid_yaml_file.options = {"name_filter": "missing"}
|
|
266
|
+
invalid_yaml_file.tax_benefit_system = TaxBenefitSystem()
|
|
267
|
+
|
|
268
|
+
with pytest.raises(ValueError, match="'keywords' must be a list"):
|
|
269
|
+
list(invalid_yaml_file.collect())
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def test_yaml_runner_allows_yaml_merge_anchors(tmp_path):
|
|
273
|
+
yaml_path = tmp_path / "anchors.yaml"
|
|
274
|
+
yaml_path.write_text(
|
|
275
|
+
"""
|
|
276
|
+
- name: define anchor
|
|
277
|
+
input:
|
|
278
|
+
persons: &persons
|
|
279
|
+
Alicia:
|
|
280
|
+
salary: 4000
|
|
281
|
+
households:
|
|
282
|
+
household:
|
|
283
|
+
parents: [Alicia]
|
|
284
|
+
output:
|
|
285
|
+
salary: 4000
|
|
286
|
+
|
|
287
|
+
- name: merge anchor
|
|
288
|
+
input:
|
|
289
|
+
persons:
|
|
290
|
+
<<: *persons
|
|
291
|
+
households:
|
|
292
|
+
household:
|
|
293
|
+
parents: [Alicia]
|
|
294
|
+
output:
|
|
295
|
+
salary: 4000
|
|
296
|
+
""".strip(),
|
|
297
|
+
encoding="utf-8",
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
yaml_file = object.__new__(YamlFile)
|
|
301
|
+
yaml_file.config = None
|
|
302
|
+
yaml_file.session = None
|
|
303
|
+
yaml_file._nodeid = "anchors"
|
|
304
|
+
yaml_file.path = yaml_path
|
|
305
|
+
yaml_file.options = {}
|
|
306
|
+
yaml_file.tax_benefit_system = TaxBenefitSystem()
|
|
307
|
+
|
|
308
|
+
collected = list(yaml_file.collect())
|
|
309
|
+
|
|
310
|
+
assert len(collected) == 2
|
|
311
|
+
|
|
312
|
+
|
|
206
313
|
def clean_performance_files(paths: List[str]):
|
|
207
314
|
for path in paths:
|
|
208
315
|
if os.path.isfile(path):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{policyengine_core-3.26.3 → policyengine_core-3.26.4}/.github/is-version-number-acceptable.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|