policyengine 3.7.0__tar.gz → 4.3.0__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.
Files changed (209) hide show
  1. {policyengine-3.7.0 → policyengine-4.3.0}/.github/workflows/pr_docs_changes.yaml +3 -6
  2. {policyengine-3.7.0 → policyengine-4.3.0}/CHANGELOG.md +112 -0
  3. {policyengine-3.7.0 → policyengine-4.3.0}/Makefile +2 -5
  4. {policyengine-3.7.0 → policyengine-4.3.0}/PKG-INFO +44 -18
  5. {policyengine-3.7.0 → policyengine-4.3.0}/README.md +41 -17
  6. policyengine-4.3.0/docs/.gitignore +5 -0
  7. policyengine-4.3.0/docs/_generator/README.md +52 -0
  8. policyengine-4.3.0/docs/_generator/build_reference.py +392 -0
  9. policyengine-4.3.0/docs/_quarto.yml +59 -0
  10. policyengine-4.3.0/docs/countries.md +83 -0
  11. {policyengine-3.7.0 → policyengine-4.3.0}/docs/dev.md +12 -6
  12. {policyengine-3.7.0 → policyengine-4.3.0}/docs/examples.md +10 -18
  13. policyengine-4.3.0/docs/getting-started.md +113 -0
  14. policyengine-4.3.0/docs/households.md +129 -0
  15. policyengine-4.3.0/docs/impact-analysis.md +110 -0
  16. policyengine-4.3.0/docs/index.md +46 -0
  17. policyengine-4.3.0/docs/microsim.md +152 -0
  18. policyengine-4.3.0/docs/outputs.md +246 -0
  19. policyengine-4.3.0/docs/reforms.md +108 -0
  20. policyengine-4.3.0/docs/regions.md +147 -0
  21. {policyengine-3.7.0 → policyengine-4.3.0}/docs/release-bundles.md +3 -3
  22. policyengine-4.3.0/examples/household_impact_example.py +104 -0
  23. {policyengine-3.7.0 → policyengine-4.3.0}/pyproject.toml +4 -1
  24. {policyengine-3.7.0 → policyengine-4.3.0}/scripts/generate_trace_tros.py +2 -2
  25. policyengine-4.3.0/scripts/refresh_release_bundle.py +79 -0
  26. policyengine-4.3.0/src/policyengine/__init__.py +46 -0
  27. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/cli.py +3 -3
  28. policyengine-4.3.0/src/policyengine/core/__init__.py +41 -0
  29. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/core/scoping_strategy.py +6 -3
  30. policyengine-4.3.0/src/policyengine/core/simulation.py +177 -0
  31. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/core/tax_benefit_model_version.py +3 -2
  32. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/countries/uk/regions.py +1 -1
  33. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/countries/us/regions.py +1 -1
  34. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/data/release_manifests/uk.json +2 -2
  35. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/data/release_manifests/us.json +2 -2
  36. policyengine-4.3.0/src/policyengine/graph/__init__.py +41 -0
  37. policyengine-4.3.0/src/policyengine/graph/extractor.py +188 -0
  38. policyengine-4.3.0/src/policyengine/graph/graph.py +130 -0
  39. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/outputs/__init__.py +2 -0
  40. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/outputs/constituency_impact.py +2 -1
  41. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/outputs/local_authority_impact.py +2 -1
  42. policyengine-3.7.0/src/policyengine/tax_benefit_models/us/outputs.py → policyengine-4.3.0/src/policyengine/outputs/program_statistics.py +1 -1
  43. policyengine-4.3.0/src/policyengine/provenance/__init__.py +92 -0
  44. policyengine-4.3.0/src/policyengine/provenance/bundle.py +319 -0
  45. policyengine-3.7.0/src/policyengine/core/trace_tro.py → policyengine-4.3.0/src/policyengine/provenance/trace.py +1 -1
  46. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/results/trace_tro.py +2 -2
  47. policyengine-4.3.0/src/policyengine/tax_benefit_models/common/__init__.py +16 -0
  48. policyengine-4.3.0/src/policyengine/tax_benefit_models/common/extra_variables.py +52 -0
  49. policyengine-4.3.0/src/policyengine/tax_benefit_models/common/model_version.py +320 -0
  50. policyengine-4.3.0/src/policyengine/tax_benefit_models/common/reform.py +197 -0
  51. policyengine-4.3.0/src/policyengine/tax_benefit_models/common/result.py +79 -0
  52. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/tax_benefit_models/uk/__init__.py +22 -16
  53. policyengine-4.3.0/src/policyengine/tax_benefit_models/uk/analysis.py +122 -0
  54. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/tax_benefit_models/uk/datasets.py +1 -1
  55. policyengine-4.3.0/src/policyengine/tax_benefit_models/uk/household.py +191 -0
  56. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/tax_benefit_models/uk/model.py +34 -197
  57. policyengine-4.3.0/src/policyengine/tax_benefit_models/us/__init__.py +74 -0
  58. policyengine-4.3.0/src/policyengine/tax_benefit_models/us/analysis.py +139 -0
  59. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/tax_benefit_models/us/datasets.py +1 -1
  60. policyengine-4.3.0/src/policyengine/tax_benefit_models/us/household.py +245 -0
  61. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/tax_benefit_models/us/model.py +50 -223
  62. policyengine-4.3.0/src/policyengine/utils/household_validation.py +113 -0
  63. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine.egg-info/PKG-INFO +44 -18
  64. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine.egg-info/SOURCES.txt +47 -12
  65. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine.egg-info/requires.txt +3 -0
  66. policyengine-4.3.0/tests/fixtures/household_calculator_snapshots/uk_couple_two_kids.json +139 -0
  67. policyengine-4.3.0/tests/fixtures/household_calculator_snapshots/uk_model_surface.json +11 -0
  68. policyengine-4.3.0/tests/fixtures/household_calculator_snapshots/uk_single_adult_employment_income.json +58 -0
  69. policyengine-4.3.0/tests/fixtures/household_calculator_snapshots/uk_single_adult_no_income.json +58 -0
  70. policyengine-4.3.0/tests/fixtures/household_calculator_snapshots/uk_single_parent_one_child.json +85 -0
  71. policyengine-4.3.0/tests/fixtures/household_calculator_snapshots/us_married_two_kids_high_income.json +97 -0
  72. policyengine-4.3.0/tests/fixtures/household_calculator_snapshots/us_model_surface.json +11 -0
  73. policyengine-4.3.0/tests/fixtures/household_calculator_snapshots/us_single_adult_employment_income.json +46 -0
  74. policyengine-4.3.0/tests/fixtures/household_calculator_snapshots/us_single_adult_no_income.json +46 -0
  75. policyengine-4.3.0/tests/fixtures/household_calculator_snapshots/us_single_parent_one_child.json +63 -0
  76. {policyengine-3.7.0 → policyengine-4.3.0}/tests/fixtures/us_reform_fixtures.py +29 -36
  77. policyengine-4.3.0/tests/test_bundle_refresh.py +321 -0
  78. policyengine-4.3.0/tests/test_dict_reforms_on_simulation.py +128 -0
  79. policyengine-4.3.0/tests/test_extra_variables.py +330 -0
  80. policyengine-4.3.0/tests/test_graph/conftest.py +0 -0
  81. policyengine-4.3.0/tests/test_graph/test_extractor.py +312 -0
  82. policyengine-4.3.0/tests/test_household_calculator_snapshot.py +217 -0
  83. policyengine-4.3.0/tests/test_household_impact.py +215 -0
  84. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_manifest_version_mismatch.py +24 -25
  85. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_release_manifests.py +19 -19
  86. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_trace_tro.py +8 -8
  87. policyengine-4.3.0/tests/test_us_microsim_structural_reforms.py +336 -0
  88. policyengine-4.3.0/tests/test_us_reform_application.py +71 -0
  89. policyengine-3.7.0/docs/.gitignore +0 -2
  90. policyengine-3.7.0/docs/advanced-outputs.md +0 -276
  91. policyengine-3.7.0/docs/core-concepts.md +0 -662
  92. policyengine-3.7.0/docs/country-models-uk.md +0 -374
  93. policyengine-3.7.0/docs/country-models-us.md +0 -444
  94. policyengine-3.7.0/docs/economic-impact-analysis.md +0 -287
  95. policyengine-3.7.0/docs/index.md +0 -20
  96. policyengine-3.7.0/docs/myst.yml +0 -27
  97. policyengine-3.7.0/docs/regions-and-scoping.md +0 -251
  98. policyengine-3.7.0/examples/household_impact_example.py +0 -120
  99. policyengine-3.7.0/src/policyengine/core/__init__.py +0 -62
  100. policyengine-3.7.0/src/policyengine/core/simulation.py +0 -91
  101. policyengine-3.7.0/src/policyengine/tax_benefit_models/uk/analysis.py +0 -265
  102. policyengine-3.7.0/src/policyengine/tax_benefit_models/uk/outputs.py +0 -105
  103. policyengine-3.7.0/src/policyengine/tax_benefit_models/us/__init__.py +0 -55
  104. policyengine-3.7.0/src/policyengine/tax_benefit_models/us/analysis.py +0 -311
  105. policyengine-3.7.0/tests/test_household_impact.py +0 -202
  106. policyengine-3.7.0/tests/test_us_reform_application.py +0 -148
  107. {policyengine-3.7.0 → policyengine-4.3.0}/.claude/policyengine-guide.md +0 -0
  108. {policyengine-3.7.0 → policyengine-4.3.0}/.claude/quick-reference.md +0 -0
  109. {policyengine-3.7.0 → policyengine-4.3.0}/.github/CONTRIBUTING.md +0 -0
  110. {policyengine-3.7.0 → policyengine-4.3.0}/.github/bump_version.py +0 -0
  111. {policyengine-3.7.0 → policyengine-4.3.0}/.github/changelog_template.md +0 -0
  112. {policyengine-3.7.0 → policyengine-4.3.0}/.github/check-changelog.sh +0 -0
  113. {policyengine-3.7.0 → policyengine-4.3.0}/.github/fetch_version.py +0 -0
  114. {policyengine-3.7.0 → policyengine-4.3.0}/.github/get-changelog-diff.sh +0 -0
  115. {policyengine-3.7.0 → policyengine-4.3.0}/.github/has-functional-changes.sh +0 -0
  116. {policyengine-3.7.0 → policyengine-4.3.0}/.github/is-version-number-acceptable.sh +0 -0
  117. {policyengine-3.7.0 → policyengine-4.3.0}/.github/publish-git-tag.sh +0 -0
  118. {policyengine-3.7.0 → policyengine-4.3.0}/.github/workflows/pr_code_changes.yaml +0 -0
  119. {policyengine-3.7.0 → policyengine-4.3.0}/.github/workflows/push.yaml +0 -0
  120. {policyengine-3.7.0 → policyengine-4.3.0}/.gitignore +0 -0
  121. {policyengine-3.7.0 → policyengine-4.3.0}/.python-version +0 -0
  122. {policyengine-3.7.0 → policyengine-4.3.0}/LICENSE +0 -0
  123. {policyengine-3.7.0 → policyengine-4.3.0}/changelog.d/.gitkeep +0 -0
  124. {policyengine-3.7.0 → policyengine-4.3.0}/docs/visualisation.md +0 -0
  125. {policyengine-3.7.0 → policyengine-4.3.0}/examples/employment_income_variation_uk.py +0 -0
  126. {policyengine-3.7.0 → policyengine-4.3.0}/examples/employment_income_variation_us.py +0 -0
  127. {policyengine-3.7.0 → policyengine-4.3.0}/examples/income_bands_uk.py +0 -0
  128. {policyengine-3.7.0 → policyengine-4.3.0}/examples/income_distribution_us.py +0 -0
  129. {policyengine-3.7.0 → policyengine-4.3.0}/examples/paper_repro_uk.py +0 -0
  130. {policyengine-3.7.0 → policyengine-4.3.0}/examples/policy_change_uk.py +0 -0
  131. {policyengine-3.7.0 → policyengine-4.3.0}/examples/speedtest_us_simulation.py +0 -0
  132. {policyengine-3.7.0 → policyengine-4.3.0}/examples/us_budgetary_impact.py +0 -0
  133. {policyengine-3.7.0 → policyengine-4.3.0}/setup.cfg +0 -0
  134. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/core/cache.py +0 -0
  135. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/core/dataset.py +0 -0
  136. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/core/dynamic.py +0 -0
  137. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/core/output.py +0 -0
  138. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/core/parameter.py +0 -0
  139. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/core/parameter_node.py +0 -0
  140. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/core/parameter_value.py +0 -0
  141. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/core/policy.py +0 -0
  142. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/core/region.py +0 -0
  143. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/core/tax_benefit_model.py +0 -0
  144. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/core/variable.py +0 -0
  145. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/countries/__init__.py +0 -0
  146. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/countries/uk/__init__.py +0 -0
  147. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/countries/us/__init__.py +0 -0
  148. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/countries/us/data/__init__.py +0 -0
  149. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/countries/us/data/districts.py +0 -0
  150. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/countries/us/data/places.py +0 -0
  151. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/countries/us/data/states.py +0 -0
  152. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/data/schemas/trace_tro.schema.json +0 -0
  153. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/outputs/aggregate.py +0 -0
  154. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/outputs/change_aggregate.py +0 -0
  155. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/outputs/congressional_district_impact.py +0 -0
  156. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/outputs/decile_impact.py +0 -0
  157. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/outputs/inequality.py +0 -0
  158. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/outputs/intra_decile_impact.py +0 -0
  159. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/outputs/poverty.py +0 -0
  160. /policyengine-3.7.0/src/policyengine/core/release_manifest.py → /policyengine-4.3.0/src/policyengine/provenance/manifest.py +0 -0
  161. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/results/__init__.py +0 -0
  162. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/results/schema.py +0 -0
  163. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/results/tracking.py +0 -0
  164. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/utils/__init__.py +0 -0
  165. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/utils/dates.py +0 -0
  166. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/utils/design.py +0 -0
  167. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/utils/entity_utils.py +0 -0
  168. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/utils/parameter_labels.py +0 -0
  169. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/utils/parametric_reforms.py +0 -0
  170. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine/utils/plotting.py +0 -0
  171. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine.egg-info/dependency_links.txt +0 -0
  172. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine.egg-info/entry_points.txt +0 -0
  173. {policyengine-3.7.0 → policyengine-4.3.0}/src/policyengine.egg-info/top_level.txt +0 -0
  174. {policyengine-3.7.0 → policyengine-4.3.0}/tests/__init__.py +0 -0
  175. {policyengine-3.7.0 → policyengine-4.3.0}/tests/conftest.py +0 -0
  176. {policyengine-3.7.0 → policyengine-4.3.0}/tests/fixtures/__init__.py +0 -0
  177. {policyengine-3.7.0 → policyengine-4.3.0}/tests/fixtures/filtering_fixtures.py +0 -0
  178. {policyengine-3.7.0 → policyengine-4.3.0}/tests/fixtures/parameter_labels_fixtures.py +0 -0
  179. {policyengine-3.7.0 → policyengine-4.3.0}/tests/fixtures/parametric_reforms_fixtures.py +0 -0
  180. {policyengine-3.7.0 → policyengine-4.3.0}/tests/fixtures/poverty_by_demographics_fixtures.py +0 -0
  181. {policyengine-3.7.0 → policyengine-4.3.0}/tests/fixtures/region_fixtures.py +0 -0
  182. {policyengine-3.7.0 → policyengine-4.3.0}/tests/fixtures/variable_label_fixtures.py +0 -0
  183. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_aggregate.py +0 -0
  184. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_bump_version.py +0 -0
  185. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_cache.py +0 -0
  186. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_change_aggregate.py +0 -0
  187. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_congressional_district_impact.py +0 -0
  188. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_constituency_impact.py +0 -0
  189. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_entity_mapping.py +0 -0
  190. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_entity_utils.py +0 -0
  191. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_filtering.py +0 -0
  192. {policyengine-3.7.0/src/policyengine → policyengine-4.3.0/tests/test_graph}/__init__.py +0 -0
  193. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_inequality.py +0 -0
  194. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_intra_decile_impact.py +0 -0
  195. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_local_authority_impact.py +0 -0
  196. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_models.py +0 -0
  197. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_pandas3_compatibility.py +0 -0
  198. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_parameter_labels.py +0 -0
  199. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_parametric_reforms.py +0 -0
  200. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_poverty.py +0 -0
  201. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_poverty_by_demographics.py +0 -0
  202. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_poverty_run.py +0 -0
  203. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_region.py +0 -0
  204. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_results.py +0 -0
  205. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_scoping_strategy.py +0 -0
  206. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_uk_regions.py +0 -0
  207. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_us_regions.py +0 -0
  208. {policyengine-3.7.0 → policyengine-4.3.0}/tests/test_variable_labels.py +0 -0
  209. {policyengine-3.7.0 → policyengine-4.3.0}/uv.lock +0 -0
@@ -18,10 +18,7 @@ jobs:
18
18
  steps:
19
19
  - name: Checkout repo
20
20
  uses: actions/checkout@v4
21
- - uses: actions/setup-node@v4
22
- with:
23
- node-version: 18.x
24
- - name: Install MyST
25
- run: npm install -g mystmd
21
+ - name: Set up Quarto
22
+ uses: quarto-dev/quarto-actions/setup@v2
26
23
  - name: Test documentation builds
27
- run: cd docs && myst build --html
24
+ run: quarto render docs
@@ -1,3 +1,115 @@
1
+ ## [4.3.0] - 2026-04-20
2
+
3
+ ### Added
4
+
5
+ - Added `policyengine.provenance.refresh_release_bundle`. Given a country and optional new model/data versions, the helper fetches the updated PyPI wheel metadata + HF dataset sha256, rewrites `data/release_manifests/{country}.json` and the matching extra pin in `pyproject.toml`, and (optionally) regenerates the bundle's TRACE TRO sidecar. A thin `scripts/refresh_release_bundle.py` wrapper exposes the library function as a CLI for release engineers. Unit-tested offline via mocked PyPI/HF responses.
6
+
7
+
8
+ ## [4.2.1] - 2026-04-20
9
+
10
+ ### Changed
11
+
12
+ - Rewrite docs content for the v4 API: separate pages per task (households, reforms, microsim, outputs, impact analysis, regions), updated code samples against real output classes and `Simulation` dict reforms.
13
+
14
+
15
+ ## [4.2.0] - 2026-04-20
16
+
17
+ ### Added
18
+
19
+ - Added ``policyengine.graph`` — a static-analysis-based variable dependency graph for PolicyEngine source trees. ``extract_from_path(path)`` walks a directory of Variable subclasses, parses formula-method bodies for ``entity("<var>", period)`` and ``add(entity, period, [list])`` references, and returns a ``VariableGraph``. Queries include ``deps(var)`` (direct dependencies), ``impact(var)`` (transitive downstream), and ``path(src, dst)`` (shortest dependency chain). No runtime dependency on country models — indexes ``policyengine-us`` (4,577 variables) in under a second.
20
+
21
+
22
+ ## [4.1.1] - 2026-04-20
23
+
24
+ ### Fixed
25
+
26
+ - Fixed `Simulation.extra_variables` being silently ignored on the US and UK microsim paths. The field is declared on the base `Simulation` and honored by the household calculator, but the country `run()` methods previously only iterated `self.entity_variables` — extras passed via `Simulation(extra_variables={...})` never reached the output dataset. Both country paths now route through a shared `MicrosimulationModelVersion.resolve_entity_variables` helper that merges defaults with extras, dedupes overlapping entries, and validates entity keys + variable names with close-match suggestions. Closes #303.
27
+ - Fixed structural-reform propagation in the US microsim path. `Simulation(policy={"gov.contrib.ctc.*": ...})` previously crashed at `.ensure()` with `AttributeError: 'NoneType' object has no attribute 'entity'` because `_build_simulation_from_dataset` instantiated entities against the module-level `policyengine_us.system` (no reform applied) instead of `microsim.tax_benefit_system` (reform applied). Published external reforms that activate all three `gov.contrib.ctc.*.in_effect` gates (e.g., app.policyengine.org policy 94589) now run end-to-end through `pe.us.economic_impact_analysis`.
28
+
29
+
30
+ ## [4.1.0] - 2026-04-20
31
+
32
+ ### Added
33
+
34
+ - ``Simulation(policy={...})`` and ``Simulation(dynamic={...})`` now accept the same flat ``{"param.path": value}`` / ``{"param.path": {date: value}}`` dict that ``pe.{uk,us}.calculate_household(reform=...)`` accepts. Dicts are compiled to full ``Policy`` / ``Dynamic`` objects on construction using the ``tax_benefit_model_version`` for parameter-path validation and ``dataset.year`` for scalar effective-date defaulting. Removes the last place where population microsim required building ``Parameter`` / ``ParameterValue`` by hand.
35
+ - **BREAKING (v4):** Collapse the household-calculator surface into a
36
+ single agent-friendly entry point, ``pe.us.calculate_household`` /
37
+ ``pe.uk.calculate_household``.
38
+
39
+ New public API:
40
+
41
+ - ``policyengine/__init__.py`` populated with canonical accessors:
42
+ ``pe.us``, ``pe.uk``, ``pe.Simulation`` (replacing the empty top-level
43
+ module). ``import policyengine as pe`` now gives you everything a
44
+ new coding session needs to reach in one line.
45
+ - ``pe.us.calculate_household(**kwargs)`` and ``pe.uk.calculate_household``
46
+ take flat keyword arguments (``people``, per-entity overrides,
47
+ ``year``, ``reform``, ``extra_variables``) instead of a pydantic
48
+ input wrapper.
49
+ - ``reform=`` accepts a plain dict: ``{parameter_path: value}`` or
50
+ ``{parameter_path: {effective_date: value}}``. Compiles internally.
51
+ - Returns :class:`HouseholdResult` (new) with dot-access:
52
+ ``result.tax_unit.income_tax``, ``result.household.household_net_income``,
53
+ ``result.person[0].age``. Singleton entities are
54
+ :class:`EntityResult`; ``person`` is a list of them. ``to_dict()``
55
+ and ``write(path)`` serialize to JSON.
56
+ - ``extra_variables=[...]`` is now a flat list; the library dispatches
57
+ each name to its entity by looking it up on the model.
58
+ - Unknown variable names (in ``people``, entity overrides, or
59
+ ``extra_variables``) raise ``ValueError`` with a ``difflib`` close-match
60
+ suggestion and a paste-able fix hint.
61
+ - Unknown dot-access on a result raises ``AttributeError`` with the
62
+ list of available variables plus the ``extra_variables=[...]`` call
63
+ that would surface the requested one.
64
+
65
+ Removed (v4 breaking):
66
+
67
+ - ``USHouseholdInput`` / ``UKHouseholdInput`` / ``USHouseholdOutput`` /
68
+ ``UKHouseholdOutput`` pydantic wrappers.
69
+ - ``calculate_household_impact`` — the name was misleading (it
70
+ returned levels, not an impact vs. baseline). Reserved for a future
71
+ delta function.
72
+ - The bare ``us_model`` / ``uk_model`` label-only singletons; each
73
+ country module now exposes ``.model`` pointing at the real
74
+ ``TaxBenefitModelVersion`` (kept ``us_latest`` / ``uk_latest``
75
+ aliases for compatibility with any in-flight downstream code).
76
+
77
+ New internal module:
78
+
79
+ - ``policyengine.tax_benefit_models.common`` — ``compile_reform``,
80
+ ``dispatch_extra_variables``, ``EntityResult``, ``HouseholdResult``
81
+ shared by both country implementations.
82
+
83
+ ### Changed
84
+
85
+ - Extracted shared `MicrosimulationModelVersion` base class in `policyengine.tax_benefit_models.common`. Country subclasses now declare class-level metadata (`country_code`, `package_name`, `group_entities`) and implement a handful of thin hooks; `run()` stays per-country. Byte-level snapshot tests verify zero output drift.
86
+ - Documentation refreshed for the v4 agent-first surface. README, `core-concepts`, `economic-impact-analysis`, `country-models-{uk,us}`, `regions-and-scoping`, `examples`, and `dev` now lead with `pe.uk.*` / `pe.us.*` entry points and flat-kwarg `calculate_household` usage. Removed leftover docs for the dropped `filter_field`/`filter_value` simulation fields. `examples/household_impact_example.py` rewritten against the v4 API.
87
+ - **BREAKING (v4):** Separate the provenance layer from the core
88
+ value-object layer.
89
+
90
+ - ``policyengine/core/release_manifest.py`` → ``policyengine/provenance/manifest.py``
91
+ - ``policyengine/core/trace_tro.py`` → ``policyengine/provenance/trace.py``
92
+ - New ``policyengine.provenance`` package re-exports the public
93
+ surface (``get_release_manifest``, ``get_data_release_manifest``,
94
+ ``build_trace_tro_from_release_bundle``, ``build_simulation_trace_tro``,
95
+ ``serialize_trace_tro``, ``canonical_json_bytes``,
96
+ ``compute_trace_composition_fingerprint``, etc.).
97
+ - ``policyengine.core`` no longer re-exports provenance types.
98
+ ``policyengine.core`` shrinks to value objects only (Dataset,
99
+ Variable, Parameter, Policy, Dynamic, Simulation, Region,
100
+ TaxBenefitModel, TaxBenefitModelVersion, scoping strategies).
101
+ - ``import policyengine.core.scoping_strategy`` no longer imports
102
+ ``h5py`` at module load; the weight-replacement code path
103
+ lazy-imports it. ``import policyengine.outputs.constituency_impact``
104
+ and ``import policyengine.outputs.local_authority_impact`` do the
105
+ same.
106
+ - Migration for downstream: replace
107
+ ``from policyengine.core import DataReleaseManifest`` (et al.)
108
+ with ``from policyengine.provenance import DataReleaseManifest``.
109
+ The country-module imports in internal code (``tax_benefit_models/{us,uk}/model.py``
110
+ and ``datasets.py``) are already updated.
111
+
112
+
1
113
  ## [3.7.0] - 2026-04-19
2
114
 
3
115
  ### Removed
@@ -1,15 +1,12 @@
1
1
  .PHONY: docs docs-serve
2
2
 
3
- MYSTMD_VERSION ?= 1.8.3
4
- MYST_CMD = npx --yes mystmd@$(MYSTMD_VERSION)
5
-
6
3
  all: build-package
7
4
 
8
5
  docs:
9
- cd docs && $(MYST_CMD) build --html
6
+ quarto render docs
10
7
 
11
8
  docs-serve:
12
- cd docs && $(MYST_CMD) start
9
+ quarto preview docs
13
10
 
14
11
  install:
15
12
  uv pip install -e .[dev]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: policyengine
3
- Version: 3.7.0
3
+ Version: 4.3.0
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
@@ -682,6 +682,8 @@ Requires-Dist: psutil>=5.9.0
682
682
  Requires-Dist: packaging>=23.0
683
683
  Provides-Extra: plotting
684
684
  Requires-Dist: plotly>=5.0.0; extra == "plotting"
685
+ Provides-Extra: graph
686
+ Requires-Dist: networkx>=3.0; extra == "graph"
685
687
  Provides-Extra: uk
686
688
  Requires-Dist: policyengine_core>=3.25.0; extra == "uk"
687
689
  Requires-Dist: policyengine-uk==2.88.0; extra == "uk"
@@ -714,26 +716,47 @@ A Python package for tax-benefit microsimulation analysis. Run policy simulation
714
716
 
715
717
  ## Quick start
716
718
 
719
+ ### Household calculator
720
+
717
721
  ```python
718
- from policyengine.core import Simulation
719
- from policyengine.tax_benefit_models.uk import PolicyEngineUKDataset, uk_latest
720
- from policyengine.outputs.aggregate import Aggregate, AggregateType
722
+ import policyengine as pe
721
723
 
722
- # Load representative microdata
723
- dataset = PolicyEngineUKDataset(
724
- name="FRS 2023-24",
725
- filepath="./data/frs_2023_24_year_2026.h5",
724
+ # UK: single adult earning £50,000
725
+ uk = pe.uk.calculate_household(
726
+ people=[{"age": 35, "employment_income": 50_000}],
726
727
  year=2026,
727
728
  )
729
+ print(uk.person[0].income_tax) # income tax
730
+ print(uk.household.hbai_household_net_income) # net income
731
+
732
+ # US: single filer in California, with a reform
733
+ us = pe.us.calculate_household(
734
+ people=[{"age": 35, "employment_income": 60_000}],
735
+ tax_unit={"filing_status": "SINGLE"},
736
+ household={"state_code": "CA"},
737
+ year=2026,
738
+ reform={"gov.irs.credits.ctc.amount.adult_dependent": 1000},
739
+ )
740
+ print(us.tax_unit.income_tax, us.household.household_net_income)
741
+ ```
728
742
 
729
- # Run simulation
730
- simulation = Simulation(
731
- dataset=dataset,
732
- tax_benefit_model_version=uk_latest,
743
+ ### Population analysis
744
+
745
+ ```python
746
+ import policyengine as pe
747
+ from policyengine.core import Simulation
748
+ from policyengine.outputs.aggregate import Aggregate, AggregateType
749
+
750
+ datasets = pe.uk.ensure_datasets(
751
+ datasets=["hf://policyengine/policyengine-uk-data/enhanced_frs_2023_24.h5"],
752
+ years=[2026],
753
+ data_folder="./data",
733
754
  )
755
+ dataset = datasets["enhanced_frs_2023_24_2026"]
756
+
757
+ simulation = Simulation(dataset=dataset, tax_benefit_model_version=pe.uk.model)
734
758
  simulation.run()
735
759
 
736
- # Calculate total universal credit spending
737
760
  agg = Aggregate(
738
761
  simulation=simulation,
739
762
  variable="universal_credit",
@@ -744,6 +767,9 @@ agg.run()
744
767
  print(f"Total UC spending: £{agg.result / 1e9:.1f}bn")
745
768
  ```
746
769
 
770
+ For baseline-vs-reform comparisons, see `pe.uk.economic_impact_analysis`
771
+ and its US counterpart.
772
+
747
773
  ## Documentation
748
774
 
749
775
  **Core concepts:**
@@ -796,7 +822,7 @@ uv pip install -e .[dev] # install with dev dependencies (pytest, ruff, m
796
822
  ```bash
797
823
  make format # ruff format
798
824
  make test # pytest with coverage
799
- make docs # build static MyST/Jupyter Book 2 HTML docs
825
+ make docs # build static Quarto HTML docs
800
826
  make docs-serve # preview the docs locally
801
827
  make clean # remove caches, build artifacts, .h5 files
802
828
  ```
@@ -889,12 +915,12 @@ dataset.load()
889
915
  Simulations apply tax-benefit models to datasets:
890
916
 
891
917
  ```python
918
+ import policyengine as pe
892
919
  from policyengine.core import Simulation
893
- from policyengine.tax_benefit_models.uk import uk_latest
894
920
 
895
921
  simulation = Simulation(
896
922
  dataset=dataset,
897
- tax_benefit_model_version=uk_latest,
923
+ tax_benefit_model_version=pe.uk.model,
898
924
  )
899
925
  simulation.run()
900
926
 
@@ -933,7 +959,7 @@ import datetime
933
959
 
934
960
  parameter = Parameter(
935
961
  name="gov.hmrc.income_tax.allowances.personal_allowance.amount",
936
- tax_benefit_model_version=uk_latest,
962
+ tax_benefit_model_version=pe.uk.model,
937
963
  data_type=float,
938
964
  )
939
965
 
@@ -952,7 +978,7 @@ policy = Policy(
952
978
  # Run reform simulation
953
979
  reform_sim = Simulation(
954
980
  dataset=dataset,
955
- tax_benefit_model_version=uk_latest,
981
+ tax_benefit_model_version=pe.uk.model,
956
982
  policy=policy,
957
983
  )
958
984
  reform_sim.run()
@@ -4,26 +4,47 @@ A Python package for tax-benefit microsimulation analysis. Run policy simulation
4
4
 
5
5
  ## Quick start
6
6
 
7
+ ### Household calculator
8
+
7
9
  ```python
8
- from policyengine.core import Simulation
9
- from policyengine.tax_benefit_models.uk import PolicyEngineUKDataset, uk_latest
10
- from policyengine.outputs.aggregate import Aggregate, AggregateType
10
+ import policyengine as pe
11
11
 
12
- # Load representative microdata
13
- dataset = PolicyEngineUKDataset(
14
- name="FRS 2023-24",
15
- filepath="./data/frs_2023_24_year_2026.h5",
12
+ # UK: single adult earning £50,000
13
+ uk = pe.uk.calculate_household(
14
+ people=[{"age": 35, "employment_income": 50_000}],
16
15
  year=2026,
17
16
  )
17
+ print(uk.person[0].income_tax) # income tax
18
+ print(uk.household.hbai_household_net_income) # net income
19
+
20
+ # US: single filer in California, with a reform
21
+ us = pe.us.calculate_household(
22
+ people=[{"age": 35, "employment_income": 60_000}],
23
+ tax_unit={"filing_status": "SINGLE"},
24
+ household={"state_code": "CA"},
25
+ year=2026,
26
+ reform={"gov.irs.credits.ctc.amount.adult_dependent": 1000},
27
+ )
28
+ print(us.tax_unit.income_tax, us.household.household_net_income)
29
+ ```
18
30
 
19
- # Run simulation
20
- simulation = Simulation(
21
- dataset=dataset,
22
- tax_benefit_model_version=uk_latest,
31
+ ### Population analysis
32
+
33
+ ```python
34
+ import policyengine as pe
35
+ from policyengine.core import Simulation
36
+ from policyengine.outputs.aggregate import Aggregate, AggregateType
37
+
38
+ datasets = pe.uk.ensure_datasets(
39
+ datasets=["hf://policyengine/policyengine-uk-data/enhanced_frs_2023_24.h5"],
40
+ years=[2026],
41
+ data_folder="./data",
23
42
  )
43
+ dataset = datasets["enhanced_frs_2023_24_2026"]
44
+
45
+ simulation = Simulation(dataset=dataset, tax_benefit_model_version=pe.uk.model)
24
46
  simulation.run()
25
47
 
26
- # Calculate total universal credit spending
27
48
  agg = Aggregate(
28
49
  simulation=simulation,
29
50
  variable="universal_credit",
@@ -34,6 +55,9 @@ agg.run()
34
55
  print(f"Total UC spending: £{agg.result / 1e9:.1f}bn")
35
56
  ```
36
57
 
58
+ For baseline-vs-reform comparisons, see `pe.uk.economic_impact_analysis`
59
+ and its US counterpart.
60
+
37
61
  ## Documentation
38
62
 
39
63
  **Core concepts:**
@@ -86,7 +110,7 @@ uv pip install -e .[dev] # install with dev dependencies (pytest, ruff, m
86
110
  ```bash
87
111
  make format # ruff format
88
112
  make test # pytest with coverage
89
- make docs # build static MyST/Jupyter Book 2 HTML docs
113
+ make docs # build static Quarto HTML docs
90
114
  make docs-serve # preview the docs locally
91
115
  make clean # remove caches, build artifacts, .h5 files
92
116
  ```
@@ -179,12 +203,12 @@ dataset.load()
179
203
  Simulations apply tax-benefit models to datasets:
180
204
 
181
205
  ```python
206
+ import policyengine as pe
182
207
  from policyengine.core import Simulation
183
- from policyengine.tax_benefit_models.uk import uk_latest
184
208
 
185
209
  simulation = Simulation(
186
210
  dataset=dataset,
187
- tax_benefit_model_version=uk_latest,
211
+ tax_benefit_model_version=pe.uk.model,
188
212
  )
189
213
  simulation.run()
190
214
 
@@ -223,7 +247,7 @@ import datetime
223
247
 
224
248
  parameter = Parameter(
225
249
  name="gov.hmrc.income_tax.allowances.personal_allowance.amount",
226
- tax_benefit_model_version=uk_latest,
250
+ tax_benefit_model_version=pe.uk.model,
227
251
  data_type=float,
228
252
  )
229
253
 
@@ -242,7 +266,7 @@ policy = Policy(
242
266
  # Run reform simulation
243
267
  reform_sim = Simulation(
244
268
  dataset=dataset,
245
- tax_benefit_model_version=uk_latest,
269
+ tax_benefit_model_version=pe.uk.model,
246
270
  policy=policy,
247
271
  )
248
272
  reform_sim.run()
@@ -0,0 +1,5 @@
1
+ # Quarto build outputs
2
+ _site
3
+ _freeze
4
+ /.quarto/
5
+ **/*.quarto_ipynb
@@ -0,0 +1,52 @@
1
+ # Reference generator prototype
2
+
3
+ Auto-generates one Quarto page per variable in a country model, plus a program-coverage page, purely from metadata on the `Variable` classes and `programs.yaml`.
4
+
5
+ ## Run
6
+
7
+ ```bash
8
+ # Full US reference (takes a couple of minutes — 4,686 variables)
9
+ python docs/_generator/build_reference.py --country us --out docs/_generated/reference/us
10
+
11
+ # Preview a filtered subset
12
+ python docs/_generator/build_reference.py --country us --filter chip --out /tmp/ref-preview
13
+ ```
14
+
15
+ Then render:
16
+
17
+ ```bash
18
+ cd /tmp/ref-preview && quarto render
19
+ ```
20
+
21
+ ## What's generated from code alone
22
+
23
+ Per variable:
24
+
25
+ - Title and identifier
26
+ - Metadata table: entity, value type, unit, period, `defined_for` gate
27
+ - Documentation (docstring)
28
+ - Components (`adds` / `subtracts` lists)
29
+ - Statutory references (from `reference = ...`)
30
+ - Source file path and line number
31
+
32
+ Per program: a row in the generated program-coverage page pulled from `programs.yaml` (id, name, category, agency, status, coverage).
33
+
34
+ Per directory (`gov/hhs/chip/`, `gov/usda/snap/`, etc.): a listing page using Quarto's built-in directory listing so the nav auto-organizes.
35
+
36
+ ## What still requires hand-authored prose
37
+
38
+ - Methodology narrative (why the model is structured this way)
39
+ - Tutorials (how to use `policyengine.py`)
40
+ - Paper content (peer-reviewable argument)
41
+ - Per-country deep dives that read as essays rather than reference lookups
42
+
43
+ ## Design
44
+
45
+ The generator reads directly from the imported country model — no web API calls, no intermediate JSON. This keeps the build offline-reproducible and version-pinned to whatever country model the `policyengine.py` package has installed. Re-running the generator on release produces a snapshot of the reference docs tied to the exact published model versions.
46
+
47
+ Extensions worth considering:
48
+
49
+ 1. Walk `parameters/` YAML tree and emit a page per parameter with its time series, breakdowns, and references.
50
+ 2. For each variable with a formula, surface the dependency graph (other variables / parameters it reads). `policyengine_core`'s `Variable.exhaustive_parameter_dependencies` gets partway there.
51
+ 3. For each calibration target (in `policyengine-us-data/storage/calibration_targets/*.csv`), emit a page describing source, aggregation level, freshness.
52
+ 4. Cross-link variables to the programs they contribute to via `programs.yaml`'s `variable:` field.