policyengine 6.3.2__tar.gz → 6.3.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-6.3.2 → policyengine-6.3.4}/CHANGELOG.md +20 -0
- {policyengine-6.3.2/src/policyengine.egg-info → policyengine-6.3.4}/PKG-INFO +1 -1
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/bundles.md +3 -1
- policyengine-6.3.4/docs/engineering/runbooks/us-legacy-spm-sources.md +122 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/microsim.md +61 -9
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/outputs.md +6 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/regions.md +9 -4
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/release-bundles.md +2 -1
- {policyengine-6.3.2 → policyengine-6.3.4}/examples/us_budgetary_impact.py +12 -3
- {policyengine-6.3.2 → policyengine-6.3.4}/pyproject.toml +1 -1
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/run_record.py +9 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/simulation.py +8 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/data/bundle/manifest.json +12 -12
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/data/bundle/uk.trace.tro.jsonld +5 -5
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/data/bundle/us.trace.tro.jsonld +5 -5
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/poverty.py +21 -1
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/common/model_version.py +23 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/us/datasets.py +178 -38
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/us/legacy_inputs.py +230 -12
- policyengine-6.3.4/src/policyengine/tax_benefit_models/us/legacy_spm/__init__.py +120 -0
- policyengine-6.3.4/src/policyengine/tax_benefit_models/us/legacy_spm/declarations.py +218 -0
- policyengine-6.3.4/src/policyengine/tax_benefit_models/us/legacy_spm/independence.py +121 -0
- policyengine-6.3.4/src/policyengine/tax_benefit_models/us/legacy_spm/model_adapter.py +337 -0
- policyengine-6.3.4/src/policyengine/tax_benefit_models/us/legacy_spm/record.py +167 -0
- policyengine-6.3.4/src/policyengine/tax_benefit_models/us/legacy_spm/registry.py +76 -0
- policyengine-6.3.4/src/policyengine/tax_benefit_models/us/legacy_spm/runs.py +140 -0
- policyengine-6.3.4/src/policyengine/tax_benefit_models/us/legacy_spm/universe.py +137 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/us/model.py +54 -4
- {policyengine-6.3.2 → policyengine-6.3.4/src/policyengine.egg-info}/PKG-INFO +1 -1
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine.egg-info/SOURCES.txt +13 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_poverty_run.py +4 -3
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_release_manifests.py +19 -5
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_us_legacy_inputs_integration.py +198 -0
- policyengine-6.3.4/tests/test_us_legacy_spm.py +565 -0
- policyengine-6.3.4/tests/test_us_legacy_spm_integration.py +772 -0
- policyengine-6.3.4/tests/test_us_legacy_spm_model_contract.py +243 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_us_regions.py +11 -8
- policyengine-6.3.4/tests/test_us_year_file_stamp.py +1021 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/uv.lock +1 -1
- {policyengine-6.3.2 → policyengine-6.3.4}/.claude/policyengine-guide.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.claude/quick-reference.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/CONTRIBUTING.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/bump_version.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/capture-version.sh +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/changelog_template.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/check-changelog.sh +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/copilot-instructions.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/dispatch-policyengine-release.sh +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/fetch_version.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/get-changelog-diff.sh +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/has-functional-changes.sh +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/is-version-number-acceptable.sh +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/publish-git-tag.sh +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/wait-for-pypi.sh +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/workflows/draft-pdf.yml +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/workflows/pr_code_changes.yaml +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/workflows/pr_docs_changes.yaml +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.github/workflows/push.yaml +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.gitignore +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/.python-version +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/AGENTS.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/CITATION.cff +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/CLAUDE.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/CODE_OF_CONDUCT.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/CONTRIBUTING.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/LICENSE +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/Makefile +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/README.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/architecture.png +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/architecture.svg +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/changelog.d/.gitkeep +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/.gitignore +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/_generator/README.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/_generator/build_reference.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/_quarto.yml +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/countries.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/data-publishing-design.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/decile-impact-spec.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/dev.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/engineering/runbooks/acs-local-wic-replacement.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/engineering/runbooks/build-m-us-populace-certification.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/engineering/runbooks/canonical-spm-development.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/engineering/skills/README.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/engineering/skills/data-certification.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/engineering/skills/github-prs.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/engineering/skills/repository-guidance.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/examples.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/getting-started.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/households.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/impact-analysis.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/index.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/methodology/index.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/methodology/model-architecture.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/methodology/us-health-costs.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/programs/index.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/programs/us-chip.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/reference/index.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/reforms.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/run-records.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/trace-case-study.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/docs/visualisation.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/examples/belgium_axiom_pilot.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/examples/employment_income_variation_uk.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/examples/employment_income_variation_us.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/examples/household_impact_example.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/examples/income_bands_uk.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/examples/income_distribution_us.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/examples/paper_repro_uk.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/examples/policy_change_uk.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/examples/speedtest_us_simulation.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/paper-preview.html +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/paper.bib +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/paper.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/scripts/bundle.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/scripts/certify_data_release.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/scripts/check_data_staleness.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/scripts/check_native_spm_loading.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/scripts/check_release_credentials.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/scripts/export_bundle_release_assets.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/scripts/generate_bundle_artifacts.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/scripts/generate_trace_tros.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/scripts/prepare_package_bundle_update.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/scripts/release_lock.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/scripts/spm_bundle.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/setup.cfg +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/bundle.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/cli.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/cache.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/dataset.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/dynamic.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/output.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/parameter.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/parameter_node.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/parameter_value.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/policy.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/region.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/scoping_strategy.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/spm.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/tax_benefit_model.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/tax_benefit_model_version.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/core/variable.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/countries/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/countries/uk/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/countries/uk/regions.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/countries/us/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/countries/us/data/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/countries/us/data/districts.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/countries/us/data/places.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/countries/us/data/states.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/countries/us/regions.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/data/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/data/schemas/trace_tro.schema.json +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/data/uk_geography_assets.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/derivations/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/derivations/narrate.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/derivations/trace.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/graph/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/graph/extractor.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/graph/graph.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/aggregate.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/change_aggregate.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/cliff_impact.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/congressional_district_impact.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/constituency_impact.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/decile_analysis.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/decile_grouping.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/decile_impact.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/extra_variables.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/inequality.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/intra_decile_impact.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/labor_supply_response.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/local_authority_impact.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/program_statistics.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/uk_geography_assets.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/outputs/uk_geography_impact.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/provenance/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/provenance/bundle_validation.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/provenance/certification.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/provenance/dataset_materialization.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/provenance/manifest.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/provenance/pyproject_pins.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/provenance/spm_configuration.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/provenance/trace.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/provenance/verify.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/provenance/zenodo.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/results/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/results/schema.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/results/trace_tro.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/results/tracking.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/be/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/be/datasets.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/be/model.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/common/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/common/axes.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/common/extra_variables.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/common/household.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/common/reform.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/common/result.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/uk/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/uk/analysis.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/uk/budget_reform_contract.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/uk/budget_reform_population.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/uk/datasets.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/uk/household.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/uk/model.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/us/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/us/analysis.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/us/household.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/tax_benefit_models/us/spm.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/utils/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/utils/dates.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/utils/design.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/utils/entity_utils.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/utils/errors.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/utils/hashing.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/utils/household_validation.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/utils/parameter_labels.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/utils/parametric_reforms.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine/utils/plotting.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine.egg-info/dependency_links.txt +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine.egg-info/entry_points.txt +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine.egg-info/requires.txt +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/src/policyengine.egg-info/top_level.txt +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/conftest.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/filtering_fixtures.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/household_calculator_snapshots/uk_couple_two_kids.json +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/household_calculator_snapshots/uk_model_surface.json +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/household_calculator_snapshots/uk_single_adult_employment_income.json +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/household_calculator_snapshots/uk_single_adult_no_income.json +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/household_calculator_snapshots/uk_single_parent_one_child.json +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/household_calculator_snapshots/us_married_two_kids_high_income.json +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/household_calculator_snapshots/us_model_surface.json +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/household_calculator_snapshots/us_single_adult_employment_income.json +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/household_calculator_snapshots/us_single_adult_no_income.json +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/household_calculator_snapshots/us_single_parent_one_child.json +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/parameter_labels_fixtures.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/parametric_reforms_fixtures.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/poverty_by_demographics_fixtures.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/region_fixtures.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/release_tros/README.md +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/release_tros/country-models.lock.toml +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/release_tros/manifest.json +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/release_tros/us-release_manifest.json +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/release_tros/us.trace.tro.jsonld +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/spm_development.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/us_reform_fixtures.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/fixtures/variable_label_fixtures.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_aggregate.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_be_axiom_pilot.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_budgetary_impact.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_bump_version.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_bundle.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_bundle_metadata.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_cache.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_certify_data_release.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_change_aggregate.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_cliff_impact.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_cliff_impact_analysis.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_congressional_district_impact.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_constituency_impact.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_dataset_materialization.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_dataset_persistence.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_dataset_runtime.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_dataset_source.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_decile_grouping.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_derivations.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_dict_reforms_on_simulation.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_entity_mapping.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_entity_utils.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_entity_utils_characterization.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_errors.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_extra_variables.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_filtering.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_generate_trace_tros.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_graph/__init__.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_graph/conftest.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_graph/test_extractor.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_household_calculator_snapshot.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_household_impact.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_inequality.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_intra_decile_impact.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_labor_supply_response.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_local_authority_impact.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_manifest_version_mismatch.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_models.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_pandas3_compatibility.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_parameter_labels.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_parameter_nodes.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_parameter_values.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_parametric_reforms.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_poverty.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_poverty_by_demographics.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_preservation_mirror.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_program_statistics.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_pyproject_pins.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_region.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_region_group_strategy.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_release_credentials.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_release_lock.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_release_tro_generation.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_results.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_run_record.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_scoping_strategy.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_small_follow_ups.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_spm_bundle_bootstrap.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_spm_bundle_tooling.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_spm_decile.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_spm_development_authentication.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_spm_household.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_spm_model.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_spm_selection.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_spm_selection_schema.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_trace_tro.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_trace_tro_verify.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_uk_analysis.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_uk_budget_reform_contract.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_uk_dated_reforms.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_uk_geography_assets.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_uk_program_statistics.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_uk_regions.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_uk_year_file_data_year.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_us_legacy_inputs.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_us_long_term_datasets.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_us_microsim_structural_reforms.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_us_native_alignment.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_us_native_hdf_weights.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_us_program_statistics.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_us_reform_application.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_variable_labels.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_variable_metadata.py +0 -0
- {policyengine-6.3.2 → policyengine-6.3.4}/tests/test_zenodo_mirror.py +0 -0
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
## [6.3.4] - 2026-10-13
|
|
2
|
+
|
|
3
|
+
### Changed
|
|
4
|
+
|
|
5
|
+
- `Poverty.rate` is now `None`, not `0.0`, when nobody in the group is measured (its weighted population with a poverty status is zero), for every source. `headcount` and `total_population` are unchanged, and the poverty DataFrame helpers report the rate as missing. Callers that format or subtract rates must handle `None`.
|
|
6
|
+
- US state and congressional-district regions temporarily filter the certified national dataset again, as in 6.2.1, because the ACS-local release lacks source-backed SPM independence and canonical SPM refused every state-region run (PolicyEngine/microcosm#1263).
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
- Measure SPM poverty on legacy certified US sources that predate SPM measurement-scope declarations, such as the ACS-local Build O release. Following Census's ACS household-population method, ACS group-quarters units are outside the SPM measurement: their SPM results are missing instead of stopping the run with `SPM_COMPOSITION_REQUIRED`, and poverty rates count measured people only. Ordinary tax and benefit results are unchanged.
|
|
11
|
+
- Supply the certified SPM independence role from the national release for the ASEC and PUF records of legacy certified US sources, so independent-teen SPM units are measured instead of stopping SPM calculations.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [6.3.3] - 2026-10-13
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- `create_datasets` stamps each US year file with the register of renamed stored inputs it was cut under and a year-file format revision. `ensure_datasets` creates a year file again, and `load_datasets` refuses it, unless its stamp matches this release exactly. A year file cut before a rename was registered, which may have lost that input, is therefore not reused. `load_datasets` says why it refuses a file, naming the renames the file may lack when its register is the reason. Year files written before the stamp existed are created again once.
|
|
19
|
+
|
|
20
|
+
|
|
1
21
|
## [6.3.2] - 2026-10-12
|
|
2
22
|
|
|
3
23
|
### Changed
|
|
@@ -147,7 +147,9 @@ python scripts/bundle.py certify-data \
|
|
|
147
147
|
--model-version <policyengine-us-version>
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
|
|
150
|
+
**Temporarily**, state and congressional-district regions filter the certified national dataset (`populace_us_2024`), as in policyengine 6.2.1. The certified ACS-local release has no source-backed SPM independence, so canonical SPM refuses thousands of its SPM units (PolicyEngine/microcosm#1263, PolicyEngine/policyengine-sim-api#747). They move back to the ACS-local dataset with a release whose SPM units all have a classified adult.
|
|
151
|
+
|
|
152
|
+
When they use it, US state and congressional-district regions scope one certified ACS-local
|
|
151
153
|
Populace dataset with row filters. Pass its non-default local-area release
|
|
152
154
|
manifest through `--regional-manifest-uri`; certification adds the pinned H5
|
|
153
155
|
artifact to `data_releases.us.datasets` and writes both regional path templates
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Legacy US SPM sources (backward compatibility)
|
|
2
|
+
|
|
3
|
+
> **Backward compatibility, not a data contract.** This layer exists so that
|
|
4
|
+
> certified US sources published *before* SPM declarations existed can still
|
|
5
|
+
> be measured. New certified sources must carry the declarations themselves;
|
|
6
|
+
> do not register them here.
|
|
7
|
+
|
|
8
|
+
policyengine-us measures SPM poverty only when a source declares two things:
|
|
9
|
+
|
|
10
|
+
- **Measurement scope:** which SPM units are inside the SPM measurement
|
|
11
|
+
population (`spm_unit_spm_universe_status`: `INCLUDED`/`OUTSIDE`, the
|
|
12
|
+
contract of PolicyEngine/microcosm#977).
|
|
13
|
+
- **Independence role:** which 15–17-year-olds independently head their own
|
|
14
|
+
SPM unit (`is_spm_independent_minor_role`).
|
|
15
|
+
|
|
16
|
+
A legacy source carries neither. Every SPM calculation on it stops with
|
|
17
|
+
`SPM_COMPOSITION_REQUIRED` ("SPM unit has no classified adult").
|
|
18
|
+
|
|
19
|
+
The package
|
|
20
|
+
[`policyengine.tax_benefit_models.us.legacy_spm`](../../../src/policyengine/tax_benefit_models/us/legacy_spm/__init__.py)
|
|
21
|
+
derives the missing declarations from evidence a legacy source does carry.
|
|
22
|
+
Nobody is dropped: memberships, weights and every ordinary tax, benefit and
|
|
23
|
+
income calculation are unchanged.
|
|
24
|
+
|
|
25
|
+
## Registered sources
|
|
26
|
+
|
|
27
|
+
Sources are keyed by certified SHA-256 in `legacy_spm/registry.py`.
|
|
28
|
+
|
|
29
|
+
| Source | Scope rule | Independence list |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| `populace_us_2024_acs_local` Build O (`769756c3…a7ec`) | `acs_household_population` | national release `source_spm_person_independence.csv` (`22b5968d…3ce5`) |
|
|
32
|
+
|
|
33
|
+
### Scope rule `acs_household_population` (#597)
|
|
34
|
+
|
|
35
|
+
Census's ACS SPM methodology measures the household population only.
|
|
36
|
+
|
|
37
|
+
- ACS records with `TYPEHUGQ` 2 or 3 and the matching `RELSHIPP` (37 or 38) are
|
|
38
|
+
group quarters, so their SPM units are `OUTSIDE`.
|
|
39
|
+
- ACS housing-unit records are `INCLUDED`.
|
|
40
|
+
- Records from the `asec` and `puf_tax_detail` channels are `INCLUDED`.
|
|
41
|
+
|
|
42
|
+
Age is never used. Unknown channels, missing or inconsistent evidence, and SPM
|
|
43
|
+
units that mix group quarters with household people all raise.
|
|
44
|
+
|
|
45
|
+
On the full Build O source, 183,206 SPM units are outside the measurement.
|
|
46
|
+
|
|
47
|
+
### Independence list (#598)
|
|
48
|
+
|
|
49
|
+
The source's ASEC/PUF records are the same records the certified national
|
|
50
|
+
release carries with a source-backed independence role. The list is joined by
|
|
51
|
+
`person_id` and `person_spm_unit_id`, and the join must be exact:
|
|
52
|
+
|
|
53
|
+
- every ASEC/PUF person appears once, in the same SPM unit;
|
|
54
|
+
- the list names nobody else.
|
|
55
|
+
|
|
56
|
+
ACS people keep the model's own fallback (household head or spouse).
|
|
57
|
+
|
|
58
|
+
On Build O, exactly 28 units change: Census-built units around an independent
|
|
59
|
+
teen.
|
|
60
|
+
|
|
61
|
+
## How runs get the declarations
|
|
62
|
+
|
|
63
|
+
| Path | What happens |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| `create_datasets` / `ensure_datasets` | Year files store the declarations as ordinary input columns, with a `policyengine_legacy_spm_declarations` record. |
|
|
66
|
+
| `Simulation.run()` over a raw legacy source file | The declarations are derived in memory. The file is recognised by its evidence columns and then its SHA-256, which is hashed once per process. |
|
|
67
|
+
| `managed_microsimulation` | The declarations are derived from the loaded tables and set on the simulation and its branches. |
|
|
68
|
+
|
|
69
|
+
`legacy_spm.model_adapter` then makes the model honour the scope:
|
|
70
|
+
|
|
71
|
+
- **native:** policyengine-us defines `spm_unit_spm_universe_status`
|
|
72
|
+
(PolicyEngine/policyengine-us#9462). The declaration is just an input, and
|
|
73
|
+
nothing is overridden.
|
|
74
|
+
- **override:** policyengine-us 2.2.1 cannot read it. A variable-only reform:
|
|
75
|
+
- adds the input;
|
|
76
|
+
- wraps the installed SPM chain so that outside units never reach the
|
|
77
|
+
canonical provider and every SPM outcome for them is NaN ("not measured").
|
|
78
|
+
|
|
79
|
+
Poverty indicators become floats (1.0, 0.0 or NaN). The override wraps the
|
|
80
|
+
installed formulas, with one exception: `spm_unit_income_decile` ranks
|
|
81
|
+
units, so it is recalculated over measured units with the installed method.
|
|
82
|
+
A contract test pins that method. The override refuses to run if the SPM
|
|
83
|
+
chain no longer has the verified shape.
|
|
84
|
+
|
|
85
|
+
Poverty rates count measured people only. A group with nobody measured has a
|
|
86
|
+
rate of `None`, not 0.
|
|
87
|
+
|
|
88
|
+
## Staleness
|
|
89
|
+
|
|
90
|
+
The record holds a `LegacySPMProfile`: the registry entry plus
|
|
91
|
+
`ADAPTER_REVISION`. Checks are total and exact, like the year-file stamp:
|
|
92
|
+
|
|
93
|
+
- `ensure_datasets` cuts a year file again, and `load_datasets` refuses it, when
|
|
94
|
+
its record is absent, unreadable, malformed, or from another profile.
|
|
95
|
+
- `Simulation.load()` refuses an output saved under a different profile.
|
|
96
|
+
|
|
97
|
+
Raise `ADAPTER_REVISION` whenever a change to derivation or the override means
|
|
98
|
+
existing files must be made again.
|
|
99
|
+
|
|
100
|
+
## When the model or data changes
|
|
101
|
+
|
|
102
|
+
- **policyengine-us gains native scope (#9462).**
|
|
103
|
+
`test_the_installed_model_does_not_read_scope_natively_yet` fails. Check that
|
|
104
|
+
the native members include `INCLUDED` and `OUTSIDE`, and confirm the native
|
|
105
|
+
runs in the integration tests. Then delete the override half of
|
|
106
|
+
`model_adapter` (keep the derivation) and raise `ADAPTER_REVISION`.
|
|
107
|
+
- **The SPM chain changes.** `test_the_override_covers_every_variable_that_depends_on_the_provider`,
|
|
108
|
+
`test_the_installed_chain_has_the_verified_shape` or
|
|
109
|
+
`test_the_recalculated_decile_matches_the_installed_method` fails. Re-verify
|
|
110
|
+
the override against the new chain before bumping the pin.
|
|
111
|
+
- **A rebuilt source declares scope and role itself.** Point the bundle at it.
|
|
112
|
+
Keep the Build O registry entry only while anything still reads Build O,
|
|
113
|
+
then delete it.
|
|
114
|
+
|
|
115
|
+
## Related
|
|
116
|
+
|
|
117
|
+
- Microcosm #977: scope classification at source.
|
|
118
|
+
- Microcosm #959: independence role in US builds.
|
|
119
|
+
- policyengine-us #9462: native scope.
|
|
120
|
+
- policyengine.py #519: nullable SPM summaries.
|
|
121
|
+
- The year-file and output stamps (#590, and #593/#594 in flight). Fold this
|
|
122
|
+
record into them once those land.
|
|
@@ -87,6 +87,24 @@ before passing them to the country model. Generic adult/child counts remain
|
|
|
87
87
|
separate. The native source enrichment is not recalibration, and inherited
|
|
88
88
|
schema-5 calibration diagnostics cannot be relabeled as schema 6.
|
|
89
89
|
|
|
90
|
+
**Legacy SPM sources (backward compatibility).** Some certified US sources
|
|
91
|
+
predate SPM declarations, for example the ACS-local Build O release. For those
|
|
92
|
+
sources, .py derives the declarations from evidence they carry, following
|
|
93
|
+
Census's ACS SPM methodology, which measures the household population only:
|
|
94
|
+
|
|
95
|
+
- ACS group-quarters SPM units are outside the SPM measurement. Their SPM
|
|
96
|
+
thresholds, resources and poverty indicators are missing (NaN).
|
|
97
|
+
- Poverty indicators on those sources are floats: 1.0, 0.0, or NaN for "not
|
|
98
|
+
measured".
|
|
99
|
+
- Poverty rates count measured people only. A group with nobody measured has
|
|
100
|
+
a rate of `None`, not 0.
|
|
101
|
+
- The sources' ASEC and PUF records take the certified SPM independence role
|
|
102
|
+
from the national release.
|
|
103
|
+
|
|
104
|
+
Ordinary tax, benefit and income results are unchanged. Outputs record the
|
|
105
|
+
declarations they used under `legacy_spm_declarations`. See
|
|
106
|
+
[the runbook](engineering/runbooks/us-legacy-spm-sources.md).
|
|
107
|
+
|
|
90
108
|
The wrapper's native pandas HDF loader accepts files that store only calibrated
|
|
91
109
|
`household_weight`. It maps missing person and group weight columns through
|
|
92
110
|
native membership IDs in memory, retaining supplied weight columns and the
|
|
@@ -401,15 +419,49 @@ The renames applied are recorded as `{old: new}` (`{}` when none applied):
|
|
|
401
419
|
carried the draw: data that stores neither name runs with the new input's
|
|
402
420
|
default, which for WIC is full take-up.
|
|
403
421
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
422
|
+
A saved US output written before this mapping existed has no record and may
|
|
423
|
+
have been calculated without the mapped inputs, so `load()` refuses it, and
|
|
424
|
+
`ensure()` runs the simulation again and saves the new output. Saved outputs
|
|
425
|
+
are checked only for the record, not for the register they were calculated
|
|
426
|
+
under.
|
|
427
|
+
|
|
428
|
+
### Year files
|
|
429
|
+
|
|
430
|
+
`create_datasets` stamps each year file, after writing everything else, with
|
|
431
|
+
the register it was cut under and a year-file format revision
|
|
432
|
+
(`legacy_inputs.YEAR_FILE_STAMP_H5_DATASET`, UTF-8 JSON
|
|
433
|
+
`{"register": {old: new, ...}, "revision": 1}`). `ensure_datasets` reuses a
|
|
434
|
+
year file only when its stamp equals this release's exactly and its renames
|
|
435
|
+
record lists only renames in the stamped register. Otherwise it logs why and
|
|
436
|
+
creates the year files again; `load_datasets` refuses the file with the same
|
|
437
|
+
reason, which names the renames the file may lack when its register is the
|
|
438
|
+
cause. To decide, both read only the stamp and the record, never the tables
|
|
439
|
+
or the source dataset. `legacy_inputs.year_file_stamp_problem(path)` returns
|
|
440
|
+
the reason, or `None` for a current year file.
|
|
441
|
+
|
|
442
|
+
A year file is out of date when:
|
|
443
|
+
|
|
444
|
+
- it has no stamp. Year files that policyengine.py 6.1.1 and earlier cut,
|
|
445
|
+
with policyengine-us 2.x, from a source storing the draw only as
|
|
446
|
+
`would_claim_wic` (such as the certified default) store neither WIC take-up
|
|
447
|
+
name, so the draw is lost from them. Year files written with the renames
|
|
448
|
+
record but before the stamp are cut again once, and so is a year file whose
|
|
449
|
+
write did not finish;
|
|
450
|
+
- its register lacks an entry this release has. It may have lost that
|
|
451
|
+
entry's input, as the older files lost the WIC draw;
|
|
452
|
+
- its register has an entry this release lacks, or maps an old name to
|
|
453
|
+
another new name. It may store a new name this release's engine does not
|
|
454
|
+
define, and a run skips any column the engine does not define;
|
|
455
|
+
- it has another format revision, or its stamp or record cannot be read.
|
|
456
|
+
|
|
457
|
+
So any change to `LEGACY_INPUT_RENAMES` makes every year file out of date,
|
|
458
|
+
and two policyengine.py versions with different registers that share a data
|
|
459
|
+
folder cut each other's year files again. `ensure_datasets` raises, rather
|
|
460
|
+
than cutting the files again, when a year file cannot be opened for reasons
|
|
461
|
+
unrelated to its contents: no permission, a directory at its path, or a lock
|
|
462
|
+
held by another process. A year file opened directly, as
|
|
463
|
+
`PolicyEngineUSDataset(filepath=...)`, is not checked, and saving it again with
|
|
464
|
+
`save()` drops its stamp.
|
|
413
465
|
|
|
414
466
|
## Pinned model versions
|
|
415
467
|
|
|
@@ -167,6 +167,12 @@ rate.run()
|
|
|
167
167
|
rate.headcount, rate.total_population, rate.rate
|
|
168
168
|
```
|
|
169
169
|
|
|
170
|
+
`rate.rate` is `None` when nobody in the group is measured: the group's
|
|
171
|
+
weighted population with a poverty status is zero, for example a filter that
|
|
172
|
+
matches no one, or a group whose members are all outside the SPM measurement
|
|
173
|
+
on a legacy source. That is not a measured rate of zero, so handle `None`
|
|
174
|
+
before formatting or subtracting rates.
|
|
175
|
+
|
|
170
176
|
For all canonical poverty measures over one simulation:
|
|
171
177
|
|
|
172
178
|
```python
|
|
@@ -23,9 +23,13 @@ ca_snap = Aggregate(
|
|
|
23
23
|
ca_snap.run()
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
Each state is a region in the US registry. State regions load the
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
Each state is a region in the US registry. State regions load the Populace
|
|
27
|
+
dataset declared by `region.dataset_path`, then scope its rows by `state_fips`.
|
|
28
|
+
They do not require separate state H5 files.
|
|
29
|
+
|
|
30
|
+
**Temporarily**, state and congressional-district regions filter the certified national dataset (`populace_us_2024`), as in policyengine 6.2.1. The certified ACS-local release has no source-backed SPM independence, so canonical SPM refuses thousands of its SPM units (PolicyEngine/microcosm#1263, PolicyEngine/policyengine-sim-api#747). They move back to the ACS-local dataset with a release whose SPM units all have a classified adult.
|
|
31
|
+
|
|
32
|
+
For example:
|
|
29
33
|
|
|
30
34
|
```python
|
|
31
35
|
states = pe.us.model.region_registry.get_by_type("state")
|
|
@@ -52,7 +56,8 @@ for row in impacts.district_results:
|
|
|
52
56
|
|
|
53
57
|
`district_geoid` is the SSDD integer (state FIPS × 100 + district number;
|
|
54
58
|
at-large districts use `00`). Congressional district regions load the same
|
|
55
|
-
|
|
59
|
+
file as state regions (for now the national dataset; see above) and scope its rows by
|
|
60
|
+
`congressional_district_geoid`.
|
|
56
61
|
|
|
57
62
|
## UK countries
|
|
58
63
|
|
|
@@ -207,7 +207,8 @@ python scripts/bundle.py certify-data --country us --data-producer populace \
|
|
|
207
207
|
|
|
208
208
|
That produces one US bundle manifest entry containing the Populace national
|
|
209
209
|
default dataset and the certified ACS-local regional dataset. State and
|
|
210
|
-
congressional-district simulations use
|
|
210
|
+
congressional-district simulations use one of them with runtime row filters (for now the
|
|
211
|
+
national dataset; see [Regions](regions.md)), so
|
|
211
212
|
derived `states/*.h5` or `districts/*.h5` files are not vendored into
|
|
212
213
|
`data_releases.us.datasets`.
|
|
213
214
|
|
|
@@ -32,6 +32,11 @@ from policyengine.tax_benefit_models.us import (
|
|
|
32
32
|
)
|
|
33
33
|
|
|
34
34
|
|
|
35
|
+
def _format_rate(rate: float | None) -> str:
|
|
36
|
+
"""Format a poverty rate; ``None`` means nobody in the group is measured."""
|
|
37
|
+
return "n/a" if rate is None else f"{rate:.4f}"
|
|
38
|
+
|
|
39
|
+
|
|
35
40
|
def main():
|
|
36
41
|
year = 2026
|
|
37
42
|
|
|
@@ -147,11 +152,15 @@ def main():
|
|
|
147
152
|
analysis.reform_poverty.outputs,
|
|
148
153
|
strict=True,
|
|
149
154
|
):
|
|
155
|
+
# A rate is None when nobody in the group is measured.
|
|
156
|
+
change = (
|
|
157
|
+
"n/a" if bp.rate is None or rp.rate is None else f"{rp.rate - bp.rate:+.4f}"
|
|
158
|
+
)
|
|
150
159
|
print(
|
|
151
160
|
f" {bp.metric:30s} "
|
|
152
|
-
f"baseline={bp.rate
|
|
153
|
-
f"reform={rp.rate
|
|
154
|
-
f"change={
|
|
161
|
+
f"baseline={_format_rate(bp.rate)} "
|
|
162
|
+
f"reform={_format_rate(rp.rate)} "
|
|
163
|
+
f"change={change}"
|
|
155
164
|
)
|
|
156
165
|
|
|
157
166
|
print("\n=== Inequality ===")
|
|
@@ -193,6 +193,15 @@ def build_simulation_run_record_payloads(
|
|
|
193
193
|
if renames is not None:
|
|
194
194
|
results_payload["legacy_input_renames"] = dict(renames)
|
|
195
195
|
|
|
196
|
+
# BACKWARD COMPATIBILITY (#597, #598): the legacy SPM declarations a
|
|
197
|
+
# US run applied, which change its SPM results. See
|
|
198
|
+
# ``policyengine.tax_benefit_models.us.legacy_spm``.
|
|
199
|
+
legacy_spm_declarations = (
|
|
200
|
+
getattr(simulation.output_dataset, "metadata", None) or {}
|
|
201
|
+
).get("legacy_spm_declarations")
|
|
202
|
+
if legacy_spm_declarations is not None:
|
|
203
|
+
results_payload["legacy_spm_declarations"] = dict(legacy_spm_declarations)
|
|
204
|
+
|
|
196
205
|
return {"reform": reform, "input": input_payload, "results": results_payload}
|
|
197
206
|
|
|
198
207
|
|
|
@@ -258,4 +258,12 @@ class Simulation(BaseModel):
|
|
|
258
258
|
)
|
|
259
259
|
if renames is not None:
|
|
260
260
|
result["legacy_input_renames"] = dict(renames)
|
|
261
|
+
# BACKWARD COMPATIBILITY (#597, #598): the legacy SPM declarations a
|
|
262
|
+
# US run applied, which change its SPM results. See
|
|
263
|
+
# ``policyengine.tax_benefit_models.us.legacy_spm``.
|
|
264
|
+
legacy_spm_declarations = (
|
|
265
|
+
getattr(self.output_dataset, "metadata", None) or {}
|
|
266
|
+
).get("legacy_spm_declarations")
|
|
267
|
+
if legacy_spm_declarations is not None:
|
|
268
|
+
result["legacy_spm_declarations"] = dict(legacy_spm_declarations)
|
|
261
269
|
return result
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"bundle_version": "6.3.
|
|
2
|
+
"bundle_version": "6.3.4",
|
|
3
3
|
"citation": {
|
|
4
4
|
"publisher": "PolicyEngine",
|
|
5
|
-
"title": "PolicyEngine bundle 6.3.
|
|
5
|
+
"title": "PolicyEngine bundle 6.3.4",
|
|
6
6
|
"type": "software-bundle",
|
|
7
|
-
"version": "6.3.
|
|
7
|
+
"version": "6.3.4"
|
|
8
8
|
},
|
|
9
9
|
"countries": {
|
|
10
10
|
"uk": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"data_releases": {
|
|
18
18
|
"uk": {
|
|
19
19
|
"build_id": "policyengine-uk-data-1.58.0",
|
|
20
|
-
"bundle_id": "uk-6.3.
|
|
20
|
+
"bundle_id": "uk-6.3.4",
|
|
21
21
|
"certification": {
|
|
22
22
|
"built_with_model_git_sha": "4cbedbecca352f52dffe47e849553c2759a00711",
|
|
23
23
|
"built_with_model_version": "2.122.2",
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"version": "2.126.12",
|
|
100
100
|
"wheel_url": "https://files.pythonhosted.org/packages/4f/3f/0a611e9b25beb75db3f2f521d359eabad0d1ab4e50194b866663355591ff/policyengine_uk-2.126.12-py3-none-any.whl"
|
|
101
101
|
},
|
|
102
|
-
"policyengine_version": "6.3.
|
|
102
|
+
"policyengine_version": "6.3.4",
|
|
103
103
|
"region_datasets": {
|
|
104
104
|
"national": {
|
|
105
105
|
"path_template": "enhanced_frs_2024_25.h5"
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
},
|
|
113
113
|
"us": {
|
|
114
114
|
"build_id": "populace-us-2024-spm-20260915",
|
|
115
|
-
"bundle_id": "us-6.3.
|
|
115
|
+
"bundle_id": "us-6.3.4",
|
|
116
116
|
"certification": {
|
|
117
117
|
"built_with_model_version": "2.2.1",
|
|
118
118
|
"certified_by": "policyengine.py bundle certification",
|
|
@@ -217,16 +217,16 @@
|
|
|
217
217
|
"version": "2.2.1",
|
|
218
218
|
"wheel_url": "https://files.pythonhosted.org/packages/5e/09/86ac3968d2a18e28fce3ba1186fc21728e9f299b96a806d6f204f1e0aaed/policyengine_us-2.2.1-py3-none-any.whl"
|
|
219
219
|
},
|
|
220
|
-
"policyengine_version": "6.3.
|
|
220
|
+
"policyengine_version": "6.3.4",
|
|
221
221
|
"region_datasets": {
|
|
222
222
|
"congressional_district": {
|
|
223
|
-
"path_template": "
|
|
223
|
+
"path_template": "populace_us_2024.h5"
|
|
224
224
|
},
|
|
225
225
|
"national": {
|
|
226
226
|
"path_template": "populace_us_2024.h5"
|
|
227
227
|
},
|
|
228
228
|
"state": {
|
|
229
|
-
"path_template": "
|
|
229
|
+
"path_template": "populace_us_2024.h5"
|
|
230
230
|
}
|
|
231
231
|
},
|
|
232
232
|
"regional_release_manifest_uri": "https://huggingface.co/datasets/policyengine/populace-us/resolve/populace-us-2024-buildo-acs-local-767312d60-20260923T074941Z/releases/populace-us-2024-buildo-acs-local-767312d60-20260923T074941Z/release_manifest.json",
|
|
@@ -295,10 +295,10 @@
|
|
|
295
295
|
"packages": {
|
|
296
296
|
"policyengine": {
|
|
297
297
|
"import_name": "policyengine",
|
|
298
|
-
"install_requirement": "policyengine==6.3.
|
|
298
|
+
"install_requirement": "policyengine==6.3.4",
|
|
299
299
|
"name": "policyengine",
|
|
300
300
|
"role": "bundle_carrier",
|
|
301
|
-
"version": "6.3.
|
|
301
|
+
"version": "6.3.4"
|
|
302
302
|
},
|
|
303
303
|
"policyengine-core": {
|
|
304
304
|
"import_name": "policyengine_core",
|
|
@@ -334,6 +334,6 @@
|
|
|
334
334
|
"wheel_url": "https://files.pythonhosted.org/packages/19/a0/c484f69a0ebf88a9b9fd0ac28176f8df66550f46714f1b0c5ec0b360824e/spm_calculator-1.0.0-py3-none-any.whl"
|
|
335
335
|
}
|
|
336
336
|
},
|
|
337
|
-
"policyengine_version": "6.3.
|
|
337
|
+
"policyengine_version": "6.3.4",
|
|
338
338
|
"schema_version": 2
|
|
339
339
|
}
|
|
@@ -18,18 +18,18 @@
|
|
|
18
18
|
"schema:url": "https://policyengine.org"
|
|
19
19
|
},
|
|
20
20
|
"schema:dateCreated": "2026-10-07T17:31:53.189867Z",
|
|
21
|
-
"schema:description": "TRACE TRO for certified runtime bundle uk-6.3.
|
|
21
|
+
"schema:description": "TRACE TRO for certified runtime bundle uk-6.3.4 covering the bundle manifest, the certified dataset artifact, the country model wheel, and the country data release manifest when it is available.",
|
|
22
22
|
"schema:name": "policyengine uk certified bundle TRO",
|
|
23
23
|
"trov:createdWith": {
|
|
24
24
|
"@type": "schema:SoftwareApplication",
|
|
25
25
|
"schema:name": "policyengine",
|
|
26
|
-
"schema:softwareVersion": "6.3.
|
|
26
|
+
"schema:softwareVersion": "6.3.4"
|
|
27
27
|
},
|
|
28
28
|
"trov:hasArrangement": [
|
|
29
29
|
{
|
|
30
30
|
"@id": "arrangement/1",
|
|
31
31
|
"@type": "trov:ArtifactArrangement",
|
|
32
|
-
"rdfs:comment": "Certified arrangement for bundle uk-6.3.
|
|
32
|
+
"rdfs:comment": "Certified arrangement for bundle uk-6.3.4.",
|
|
33
33
|
"trov:hasArtifactLocation": [
|
|
34
34
|
{
|
|
35
35
|
"@id": "arrangement/1/location/bundle_manifest",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"@type": "trov:ResearchArtifact",
|
|
76
76
|
"schema:name": "policyengine.py bundle manifest for uk",
|
|
77
77
|
"trov:mimeType": "application/json",
|
|
78
|
-
"trov:sha256": "
|
|
78
|
+
"trov:sha256": "594d1c8ba2539df9c26ca2b6a7170ab20fb03176e5428b3963dd42e61b707564"
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
81
|
"@id": "composition/1/artifact/data_release_manifest",
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"trov:hasFingerprint": {
|
|
103
103
|
"@id": "composition/1/fingerprint",
|
|
104
104
|
"@type": "trov:CompositionFingerprint",
|
|
105
|
-
"trov:sha256": "
|
|
105
|
+
"trov:sha256": "42003f5d9bda251119c325e8d61d22c05edb1c75bf5b9ad80ab3e497fe548439"
|
|
106
106
|
}
|
|
107
107
|
},
|
|
108
108
|
"trov:hasPerformance": {
|
|
@@ -17,18 +17,18 @@
|
|
|
17
17
|
"schema:name": "PolicyEngine",
|
|
18
18
|
"schema:url": "https://policyengine.org"
|
|
19
19
|
},
|
|
20
|
-
"schema:description": "TRACE TRO for certified runtime bundle us-6.3.
|
|
20
|
+
"schema:description": "TRACE TRO for certified runtime bundle us-6.3.4 covering the bundle manifest, the certified dataset artifact, the country model wheel, and the country data release manifest when it is available.",
|
|
21
21
|
"schema:name": "policyengine us certified bundle TRO",
|
|
22
22
|
"trov:createdWith": {
|
|
23
23
|
"@type": "schema:SoftwareApplication",
|
|
24
24
|
"schema:name": "policyengine",
|
|
25
|
-
"schema:softwareVersion": "6.3.
|
|
25
|
+
"schema:softwareVersion": "6.3.4"
|
|
26
26
|
},
|
|
27
27
|
"trov:hasArrangement": [
|
|
28
28
|
{
|
|
29
29
|
"@id": "arrangement/1",
|
|
30
30
|
"@type": "trov:ArtifactArrangement",
|
|
31
|
-
"rdfs:comment": "Certified arrangement for bundle us-6.3.
|
|
31
|
+
"rdfs:comment": "Certified arrangement for bundle us-6.3.4.",
|
|
32
32
|
"trov:hasArtifactLocation": [
|
|
33
33
|
{
|
|
34
34
|
"@id": "arrangement/1/location/bundle_manifest",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"@type": "trov:ResearchArtifact",
|
|
75
75
|
"schema:name": "policyengine.py bundle manifest for us",
|
|
76
76
|
"trov:mimeType": "application/json",
|
|
77
|
-
"trov:sha256": "
|
|
77
|
+
"trov:sha256": "594d1c8ba2539df9c26ca2b6a7170ab20fb03176e5428b3963dd42e61b707564"
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
"@id": "composition/1/artifact/data_release_manifest",
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"trov:hasFingerprint": {
|
|
102
102
|
"@id": "composition/1/fingerprint",
|
|
103
103
|
"@type": "trov:CompositionFingerprint",
|
|
104
|
-
"trov:sha256": "
|
|
104
|
+
"trov:sha256": "0c5fdf655befb2e64f5511bfefd9dc022041a526f1505ac9ee31a7058e349bff"
|
|
105
105
|
}
|
|
106
106
|
},
|
|
107
107
|
"trov:hasPerformance": {
|
|
@@ -81,6 +81,21 @@ class Poverty(Output):
|
|
|
81
81
|
|
|
82
82
|
# Map poverty variable to target entity if needed
|
|
83
83
|
if poverty_var_obj.entity != target_entity:
|
|
84
|
+
source = getattr(
|
|
85
|
+
self.simulation.output_dataset.data, poverty_var_obj.entity
|
|
86
|
+
)
|
|
87
|
+
if (
|
|
88
|
+
target_entity != "person"
|
|
89
|
+
and pd.isna(source[self.poverty_variable]).any()
|
|
90
|
+
):
|
|
91
|
+
# Mapping onto a group sums members and fills empty groups
|
|
92
|
+
# with zero, which would count a person outside the SPM
|
|
93
|
+
# measurement as measured and not poor.
|
|
94
|
+
raise ValueError(
|
|
95
|
+
f"{self.poverty_variable} is missing for units outside "
|
|
96
|
+
f"the poverty measurement; summarise it for people, not "
|
|
97
|
+
f"for {target_entity} units."
|
|
98
|
+
)
|
|
84
99
|
mapped = self.simulation.output_dataset.data.map_to_entity(
|
|
85
100
|
poverty_var_obj.entity,
|
|
86
101
|
target_entity,
|
|
@@ -121,8 +136,13 @@ class Poverty(Output):
|
|
|
121
136
|
# Calculate results using weighted counts
|
|
122
137
|
self.headcount = float((poverty_series == True).sum()) # noqa: E712
|
|
123
138
|
self.total_population = float(poverty_series.count())
|
|
139
|
+
# ``None`` means nobody in the group is measured (for example, every
|
|
140
|
+
# member is outside the SPM measurement population), which is not
|
|
141
|
+
# a measured rate of zero.
|
|
124
142
|
self.rate = (
|
|
125
|
-
self.headcount / self.total_population
|
|
143
|
+
self.headcount / self.total_population
|
|
144
|
+
if self.total_population > 0
|
|
145
|
+
else None
|
|
126
146
|
)
|
|
127
147
|
|
|
128
148
|
|
|
@@ -417,6 +417,14 @@ class MicrosimulationModelVersion(TaxBenefitModelVersion):
|
|
|
417
417
|
RENAMES_RECORD_KEY,
|
|
418
418
|
read_renames_record,
|
|
419
419
|
)
|
|
420
|
+
from policyengine.tax_benefit_models.us.legacy_spm import (
|
|
421
|
+
RECORD_KEY as LEGACY_SPM_RECORD_KEY,
|
|
422
|
+
)
|
|
423
|
+
from policyengine.tax_benefit_models.us.legacy_spm import (
|
|
424
|
+
expected_profile_for_dataset,
|
|
425
|
+
read_record_value,
|
|
426
|
+
record_problem,
|
|
427
|
+
)
|
|
420
428
|
|
|
421
429
|
with h5py.File(filepath, "r") as stream:
|
|
422
430
|
raw = (
|
|
@@ -442,6 +450,17 @@ class MicrosimulationModelVersion(TaxBenefitModelVersion):
|
|
|
442
450
|
"Saved US simulation predates the mapping of renamed "
|
|
443
451
|
"stored inputs (it has no record of them); run it again"
|
|
444
452
|
)
|
|
453
|
+
# BACKWARD COMPATIBILITY (#597, #598): an output is reused only
|
|
454
|
+
# under exactly the legacy SPM declarations its input needs.
|
|
455
|
+
recorded_legacy_spm = read_record_value(filepath)
|
|
456
|
+
legacy_problem = record_problem(
|
|
457
|
+
recorded_legacy_spm, expected_profile_for_dataset(simulation.dataset)
|
|
458
|
+
)
|
|
459
|
+
if legacy_problem is not None:
|
|
460
|
+
raise ValueError(
|
|
461
|
+
f"Saved US simulation output is out of date: {legacy_problem}; "
|
|
462
|
+
"run it again"
|
|
463
|
+
)
|
|
445
464
|
|
|
446
465
|
if self.country_code == "uk":
|
|
447
466
|
from policyengine.tax_benefit_models.uk.datasets import (
|
|
@@ -474,6 +493,10 @@ class MicrosimulationModelVersion(TaxBenefitModelVersion):
|
|
|
474
493
|
simulation.output_dataset.metadata.update(
|
|
475
494
|
{"spm_config": recorded["config"], RENAMES_RECORD_KEY: recorded_renames}
|
|
476
495
|
)
|
|
496
|
+
if isinstance(recorded_legacy_spm, dict):
|
|
497
|
+
simulation.output_dataset.metadata[LEGACY_SPM_RECORD_KEY] = (
|
|
498
|
+
recorded_legacy_spm
|
|
499
|
+
)
|
|
477
500
|
|
|
478
501
|
if os.path.exists(filepath):
|
|
479
502
|
simulation.created_at = datetime.datetime.fromtimestamp(
|