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