Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/obr-source-manifest.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Build the OBR targets only from the committed EFO workbooks named, with their SHA-256 and title, in a vintage manifest (`targets/source_manifests/`). Read each table's financial years from its header row rather than fixed column letters, and fail the build when a manifest target or year is missing instead of logging and dropping it. Add `python -m policyengine_uk_data.targets.obr_sources ingest` for adopting a new EFO vintage, which prints every target's change; its `--dry-run` reports, and exits non-zero on, an ingested vintage, an interrupted ingest's leftovers or a download page off obr.uk, which the real ingest refuses.
799 changes: 799 additions & 0 deletions policyengine_uk_data/targets/obr_sources.py

Large diffs are not rendered by default.

75 changes: 75 additions & 0 deletions policyengine_uk_data/targets/source_manifests/obr_march_2026.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# OBR Economic and fiscal outlook, March 2026: detailed forecast tables.
# The bytes, not this file's labels, decide the vintage: builds verify each
# workbook's SHA-256, size and own title (Contents!B2) before parsing it.
# See targets/obr_sources.py for every field.
schema_version: 1
vintage: march_2026
label: March 2026
# Financial years every parsed table must head, by the calendar year they
# start in: 2024-25 to 2030-31.
first_year: 2024
last_year: 2030
unit: £ billion
# Neither workbook has a downloaded_at. Both entered git in 11e41f9d, so
# they were downloaded no later than 2026-07-21T21:06:50+01:00, but nothing
# recorded when (git keeps no file times): their download time is neither an
# mtime nor a given one.
files:
receipts:
path: obr_efo/efo_receipts.xlsx
sha256: f65b6cb7f96931d4abd85940794eb60f6f65afca8bbf16c74a4548bf92766a28
size_bytes: 187899
title: "March 2026 Economic and fiscal outlook – detailed forecast tables: receipts"
url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-receipts/
retrieved: >-
Committed on 2026-07-21 in 11e41f9d, as the download fallback. The
workbook's own properties record it as modified on 2026-03-02.
obr.uk refused scripted downloads on 2026-10-15 (HTTP 403), so the
bytes were not re-fetched for this manifest.
downloaded_at_basis: unrecorded
expenditure:
path: obr_efo/efo_expenditure.xlsx
sha256: 700bfd700c872794e5fe8cf164086cd38a63850db26427b9d4b2e363d177d9a1
size_bytes: 236965
title: "March 2026 Economic and fiscal outlook – detailed forecast tables: expenditure"
url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/
retrieved: >-
Committed on 2026-07-21 in 11e41f9d, as the download fallback. The
workbook's own properties record it as modified on 2026-03-02.
obr.uk refused scripted downloads on 2026-10-15 (HTTP 403), so the
bytes were not re-fetched for this manifest.
downloaded_at_basis: unrecorded
# Every target the workbooks must yield, each with every year above. A
# target the parsers build that is not listed here also fails, so changing
# the target set means changing this list.
targets:
required:
- obr/income_tax
- obr/ni
- obr/vat
- obr/fuel_duties
- obr/capital_gains_tax
- obr/sdlt
- obr/ni_employee
- obr/ni_employer
- obr/council_tax
- obr/council_tax_england
- obr/council_tax_scotland
- obr/council_tax_wales
- obr/domestic_rates
- obr/pip
- obr/esa
- obr/attendance_allowance
- obr/carers_allowance
- obr/statutory_maternity_pay
- obr/winter_fuel_allowance
- obr/child_benefit
- obr/state_pension
- obr/jobseekers_allowance
- obr/universal_credit
- obr/tv_licence_fee
# Self-employed NICs: one combined Class 2 and 4 line (March 2026), or
# the two classes on separate rows (earlier vintages).
- any_of:
- [obr/ni_self_employed]
- [obr/ni_class_2, obr/ni_class_4]
7 changes: 4 additions & 3 deletions policyengine_uk_data/targets/sources.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
# Update these when new vintages are published.

obr:
efo_receipts: "https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-receipts/"
efo_expenditure: "https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/"
vintage: "march_2026"
# The EFO vintage the OBR targets come from: a manifest in
# targets/source_manifests/ naming its hash-verified workbooks. Adopt a new
# vintage with `python -m policyengine_uk_data.targets.obr_sources ingest`.
manifest: obr_march_2026.yaml

hmrc:
spi_collated: "https://assets.publishing.service.gov.uk/media/69f1f12d2fae53a03709682f/Collated_Tables_3_1_to_3_11_2324.ods"
Expand Down
Loading
Loading