Skip to content

Schema decision: semantics of the column pattern entry for wide files #120

Description

@mmcky

A schema.columns entry carries either name (one exact column) or pattern (a regex matching a run of columns). pattern was proposed in #14 and first used on 2026-09-01; four manifests use it today (business_cycle_data.csv.yml, unemployment_rate_annual.csv.yml, private_credit_to_gdp.csv.yml, chapter_3.xlsx.yml), all for wide files whose column set grows. manifest-schema.yml documents the field but not its semantics, and no validator reads it yet.

To decide before the manifest-driven validate() enforces it:

  1. Regex dialect and anchoring: full-match or search; Python re as the reference.
  2. Ordering and contiguity: must the matched run be contiguous, and in the position it appears in the columns list, or is it a set membership test? business_cycle additionally asserts an unbroken year grid, which is stronger than any regex says.
  3. Minimum run length: does a pattern that matches zero columns pass (schema silent) or fail (file lost its wide part)?
  4. Exhaustiveness: must every column in the file be claimed by exactly one name or pattern entry, so an unexpected column fails validation? (business_cycle's own check says yes.)
  5. Whether date_range for a wide file is derived from the pattern's matched columns, as scripts/snapshots.py already does when stamping date_range.end.

Record the outcome in manifest-schema.yml's comment on pattern, and touch the four manifests only if the decision changes what they mean.

Sub-issue of #14.

Activity

  1. added theissue type on Sep 2, 2026
  2. mmcky commented on Sep 6, 2026

    @mmcky
    ContributorAuthor

    Decision, 2026-09-07: ordered, contiguous, exhaustive, at least one match, and a capture group carries the date

    Settled the five questions against what the repo does today rather than in the abstract. Three CSV manifests carry the same entry (YR\d{4}, float64) for the three World Bank tables, each with 68 header columns on an unbroken grid from YR1960 to YR2025; chapter_3.xlsx.yml's sheets_pattern is a sibling key for sheet names and is not covered here. builders/business_cycle.py's hand-written validate() is already stricter than any regex: it requires the year columns to be every column after Country, to start at 1960, to have no gap, and to be float, and it derives date_range.end from the last year column, which scripts/snapshots.py stamp then writes into the manifest. So the de facto semantics were already ordered, contiguous, exhaustive and date-bearing; this records them so the shared validate() (#119) can enforce them.

    question decision
    1. dialect and anchoring Python re, fullmatch — YR\d{4} cannot match YR19601
    2. ordering and contiguity the validator walks columns in order; a pattern entry consumes the maximal run of consecutive matching columns, in the position it appears. Column order is part of the contract because positional reads exist in the lectures
    3. minimum run one. Zero matches fails with "wide part missing". No min_count field until a file needs a floor above one
    4. exhaustiveness every file column must be claimed by exactly one name or pattern entry; an unclaimed column fails
    5. date_range for wide files derived from the matched columns when the pattern has exactly one capture group: YR(\d{4}). The grid check (no gaps) stays builder-specific, layered on top

    What the validator reads. The manifest describes the CSV header as written, so the validator reads the raw file with pandas defaults, honouring the manifest's existing delimiter and read_as keys, and no index_col — even though business_cycle.py reads with index_col=0 and sees Country first. The manifest stays a description of the bytes on disk; the read-options half of this is recorded on #122.

    Edits this implies. YR\d{4} → YR(\d{4}) in business_cycle_data.csv.yml, unemployment_rate_annual.csv.yml and private_credit_to_gdp.csv.yml (a two-character change that alters nothing about what they mean), and the pattern comment in manifest-schema.yml rewritten to say the above. Both ride with #119 or a small precursor PR; this issue closes when manifest-schema.yml records it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions