Sitemap regeneration failed on staging. 'richmond' in the curated locality list collides with the GIAS town Richmond in North Yorkshire (37 schools), the registry raised, and the admin endpoint 500d — taking down sitemap generation for all 25,000 school pages over one bad row of curated data. The guard now skips the colliding locality and logs an error. Skipping still achieves what the guard was for — a locality never silently shadows a town — without letting curated data break the site. That matters beyond this bug: GIAS town names change with no code change here, so a raise could fire spontaneously in production later. Also removes four localities that were London boroughs rather than districts. Hackney, Islington, Greenwich and Ealing are local authorities with 104, 72, 108 and 115 schools and already have authority pages; a locality defined by two or three outcodes would have been a partial near-duplicate of one — the thin-content failure the two-namespace design exists to avoid. A test now guards the whole borough list. Validated against the live corpus: 15 localities, no town collisions, no authority duplicates, all 15 clear the threshold. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015mWQnpye9F299NVRCCSRvj
55 lines
2.7 KiB
Python
55 lines
2.7 KiB
Python
"""Curated London localities, defined by the postcode districts they cover.
|
|
|
|
The GIAS `town` field puts 1,819 London schools under the single value
|
|
"London", so it cannot answer "schools in Battersea" — a query that appears in
|
|
the Search Console baseline. No single field can: parliamentary constituency
|
|
gives Battersea but not Canary Wharf; postcodes.io's admin_ward gives Canary
|
|
Wharf but not Battersea; neither gives Clapham or Shoreditch, which are postal
|
|
and colloquial rather than administrative.
|
|
|
|
So this is curated. Where a locality ends is a judgement, not a fact, and a
|
|
reviewable file is the honest place for a judgement. No new ingestion is
|
|
needed — the corpus already carries postcodes.
|
|
|
|
This is the canonical copy. `pipeline/transform/seeds/locality_outcodes.csv`
|
|
mirrors it for anyone querying the warehouse directly; the backend image does
|
|
not contain `pipeline/`, which is why the module rather than the seed is
|
|
canonical. Same arrangement as `backend/gias_codes.py`.
|
|
|
|
A locality whose outcodes hold fewer than MIN_SCHOOLS schools is not
|
|
published, so a typo produces no page rather than an empty one. Places that
|
|
fail that check are logged at startup, because a locality you meant to publish
|
|
quietly not appearing is the failure worth hearing about.
|
|
|
|
Two rules for anything added here.
|
|
|
|
**Sub-borough districts only.** A London borough is a local authority and
|
|
already has a page at /schools/authority/[la] covering all of its schools; a
|
|
locality defined by two or three outcodes would be a partial, near-duplicate
|
|
subset of it. Hackney, Islington, Greenwich and Ealing were all in the first
|
|
draft for that reason and have been removed.
|
|
|
|
**The slug must not match a GIAS town.** "Richmond" did — GIAS has a Richmond
|
|
in North Yorkshire with 37 schools — so the London one could never publish.
|
|
The registry skips any locality that collides and logs it.
|
|
"""
|
|
|
|
# slug -> (display name, outcodes)
|
|
LOCALITY_OUTCODES: dict[str, tuple[str, tuple[str, ...]]] = {
|
|
"battersea": ("Battersea", ("SW11",)),
|
|
"canary-wharf": ("Canary Wharf", ("E14",)),
|
|
"clapham": ("Clapham", ("SW4",)),
|
|
"shoreditch": ("Shoreditch", ("EC2A", "E1")),
|
|
"peckham": ("Peckham", ("SE15",)),
|
|
"brixton": ("Brixton", ("SW2", "SW9")),
|
|
"camden-town": ("Camden Town", ("NW1",)),
|
|
"wimbledon": ("Wimbledon", ("SW19",)),
|
|
"putney": ("Putney", ("SW15",)),
|
|
"fulham": ("Fulham", ("SW6",)),
|
|
"chiswick": ("Chiswick", ("W4",)),
|
|
"stratford": ("Stratford", ("E15",)),
|
|
"walthamstow": ("Walthamstow", ("E17",)),
|
|
"tooting": ("Tooting", ("SW17",)),
|
|
"dulwich": ("Dulwich", ("SE21", "SE22")),
|
|
}
|