policyengine 3.4.2__tar.gz → 3.4.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-3.4.4/.github/bump_version.py +135 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/.github/workflows/push.yaml +4 -3
- {policyengine-3.4.2 → policyengine-3.4.4}/CHANGELOG.md +21 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/Makefile +9 -3
- {policyengine-3.4.2 → policyengine-3.4.4}/PKG-INFO +5 -4
- {policyengine-3.4.2 → policyengine-3.4.4}/README.md +2 -1
- {policyengine-3.4.2 → policyengine-3.4.4}/docs/dev.md +8 -4
- {policyengine-3.4.2 → policyengine-3.4.4}/docs/index.md +1 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/docs/myst.yml +1 -0
- policyengine-3.4.4/docs/release-bundles.md +329 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/pyproject.toml +3 -3
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/__init__.py +13 -0
- policyengine-3.4.4/src/policyengine/core/release_manifest.py +380 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/tax_benefit_model_version.py +81 -4
- policyengine-3.4.4/src/policyengine/core/trace_tro.py +259 -0
- policyengine-3.4.4/src/policyengine/data/release_manifests/uk.json +45 -0
- policyengine-3.4.4/src/policyengine/data/release_manifests/us.json +48 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/tax_benefit_models/uk/model.py +25 -33
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/tax_benefit_models/us/model.py +25 -21
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine.egg-info/PKG-INFO +5 -4
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine.egg-info/SOURCES.txt +3 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine.egg-info/requires.txt +2 -2
- policyengine-3.4.4/tests/test_bump_version.py +56 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_models.py +5 -5
- policyengine-3.4.4/tests/test_release_manifests.py +583 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_uk_regions.py +1 -1
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_us_regions.py +3 -3
- policyengine-3.4.2/.github/bump_version.py +0 -77
- policyengine-3.4.2/src/policyengine/core/release_manifest.py +0 -178
- policyengine-3.4.2/src/policyengine/data/release_manifests/uk.json +0 -27
- policyengine-3.4.2/src/policyengine/data/release_manifests/us.json +0 -30
- policyengine-3.4.2/tests/test_release_manifests.py +0 -114
- {policyengine-3.4.2 → policyengine-3.4.4}/.claude/policyengine-guide.md +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/.claude/quick-reference.md +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/.github/CONTRIBUTING.md +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/.github/changelog_template.md +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/.github/check-changelog.sh +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/.github/fetch_version.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/.github/get-changelog-diff.sh +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/.github/has-functional-changes.sh +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/.github/is-version-number-acceptable.sh +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/.github/publish-git-tag.sh +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/.github/workflows/pr_code_changes.yaml +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/.github/workflows/pr_docs_changes.yaml +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/.gitignore +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/.python-version +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/LICENSE +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/changelog.d/.gitkeep +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/docs/.gitignore +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/docs/advanced-outputs.md +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/docs/core-concepts.md +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/docs/country-models-uk.md +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/docs/country-models-us.md +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/docs/economic-impact-analysis.md +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/docs/examples.md +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/docs/regions-and-scoping.md +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/docs/visualisation.md +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/examples/employment_income_variation_uk.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/examples/employment_income_variation_us.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/examples/household_impact_example.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/examples/income_bands_uk.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/examples/income_distribution_us.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/examples/paper_repro_uk.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/examples/policy_change_uk.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/examples/speedtest_us_simulation.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/examples/us_budgetary_impact.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/setup.cfg +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/__init__.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/cache.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/dataset.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/dataset_version.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/dynamic.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/output.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/parameter.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/parameter_node.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/parameter_value.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/policy.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/region.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/scoping_strategy.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/simulation.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/tax_benefit_model.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/core/variable.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/countries/__init__.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/countries/uk/__init__.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/countries/uk/regions.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/countries/us/__init__.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/countries/us/data/__init__.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/countries/us/data/districts.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/countries/us/data/places.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/countries/us/data/states.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/countries/us/regions.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/outputs/__init__.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/outputs/aggregate.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/outputs/change_aggregate.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/outputs/congressional_district_impact.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/outputs/constituency_impact.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/outputs/decile_impact.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/outputs/inequality.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/outputs/intra_decile_impact.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/outputs/local_authority_impact.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/outputs/poverty.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/tax_benefit_models/uk/__init__.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/tax_benefit_models/uk/analysis.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/tax_benefit_models/uk/datasets.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/tax_benefit_models/uk/outputs.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/tax_benefit_models/uk.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/tax_benefit_models/us/__init__.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/tax_benefit_models/us/analysis.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/tax_benefit_models/us/datasets.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/tax_benefit_models/us/outputs.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/tax_benefit_models/us.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/utils/__init__.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/utils/dates.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/utils/entity_utils.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/utils/parameter_labels.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/utils/parametric_reforms.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine/utils/plotting.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine.egg-info/dependency_links.txt +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/src/policyengine.egg-info/top_level.txt +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/__init__.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/conftest.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/fixtures/__init__.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/fixtures/filtering_fixtures.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/fixtures/parameter_labels_fixtures.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/fixtures/parametric_reforms_fixtures.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/fixtures/poverty_by_demographics_fixtures.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/fixtures/region_fixtures.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/fixtures/us_reform_fixtures.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/fixtures/variable_label_fixtures.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_aggregate.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_cache.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_change_aggregate.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_congressional_district_impact.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_constituency_impact.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_entity_mapping.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_entity_utils.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_filtering.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_household_impact.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_inequality.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_intra_decile_impact.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_local_authority_impact.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_pandas3_compatibility.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_parameter_labels.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_parametric_reforms.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_poverty.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_poverty_by_demographics.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_poverty_run.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_region.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_scoping_strategy.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_us_reform_application.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/tests/test_variable_labels.py +0 -0
- {policyengine-3.4.2 → policyengine-3.4.4}/uv.lock +0 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""Infer semver bump from towncrier fragment types and update version."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
SEMVER_PATTERN = re.compile(r"^(\d+)\.(\d+)\.(\d+)$")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def parse_version(version: str) -> tuple[int, int, int]:
|
|
12
|
+
match = SEMVER_PATTERN.match(version)
|
|
13
|
+
if not match:
|
|
14
|
+
raise ValueError(f"Invalid semver: {version}")
|
|
15
|
+
return tuple(int(part) for part in match.groups())
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_pyproject_version(pyproject_path: Path) -> str:
|
|
19
|
+
text = pyproject_path.read_text()
|
|
20
|
+
match = re.search(r'^version\s*=\s*"(\d+\.\d+\.\d+)"', text, re.MULTILINE)
|
|
21
|
+
if not match:
|
|
22
|
+
print(
|
|
23
|
+
"Could not find version in pyproject.toml",
|
|
24
|
+
file=sys.stderr,
|
|
25
|
+
)
|
|
26
|
+
sys.exit(1)
|
|
27
|
+
return match.group(1)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_changelog_versions(changelog_path: Path) -> list[str]:
|
|
31
|
+
if not changelog_path.exists():
|
|
32
|
+
return []
|
|
33
|
+
return re.findall(
|
|
34
|
+
r"^## \[(\d+\.\d+\.\d+)\]", changelog_path.read_text(), re.MULTILINE
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_git_tag_versions(repo_root: Path) -> list[str]:
|
|
39
|
+
try:
|
|
40
|
+
result = subprocess.run(
|
|
41
|
+
["git", "tag"],
|
|
42
|
+
cwd=repo_root,
|
|
43
|
+
capture_output=True,
|
|
44
|
+
text=True,
|
|
45
|
+
check=True,
|
|
46
|
+
)
|
|
47
|
+
except (FileNotFoundError, subprocess.CalledProcessError):
|
|
48
|
+
return []
|
|
49
|
+
|
|
50
|
+
versions = []
|
|
51
|
+
for tag in result.stdout.splitlines():
|
|
52
|
+
normalized = tag.removeprefix("v").strip()
|
|
53
|
+
if SEMVER_PATTERN.match(normalized):
|
|
54
|
+
versions.append(normalized)
|
|
55
|
+
return versions
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def get_current_version(
|
|
59
|
+
pyproject_path: Path,
|
|
60
|
+
changelog_path: Path,
|
|
61
|
+
repo_root: Path,
|
|
62
|
+
) -> str:
|
|
63
|
+
candidates = [get_pyproject_version(pyproject_path)]
|
|
64
|
+
candidates.extend(get_changelog_versions(changelog_path))
|
|
65
|
+
candidates.extend(get_git_tag_versions(repo_root))
|
|
66
|
+
return max(candidates, key=parse_version)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def infer_bump(changelog_dir: Path) -> str:
|
|
70
|
+
fragments = [
|
|
71
|
+
f for f in changelog_dir.iterdir() if f.is_file() and f.name != ".gitkeep"
|
|
72
|
+
]
|
|
73
|
+
if not fragments:
|
|
74
|
+
print("No changelog fragments found", file=sys.stderr)
|
|
75
|
+
sys.exit(1)
|
|
76
|
+
|
|
77
|
+
categories = {f.suffix.lstrip(".") for f in fragments}
|
|
78
|
+
for f in fragments:
|
|
79
|
+
parts = f.stem.split(".")
|
|
80
|
+
if len(parts) >= 2:
|
|
81
|
+
categories.add(parts[-1])
|
|
82
|
+
|
|
83
|
+
if "breaking" in categories:
|
|
84
|
+
return "major"
|
|
85
|
+
if "added" in categories or "removed" in categories:
|
|
86
|
+
return "minor"
|
|
87
|
+
return "patch"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def bump_version(version: str, bump: str) -> str:
|
|
91
|
+
major, minor, patch = (int(x) for x in version.split("."))
|
|
92
|
+
if bump == "major":
|
|
93
|
+
return f"{major + 1}.0.0"
|
|
94
|
+
elif bump == "minor":
|
|
95
|
+
return f"{major}.{minor + 1}.0"
|
|
96
|
+
else:
|
|
97
|
+
return f"{major}.{minor}.{patch + 1}"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def update_file(path: Path, new_version: str):
|
|
101
|
+
text = path.read_text()
|
|
102
|
+
updated, replacements = re.subn(
|
|
103
|
+
r'(^version\s*=\s*")(\d+\.\d+\.\d+)(")',
|
|
104
|
+
rf"\g<1>{new_version}\g<3>",
|
|
105
|
+
text,
|
|
106
|
+
flags=re.MULTILINE,
|
|
107
|
+
)
|
|
108
|
+
if replacements == 0:
|
|
109
|
+
print(
|
|
110
|
+
f"Could not update version in {path}",
|
|
111
|
+
file=sys.stderr,
|
|
112
|
+
)
|
|
113
|
+
sys.exit(1)
|
|
114
|
+
if updated != text:
|
|
115
|
+
path.write_text(updated)
|
|
116
|
+
print(f" Updated {path}")
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def main():
|
|
120
|
+
root = Path(__file__).resolve().parent.parent
|
|
121
|
+
pyproject = root / "pyproject.toml"
|
|
122
|
+
changelog = root / "CHANGELOG.md"
|
|
123
|
+
changelog_dir = root / "changelog.d"
|
|
124
|
+
|
|
125
|
+
current = get_current_version(pyproject, changelog, root)
|
|
126
|
+
bump = infer_bump(changelog_dir)
|
|
127
|
+
new = bump_version(current, bump)
|
|
128
|
+
|
|
129
|
+
print(f"Version: {current} -> {new} ({bump})")
|
|
130
|
+
|
|
131
|
+
update_file(pyproject, new)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
if __name__ == "__main__":
|
|
135
|
+
main()
|
|
@@ -81,10 +81,8 @@ jobs:
|
|
|
81
81
|
- uses: actions/setup-node@v4
|
|
82
82
|
with:
|
|
83
83
|
node-version: 18.x
|
|
84
|
-
- name: Install MyST
|
|
85
|
-
run: npm install -g mystmd
|
|
86
84
|
- name: Build HTML Assets
|
|
87
|
-
run:
|
|
85
|
+
run: make docs
|
|
88
86
|
- name: Upload artifact
|
|
89
87
|
uses: actions/upload-pages-artifact@v3
|
|
90
88
|
with:
|
|
@@ -108,6 +106,9 @@ jobs:
|
|
|
108
106
|
uses: actions/checkout@v4
|
|
109
107
|
with:
|
|
110
108
|
token: ${{ steps.app-token.outputs.token }}
|
|
109
|
+
fetch-depth: 0
|
|
110
|
+
- name: Fetch tags
|
|
111
|
+
run: git fetch --tags --force
|
|
111
112
|
- name: Setup Python
|
|
112
113
|
uses: actions/setup-python@v5
|
|
113
114
|
with:
|
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
## [3.4.4] - 2026-04-13
|
|
2
|
+
|
|
3
|
+
### Changed
|
|
4
|
+
|
|
5
|
+
- Add TRACE TRO export helpers for certified runtime bundles and expose them through `policyengine.core`.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## [3.4.3] - 2026-04-13
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Fix the release versioning workflow so it bumps from the highest known released version instead of regressing to a stale version from `pyproject.toml`.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## [3.4.1] - 2026-04-13
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Add certified bundle metadata that records runtime model pins alongside build-time data artifact provenance and compatibility fingerprints.
|
|
20
|
+
|
|
21
|
+
|
|
1
22
|
## [3.4.2] - 2026-04-12
|
|
2
23
|
|
|
3
24
|
### Changed
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
.PHONY: docs
|
|
1
|
+
.PHONY: docs docs-serve
|
|
2
|
+
|
|
3
|
+
MYSTMD_VERSION ?= 1.8.3
|
|
4
|
+
MYST_CMD = npx --yes mystmd@$(MYSTMD_VERSION)
|
|
2
5
|
|
|
3
6
|
all: build-package
|
|
4
7
|
|
|
5
8
|
docs:
|
|
6
|
-
cd docs &&
|
|
9
|
+
cd docs && $(MYST_CMD) build --html
|
|
10
|
+
|
|
11
|
+
docs-serve:
|
|
12
|
+
cd docs && $(MYST_CMD) start
|
|
7
13
|
|
|
8
14
|
install:
|
|
9
15
|
uv pip install -e .[dev]
|
|
@@ -27,4 +33,4 @@ build-package:
|
|
|
27
33
|
python -m build
|
|
28
34
|
|
|
29
35
|
test:
|
|
30
|
-
pytest tests --cov=policyengine --cov-report=term-missing
|
|
36
|
+
pytest tests --cov=policyengine --cov-report=term-missing
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: policyengine
|
|
3
|
-
Version: 3.4.
|
|
3
|
+
Version: 3.4.4
|
|
4
4
|
Summary: A package to conduct policy analysis using PolicyEngine tax-benefit models.
|
|
5
5
|
Author-email: PolicyEngine <hello@policyengine.org>
|
|
6
6
|
License: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
@@ -678,7 +678,7 @@ Requires-Dist: requests>=2.31.0
|
|
|
678
678
|
Requires-Dist: psutil>=5.9.0
|
|
679
679
|
Provides-Extra: uk
|
|
680
680
|
Requires-Dist: policyengine_core>=3.23.6; extra == "uk"
|
|
681
|
-
Requires-Dist: policyengine-uk==2.
|
|
681
|
+
Requires-Dist: policyengine-uk==2.74.0; extra == "uk"
|
|
682
682
|
Provides-Extra: us
|
|
683
683
|
Requires-Dist: policyengine_core>=3.23.6; extra == "us"
|
|
684
684
|
Requires-Dist: policyengine-us==1.602.0; extra == "us"
|
|
@@ -693,7 +693,7 @@ Requires-Dist: build; extra == "dev"
|
|
|
693
693
|
Requires-Dist: pytest-asyncio>=0.26.0; extra == "dev"
|
|
694
694
|
Requires-Dist: ruff>=0.9.0; extra == "dev"
|
|
695
695
|
Requires-Dist: policyengine_core>=3.23.6; extra == "dev"
|
|
696
|
-
Requires-Dist: policyengine-uk==2.
|
|
696
|
+
Requires-Dist: policyengine-uk==2.74.0; extra == "dev"
|
|
697
697
|
Requires-Dist: policyengine-us==1.602.0; extra == "dev"
|
|
698
698
|
Requires-Dist: towncrier>=24.8.0; extra == "dev"
|
|
699
699
|
Requires-Dist: mypy>=1.11.0; extra == "dev"
|
|
@@ -788,7 +788,8 @@ uv pip install -e .[dev] # install with dev dependencies (pytest, ruff, m
|
|
|
788
788
|
```bash
|
|
789
789
|
make format # ruff format
|
|
790
790
|
make test # pytest with coverage
|
|
791
|
-
make docs # build Jupyter Book
|
|
791
|
+
make docs # build static MyST/Jupyter Book 2 HTML docs
|
|
792
|
+
make docs-serve # preview the docs locally
|
|
792
793
|
make clean # remove caches, build artifacts, .h5 files
|
|
793
794
|
```
|
|
794
795
|
|
|
@@ -86,7 +86,8 @@ uv pip install -e .[dev] # install with dev dependencies (pytest, ruff, m
|
|
|
86
86
|
```bash
|
|
87
87
|
make format # ruff format
|
|
88
88
|
make test # pytest with coverage
|
|
89
|
-
make docs # build Jupyter Book
|
|
89
|
+
make docs # build static MyST/Jupyter Book 2 HTML docs
|
|
90
|
+
make docs-serve # preview the docs locally
|
|
90
91
|
make clean # remove caches, build artifacts, .h5 files
|
|
91
92
|
```
|
|
92
93
|
|
|
@@ -12,17 +12,19 @@
|
|
|
12
12
|
```bash
|
|
13
13
|
git clone https://github.com/PolicyEngine/policyengine.py.git
|
|
14
14
|
cd policyengine.py
|
|
15
|
-
uv pip install -e .[dev]
|
|
15
|
+
uv pip install -e ".[dev]"
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
This installs
|
|
18
|
+
This installs the shared analysis layer, both country model extras, and the dev
|
|
19
|
+
dependencies used in CI (pytest, ruff, mypy, towncrier).
|
|
19
20
|
|
|
20
21
|
## Common commands
|
|
21
22
|
|
|
22
23
|
```bash
|
|
23
24
|
make format # ruff format
|
|
24
25
|
make test # pytest with coverage
|
|
25
|
-
make docs # build
|
|
26
|
+
make docs # build static MyST/Jupyter Book 2 HTML docs
|
|
27
|
+
make docs-serve # preview the docs locally
|
|
26
28
|
make clean # remove caches, build artifacts, .h5 files
|
|
27
29
|
```
|
|
28
30
|
|
|
@@ -60,7 +62,7 @@ PRs trigger the following checks:
|
|
|
60
62
|
| Tests (Python 3.13) | Required | `make test` |
|
|
61
63
|
| Tests (Python 3.14) | Required | `make test` |
|
|
62
64
|
| Mypy | Informational | `mypy src/policyengine` |
|
|
63
|
-
| Docs build | Required |
|
|
65
|
+
| Docs build | Required | `make docs` |
|
|
64
66
|
|
|
65
67
|
## Versioning and releases
|
|
66
68
|
|
|
@@ -73,6 +75,8 @@ echo "Description of change" > changelog.d/my-change.added
|
|
|
73
75
|
|
|
74
76
|
On merge, the versioning workflow bumps the version, builds the changelog, and creates a GitHub Release.
|
|
75
77
|
|
|
78
|
+
For the target release-bundle architecture, see [Release bundles](release-bundles.md). That document defines the split between country `*-data` build manifests and `policyengine.py` certified runtime bundles.
|
|
79
|
+
|
|
76
80
|
## Architecture
|
|
77
81
|
|
|
78
82
|
### Package layout
|
|
@@ -16,4 +16,5 @@ We do this by:
|
|
|
16
16
|
- [US tax-benefit model](country-models-us.md): Entities, parameters, reform examples
|
|
17
17
|
- [Examples](examples.md): Complete working scripts
|
|
18
18
|
- [Visualisation](visualisation.md): Publication-ready charts with Plotly
|
|
19
|
+
- [Release bundles](release-bundles.md): Reproducible model-plus-data certification and provenance
|
|
19
20
|
- [Development](dev.md): Setup, testing, CI, architecture
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
# Release Bundles
|
|
2
|
+
|
|
3
|
+
This document defines the intended reproducibility boundary for `policyengine.py`.
|
|
4
|
+
|
|
5
|
+
The key design decision is:
|
|
6
|
+
|
|
7
|
+
- country `*-data` repos build and stage immutable data artifacts
|
|
8
|
+
- `policyengine.py` is the only component that certifies supported runtime bundles
|
|
9
|
+
- `policyengine.py` does not rebuild country data itself
|
|
10
|
+
|
|
11
|
+
This keeps country-specific data construction in the country data repos while still giving users a single top-level version to cite and pin.
|
|
12
|
+
|
|
13
|
+
## Why this boundary exists
|
|
14
|
+
|
|
15
|
+
For countries like the UK, the data package is not model-independent. Dataset construction, imputations, and calibration steps call the country model directly. That means a published dataset artifact depends on:
|
|
16
|
+
|
|
17
|
+
- the country model version used during data construction
|
|
18
|
+
- the calibration targets used during data construction
|
|
19
|
+
- the raw input data used during data construction
|
|
20
|
+
|
|
21
|
+
If `policyengine.py` only pins a country model version and a data package version without checking that relationship, the provenance boundary is incomplete.
|
|
22
|
+
|
|
23
|
+
## Roles
|
|
24
|
+
|
|
25
|
+
### Country model package
|
|
26
|
+
|
|
27
|
+
Examples: `policyengine-uk`, `policyengine-us`
|
|
28
|
+
|
|
29
|
+
The country model package owns:
|
|
30
|
+
|
|
31
|
+
- policy logic
|
|
32
|
+
- variables and parameters
|
|
33
|
+
- reforms
|
|
34
|
+
- a `data_build_fingerprint` for the subset of model logic that affects data construction
|
|
35
|
+
|
|
36
|
+
It does not own final runtime bundle certification.
|
|
37
|
+
|
|
38
|
+
### Country data package
|
|
39
|
+
|
|
40
|
+
Examples: `policyengine-uk-data`, `policyengine-us-data`
|
|
41
|
+
|
|
42
|
+
The country data package owns:
|
|
43
|
+
|
|
44
|
+
- data build pipelines
|
|
45
|
+
- raw input acquisition
|
|
46
|
+
- calibration target snapshots
|
|
47
|
+
- expensive dataset construction
|
|
48
|
+
- staging immutable build artifacts with provenance
|
|
49
|
+
|
|
50
|
+
It does not define the final supported runtime bundle exposed to users.
|
|
51
|
+
|
|
52
|
+
### `policyengine.py`
|
|
53
|
+
|
|
54
|
+
`policyengine.py` owns:
|
|
55
|
+
|
|
56
|
+
- runtime bundle certification
|
|
57
|
+
- user-facing reproducibility boundaries
|
|
58
|
+
- the supported mapping from `policyengine.py` version to country model version and certified data artifact
|
|
59
|
+
|
|
60
|
+
It does not rebuild microdata artifacts.
|
|
61
|
+
|
|
62
|
+
## Two manifest layers
|
|
63
|
+
|
|
64
|
+
The architecture has two manifest layers with different responsibilities.
|
|
65
|
+
|
|
66
|
+
### 1. Data build manifest
|
|
67
|
+
|
|
68
|
+
Published by the country `*-data` repo.
|
|
69
|
+
|
|
70
|
+
This answers:
|
|
71
|
+
|
|
72
|
+
- what bytes were produced
|
|
73
|
+
- how they were produced
|
|
74
|
+
- which exact model and targets produced them
|
|
75
|
+
|
|
76
|
+
Suggested schema:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"schema_version": 1,
|
|
81
|
+
"country_id": "uk",
|
|
82
|
+
"data_package": {
|
|
83
|
+
"name": "policyengine-uk-data",
|
|
84
|
+
"version": "1.41.0"
|
|
85
|
+
},
|
|
86
|
+
"build": {
|
|
87
|
+
"build_id": "uk-data-2026-04-12T12-30-00Z",
|
|
88
|
+
"git_sha": "abc123",
|
|
89
|
+
"built_at": "2026-04-12T12:30:00Z",
|
|
90
|
+
"built_with_model_package": {
|
|
91
|
+
"name": "policyengine-uk",
|
|
92
|
+
"version": "2.81.0",
|
|
93
|
+
"git_sha": "def456",
|
|
94
|
+
"data_build_fingerprint": "sha256:..."
|
|
95
|
+
},
|
|
96
|
+
"calibration_targets": {
|
|
97
|
+
"snapshot_id": "2026-04-10",
|
|
98
|
+
"sha256": "sha256:..."
|
|
99
|
+
},
|
|
100
|
+
"raw_inputs": [
|
|
101
|
+
{
|
|
102
|
+
"name": "frs_2023_24",
|
|
103
|
+
"sha256": "sha256:..."
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
"build_environment": {
|
|
107
|
+
"python_version": "3.13.3",
|
|
108
|
+
"lockfile_sha256": "sha256:..."
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"default_datasets": {
|
|
112
|
+
"national": "enhanced_frs_2023_24",
|
|
113
|
+
"baseline": "frs_2023_24"
|
|
114
|
+
},
|
|
115
|
+
"artifacts": {
|
|
116
|
+
"enhanced_frs_2023_24": {
|
|
117
|
+
"kind": "microdata",
|
|
118
|
+
"repo_id": "policyengine/policyengine-uk-data-private",
|
|
119
|
+
"path": "builds/uk-data-2026-04-12T12-30-00Z/enhanced_frs_2023_24.h5",
|
|
120
|
+
"revision": "uk-data-2026-04-12T12-30-00Z",
|
|
121
|
+
"sha256": "sha256:...",
|
|
122
|
+
"size_bytes": 123456789
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Notes:
|
|
129
|
+
|
|
130
|
+
- `build_id` must be immutable.
|
|
131
|
+
- build artifacts should be staged under a build-specific path or revision, not a floating release tag.
|
|
132
|
+
- the build manifest is the authoritative provenance record for the artifact bytes.
|
|
133
|
+
|
|
134
|
+
### 2. Certified runtime bundle manifest
|
|
135
|
+
|
|
136
|
+
Published by `policyengine.py`.
|
|
137
|
+
|
|
138
|
+
This answers:
|
|
139
|
+
|
|
140
|
+
- which model and data artifact are supported together at runtime
|
|
141
|
+
- which exact dataset should be used by default
|
|
142
|
+
- which artifact checksum and provenance should be surfaced to users
|
|
143
|
+
|
|
144
|
+
Suggested schema:
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"schema_version": 1,
|
|
149
|
+
"policyengine_version": "3.5.0",
|
|
150
|
+
"bundle_id": "uk-3.5.0",
|
|
151
|
+
"published_at": "2026-04-12T13:00:00Z",
|
|
152
|
+
"country_id": "uk",
|
|
153
|
+
"model_package": {
|
|
154
|
+
"name": "policyengine-uk",
|
|
155
|
+
"version": "2.81.1"
|
|
156
|
+
},
|
|
157
|
+
"certified_data_artifact": {
|
|
158
|
+
"data_package": {
|
|
159
|
+
"name": "policyengine-uk-data",
|
|
160
|
+
"version": "1.41.0"
|
|
161
|
+
},
|
|
162
|
+
"build_id": "uk-data-2026-04-12T12-30-00Z",
|
|
163
|
+
"dataset": "enhanced_frs_2023_24",
|
|
164
|
+
"uri": "hf://policyengine/policyengine-uk-data-private/builds/uk-data-2026-04-12T12-30-00Z/enhanced_frs_2023_24.h5@uk-data-2026-04-12T12-30-00Z",
|
|
165
|
+
"sha256": "sha256:..."
|
|
166
|
+
},
|
|
167
|
+
"certification": {
|
|
168
|
+
"compatibility_basis": "matching_data_build_fingerprint",
|
|
169
|
+
"built_with_model_version": "2.81.0",
|
|
170
|
+
"certified_for_model_version": "2.81.1",
|
|
171
|
+
"data_build_fingerprint": "sha256:...",
|
|
172
|
+
"certified_by": "policyengine.py release workflow"
|
|
173
|
+
},
|
|
174
|
+
"default_dataset": "enhanced_frs_2023_24",
|
|
175
|
+
"region_artifacts": {
|
|
176
|
+
"national": {
|
|
177
|
+
"dataset": "enhanced_frs_2023_24"
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Notes:
|
|
184
|
+
|
|
185
|
+
- this is the user-facing reproducibility boundary
|
|
186
|
+
- apps and APIs should surface this bundle, not only country package versions
|
|
187
|
+
- a bundle may reuse a previously staged data artifact if compatibility is explicitly certified
|
|
188
|
+
|
|
189
|
+
## TRACE export
|
|
190
|
+
|
|
191
|
+
The internal build manifest and certified runtime bundle remain the operational source of
|
|
192
|
+
truth.
|
|
193
|
+
|
|
194
|
+
TRACE sits on top of those manifests as a standards-based export layer.
|
|
195
|
+
|
|
196
|
+
### What gets exported
|
|
197
|
+
|
|
198
|
+
Country `*-data` repos should emit a `trace.tro.jsonld` file for each published data
|
|
199
|
+
release. That TRO should cover:
|
|
200
|
+
|
|
201
|
+
- the release manifest itself
|
|
202
|
+
- each published artifact hash listed in the release manifest
|
|
203
|
+
- the build-time model provenance recorded in the release manifest
|
|
204
|
+
|
|
205
|
+
`policyengine.py` should emit a separate certified-bundle TRO. That TRO should cover:
|
|
206
|
+
|
|
207
|
+
- the bundled country release manifest shipped in `policyengine.py`
|
|
208
|
+
- the country data release manifest resolved for the certified data package version
|
|
209
|
+
- the certified dataset artifact hash
|
|
210
|
+
- the certification basis used to allow runtime reuse
|
|
211
|
+
|
|
212
|
+
### What TRACE does not replace
|
|
213
|
+
|
|
214
|
+
TRACE is not the source of truth for compatibility policy.
|
|
215
|
+
|
|
216
|
+
In particular, TRACE does not decide:
|
|
217
|
+
|
|
218
|
+
- whether a new model version can safely reuse an existing data artifact
|
|
219
|
+
- how `data_build_fingerprint` is computed
|
|
220
|
+
- which staged artifact becomes a supported runtime default
|
|
221
|
+
|
|
222
|
+
Those decisions still belong to the country data build manifest and the
|
|
223
|
+
`policyengine.py` certified runtime bundle.
|
|
224
|
+
|
|
225
|
+
### Why we still want it
|
|
226
|
+
|
|
227
|
+
TRACE adds three things our internal manifests do not provide by themselves:
|
|
228
|
+
|
|
229
|
+
- a standard declaration format for provenance exchange
|
|
230
|
+
- a composition fingerprint over the exact artifacts in scope
|
|
231
|
+
- a better external surface for papers, audits, and reproducibility reviews
|
|
232
|
+
|
|
233
|
+
That is why the recommended design is:
|
|
234
|
+
|
|
235
|
+
- internal manifests for build/certification control
|
|
236
|
+
- generated TRACE TROs for standards-based export
|
|
237
|
+
|
|
238
|
+
## Compatibility rule
|
|
239
|
+
|
|
240
|
+
The architecture should avoid forcing a new data build for every harmless country model release.
|
|
241
|
+
|
|
242
|
+
To do that safely, compatibility must be explicit.
|
|
243
|
+
|
|
244
|
+
### Data build fingerprint
|
|
245
|
+
|
|
246
|
+
Each country model package should expose a `data_build_fingerprint` that covers the subset of logic that affects dataset construction or calibration.
|
|
247
|
+
|
|
248
|
+
Examples of inputs to the fingerprint:
|
|
249
|
+
|
|
250
|
+
- variables used in imputations
|
|
251
|
+
- variables used in calibration loss matrices
|
|
252
|
+
- parameters referenced during data construction
|
|
253
|
+
- uprating or target-computation logic used during the build
|
|
254
|
+
|
|
255
|
+
Things that should usually not affect the fingerprint:
|
|
256
|
+
|
|
257
|
+
- runtime-only outputs that are not used in data construction
|
|
258
|
+
- UI-oriented metadata
|
|
259
|
+
- code paths unrelated to data construction
|
|
260
|
+
|
|
261
|
+
### Certification rules
|
|
262
|
+
|
|
263
|
+
`policyengine.py` may certify a staged data artifact for a model version only if one of the following is true:
|
|
264
|
+
|
|
265
|
+
1. the model version exactly matches the `built_with_model_package.version`
|
|
266
|
+
2. the model version has the same `data_build_fingerprint` as the build-time model version
|
|
267
|
+
|
|
268
|
+
If neither is true, the bundle release must fail and a new data build is required.
|
|
269
|
+
|
|
270
|
+
This should be a hard failure, not a warning.
|
|
271
|
+
|
|
272
|
+
## Artifact states
|
|
273
|
+
|
|
274
|
+
Artifacts should move through explicit states:
|
|
275
|
+
|
|
276
|
+
- `staged`: built by the country data repo and available for inspection or later certification
|
|
277
|
+
- `certified`: referenced by a released `policyengine.py` runtime bundle
|
|
278
|
+
- `deprecated`: no longer recommended for new use, but still reproducible
|
|
279
|
+
|
|
280
|
+
The key point is that `staged` and `certified` are different states. A staged artifact is not automatically part of a supported runtime release.
|
|
281
|
+
|
|
282
|
+
## UK release workflow
|
|
283
|
+
|
|
284
|
+
### Case 1: model-only release
|
|
285
|
+
|
|
286
|
+
1. Cut UK model release candidate `M`.
|
|
287
|
+
2. Compute `data_build_fingerprint(M)`.
|
|
288
|
+
3. Compare it to the fingerprint recorded in the previously certified data build manifest.
|
|
289
|
+
4. If the fingerprint matches, skip the expensive UK data rebuild.
|
|
290
|
+
5. Release `policyengine.py` with a new certified runtime bundle that points to the existing staged UK artifact.
|
|
291
|
+
|
|
292
|
+
### Case 2: data-affecting release
|
|
293
|
+
|
|
294
|
+
1. Cut UK model release candidate `M`.
|
|
295
|
+
2. Compute `data_build_fingerprint(M)`.
|
|
296
|
+
3. If the fingerprint changed, build a new UK data artifact in `policyengine-uk-data` against:
|
|
297
|
+
- exact `policyengine-uk==M`
|
|
298
|
+
- exact target snapshot
|
|
299
|
+
- exact raw input hashes
|
|
300
|
+
4. Stage the new artifact under a build-specific immutable path or revision.
|
|
301
|
+
5. Publish the UK data build manifest.
|
|
302
|
+
6. Release `policyengine.py` with a certified runtime bundle that points to the new staged artifact.
|
|
303
|
+
|
|
304
|
+
## Implementation guidance
|
|
305
|
+
|
|
306
|
+
The current `release_manifest.json` mechanism in country data repos is a good starting point, but it is not yet enough on its own. The target implementation should add:
|
|
307
|
+
|
|
308
|
+
- `built_with_model_package.version`
|
|
309
|
+
- `built_with_model_package.git_sha`
|
|
310
|
+
- `built_with_model_package.data_build_fingerprint`
|
|
311
|
+
- calibration target snapshot metadata
|
|
312
|
+
- immutable staged artifact paths or revisions
|
|
313
|
+
|
|
314
|
+
The target implementation in `policyengine.py` should add:
|
|
315
|
+
|
|
316
|
+
- hard validation of bundle certification rules
|
|
317
|
+
- explicit runtime bundle metadata on simulations, APIs, and app responses
|
|
318
|
+
- checksum-backed dataset resolution from the certified bundle manifest
|
|
319
|
+
|
|
320
|
+
## Why not let `policyengine.py` build all country data directly?
|
|
321
|
+
|
|
322
|
+
Because that would centralise the wrong concerns:
|
|
323
|
+
|
|
324
|
+
- country-specific private data handling would move into the generic orchestration layer
|
|
325
|
+
- country-specific build logic would move into the generic orchestration layer
|
|
326
|
+
- expensive build failures would block the top-level runtime package more often
|
|
327
|
+
- provenance would still originate in the country data pipeline, so `policyengine.py` would not actually eliminate the need for the country build manifest
|
|
328
|
+
|
|
329
|
+
`policyengine.py` should be the certification boundary, not the country data build system.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "policyengine"
|
|
7
|
-
version = "3.4.
|
|
7
|
+
version = "3.4.4"
|
|
8
8
|
description = "A package to conduct policy analysis using PolicyEngine tax-benefit models."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [
|
|
@@ -28,7 +28,7 @@ dependencies = [
|
|
|
28
28
|
[project.optional-dependencies]
|
|
29
29
|
uk = [
|
|
30
30
|
"policyengine_core>=3.23.6",
|
|
31
|
-
"policyengine-uk==2.
|
|
31
|
+
"policyengine-uk==2.74.0",
|
|
32
32
|
]
|
|
33
33
|
us = [
|
|
34
34
|
"policyengine_core>=3.23.6",
|
|
@@ -45,7 +45,7 @@ dev = [
|
|
|
45
45
|
"pytest-asyncio>=0.26.0",
|
|
46
46
|
"ruff>=0.9.0",
|
|
47
47
|
"policyengine_core>=3.23.6",
|
|
48
|
-
"policyengine-uk==2.
|
|
48
|
+
"policyengine-uk==2.74.0",
|
|
49
49
|
"policyengine-us==1.602.0",
|
|
50
50
|
"towncrier>=24.8.0",
|
|
51
51
|
"mypy>=1.11.0",
|