From 203486a9d327c111b3d090aab7a72a9c522df248 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Sun, 11 Oct 2026 14:11:46 +0200 Subject: [PATCH] Answer architecture round 8: a shipped package's folder spells its namespace (data/sv_SE, data/geo/SE) under its lowered Go name, as a second bench chose, a mounted root folder reads as its namespace, and item 196 cites goal 9.2 --- AGENTS.md | 2 +- CHANGELOG.md | 4 +-- DATA-LICENSES.md | 18 ++++++------ README.md | 17 +++++------ data-import/geo-se.py | 2 +- data-import/geo-us.py | 2 +- data-import/geo.py | 4 +-- data-import/names-se.py | 4 +-- data-import/names-us.py | 4 +-- data/{enus => en_US}/.fejkdata.json | 0 data/{enus => en_US}/address.json | 0 data/{enus => en_US}/color.json | 0 data/{enus => en_US}/company.json | 0 data/{enus => en_US}/date.json | 0 data/{enus => en_US}/email.json | 0 data/{enus => en_US}/first-name.json | 0 data/{enus => en_US}/first-name.tsv | 0 data/{enus => en_US}/fs.go | 0 data/{enus => en_US}/ip.json | 0 data/{enus => en_US}/itin.json | 0 data/{enus => en_US}/last-name.json | 0 data/{enus => en_US}/last-name.tsv | 0 data/{enus => en_US}/person.json | 0 data/{enus => en_US}/phone-exchange.json | 0 data/{enus => en_US}/phone.json | 0 data/{enus => en_US}/price.json | 0 data/{enus => en_US}/sentence.json | 0 data/{enus => en_US}/sex.json | 0 data/{enus => en_US}/sex.tsv | 0 data/{enus => en_US}/ssn.json | 0 data/{enus => en_US}/time.json | 0 data/{enus => en_US}/title.json | 0 data/{enus => en_US}/title.tsv | 0 data/{enus => en_US}/url.json | 0 data/{enus => en_US}/username.json | 0 data/{enus => en_US}/version.json | 0 data/{enus => en_US}/word.json | 0 data/{geose => geo/SE}/.fejkdata.json | 0 data/{geose => geo/SE}/address.json | 0 data/{geose => geo/SE}/fs.go | 0 data/{geose => geo/SE}/locality.json | 0 data/{geose => geo/SE}/locality.tsv | 0 data/{geose => geo/SE}/municipality.json | 0 data/{geose => geo/SE}/municipality.tsv | 0 data/{geose => geo/SE}/postal-code.json | 0 data/{geose => geo/SE}/postal-code.tsv | 0 data/{geose => geo/SE}/region.json | 0 data/{geose => geo/SE}/region.tsv | 0 data/{geose => geo/SE}/street.json | 0 data/{geose => geo/SE}/street.tsv | 0 data/{geous => geo/US}/.fejkdata.json | 0 data/{geous => geo/US}/address.json | 0 data/{geous => geo/US}/fs.go | 0 data/{geous => geo/US}/locality.json | 0 data/{geous => geo/US}/locality.tsv | 0 data/{geous => geo/US}/municipality.json | 0 data/{geous => geo/US}/municipality.tsv | 0 data/{geous => geo/US}/postal-code.json | 0 data/{geous => geo/US}/postal-code.tsv | 0 data/{geous => geo/US}/region.json | 0 data/{geous => geo/US}/region.tsv | 0 data/{geous => geo/US}/street.json | 0 data/{geous => geo/US}/street.tsv | 0 data/modules.go | 8 +++--- data/{svse => sv_SE}/.fejkdata.json | 0 data/{svse => sv_SE}/address.json | 0 data/{svse => sv_SE}/birth-number.json | 0 data/{svse => sv_SE}/birth-number.tsv | 0 data/{svse => sv_SE}/color.json | 0 data/{svse => sv_SE}/company.json | 0 data/{svse => sv_SE}/date.json | 0 data/{svse => sv_SE}/email.json | 0 data/{svse => sv_SE}/first-name.json | 0 data/{svse => sv_SE}/first-name.tsv | 0 data/{svse => sv_SE}/fs.go | 0 data/{svse => sv_SE}/ip.json | 0 data/{svse => sv_SE}/last-name.json | 0 data/{svse => sv_SE}/last-name.tsv | 0 data/{svse => sv_SE}/person.json | 0 data/{svse => sv_SE}/personnummer.json | 0 data/{svse => sv_SE}/phone.json | 0 data/{svse => sv_SE}/price.json | 0 data/{svse => sv_SE}/samordningsnummer.json | 0 data/{svse => sv_SE}/sentence.json | 0 data/{svse => sv_SE}/sex.json | 0 data/{svse => sv_SE}/sex.tsv | 0 data/{svse => sv_SE}/time.json | 0 data/{svse => sv_SE}/title.json | 0 data/{svse => sv_SE}/title.tsv | 0 data/{svse => sv_SE}/url.json | 0 data/{svse => sv_SE}/username.json | 0 data/{svse => sv_SE}/version.json | 0 data/{svse => sv_SE}/word.json | 0 docs/comprehension-history.md | 32 +++++++++++++++++++++ docs/decisions.md | 22 ++++++++------ internal/datafiles/datafiles.go | 2 ++ todo.md | 2 +- 97 files changed, 81 insertions(+), 42 deletions(-) rename data/{enus => en_US}/.fejkdata.json (100%) rename data/{enus => en_US}/address.json (100%) rename data/{enus => en_US}/color.json (100%) rename data/{enus => en_US}/company.json (100%) rename data/{enus => en_US}/date.json (100%) rename data/{enus => en_US}/email.json (100%) rename data/{enus => en_US}/first-name.json (100%) rename data/{enus => en_US}/first-name.tsv (100%) rename data/{enus => en_US}/fs.go (100%) rename data/{enus => en_US}/ip.json (100%) rename data/{enus => en_US}/itin.json (100%) rename data/{enus => en_US}/last-name.json (100%) rename data/{enus => en_US}/last-name.tsv (100%) rename data/{enus => en_US}/person.json (100%) rename data/{enus => en_US}/phone-exchange.json (100%) rename data/{enus => en_US}/phone.json (100%) rename data/{enus => en_US}/price.json (100%) rename data/{enus => en_US}/sentence.json (100%) rename data/{enus => en_US}/sex.json (100%) rename data/{enus => en_US}/sex.tsv (100%) rename data/{enus => en_US}/ssn.json (100%) rename data/{enus => en_US}/time.json (100%) rename data/{enus => en_US}/title.json (100%) rename data/{enus => en_US}/title.tsv (100%) rename data/{enus => en_US}/url.json (100%) rename data/{enus => en_US}/username.json (100%) rename data/{enus => en_US}/version.json (100%) rename data/{enus => en_US}/word.json (100%) rename data/{geose => geo/SE}/.fejkdata.json (100%) rename data/{geose => geo/SE}/address.json (100%) rename data/{geose => geo/SE}/fs.go (100%) rename data/{geose => geo/SE}/locality.json (100%) rename data/{geose => geo/SE}/locality.tsv (100%) rename data/{geose => geo/SE}/municipality.json (100%) rename data/{geose => geo/SE}/municipality.tsv (100%) rename data/{geose => geo/SE}/postal-code.json (100%) rename data/{geose => geo/SE}/postal-code.tsv (100%) rename data/{geose => geo/SE}/region.json (100%) rename data/{geose => geo/SE}/region.tsv (100%) rename data/{geose => geo/SE}/street.json (100%) rename data/{geose => geo/SE}/street.tsv (100%) rename data/{geous => geo/US}/.fejkdata.json (100%) rename data/{geous => geo/US}/address.json (100%) rename data/{geous => geo/US}/fs.go (100%) rename data/{geous => geo/US}/locality.json (100%) rename data/{geous => geo/US}/locality.tsv (100%) rename data/{geous => geo/US}/municipality.json (100%) rename data/{geous => geo/US}/municipality.tsv (100%) rename data/{geous => geo/US}/postal-code.json (100%) rename data/{geous => geo/US}/postal-code.tsv (100%) rename data/{geous => geo/US}/region.json (100%) rename data/{geous => geo/US}/region.tsv (100%) rename data/{geous => geo/US}/street.json (100%) rename data/{geous => geo/US}/street.tsv (100%) rename data/{svse => sv_SE}/.fejkdata.json (100%) rename data/{svse => sv_SE}/address.json (100%) rename data/{svse => sv_SE}/birth-number.json (100%) rename data/{svse => sv_SE}/birth-number.tsv (100%) rename data/{svse => sv_SE}/color.json (100%) rename data/{svse => sv_SE}/company.json (100%) rename data/{svse => sv_SE}/date.json (100%) rename data/{svse => sv_SE}/email.json (100%) rename data/{svse => sv_SE}/first-name.json (100%) rename data/{svse => sv_SE}/first-name.tsv (100%) rename data/{svse => sv_SE}/fs.go (100%) rename data/{svse => sv_SE}/ip.json (100%) rename data/{svse => sv_SE}/last-name.json (100%) rename data/{svse => sv_SE}/last-name.tsv (100%) rename data/{svse => sv_SE}/person.json (100%) rename data/{svse => sv_SE}/personnummer.json (100%) rename data/{svse => sv_SE}/phone.json (100%) rename data/{svse => sv_SE}/price.json (100%) rename data/{svse => sv_SE}/samordningsnummer.json (100%) rename data/{svse => sv_SE}/sentence.json (100%) rename data/{svse => sv_SE}/sex.json (100%) rename data/{svse => sv_SE}/sex.tsv (100%) rename data/{svse => sv_SE}/time.json (100%) rename data/{svse => sv_SE}/title.json (100%) rename data/{svse => sv_SE}/title.tsv (100%) rename data/{svse => sv_SE}/url.json (100%) rename data/{svse => sv_SE}/username.json (100%) rename data/{svse => sv_SE}/version.json (100%) rename data/{svse => sv_SE}/word.json (100%) diff --git a/AGENTS.md b/AGENTS.md index 4d10aa3..52690e5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -47,7 +47,7 @@ In [docs/decisions.md](docs/decisions.md): - `FakeTemplate` and `NewTemplate` both stay - The shipped data is embedded, not discovered - The shipped data is Go packages a library imports by choice, and the CLI carries every one, from 0.1.0 -- A shipped package is named by its namespace in lower case without separators, and its manifest mounts it there with `namespace` +- A shipped package's folder spells its namespace, its Go name is that namespace in lower case without separators, and its manifest mounts it with `namespace` - A source whose manifest carries an index loads each category on first reach; any other loads in `New`, with what it reads - Every `{…}` draws afresh, and only a name keeps a pick - Reference sigils follow the filesystem diff --git a/CHANGELOG.md b/CHANGELOG.md index 279ead2..9f6e2ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -126,8 +126,8 @@ replacement, and each removed path, column or flag. `sv_SE.sex[f].first-name[Kim]`, and a category with no columns names the record that gives it one. - The shipped data comes in Go packages, one per module, each exporting `FS`: - `github.com/larvit/fejkdata/data/enus`, `…/svse`, `…/misc`, `…/geose` and - `…/geous`. `data.Modules()`, from `github.com/larvit/fejkdata/data`, lists every one, + `github.com/larvit/fejkdata/data/en_US` (package `enus`), `…/sv_SE` (`svse`), `…/misc`, + `…/geo/SE` (`geose`) and `…/geo/US` (`geous`). `data.Modules()`, from `github.com/larvit/fejkdata/data`, lists every one, and the CLI carries them all. `New` loads the modules `WithDataFS(modules...)` names and the folders `WithDataPath` names, and fails, naming `WithDataFS`, where no such option is given. A manifest's `namespace` mounts its source under a dot path. diff --git a/DATA-LICENSES.md b/DATA-LICENSES.md index 95b8471..f8e527f 100644 --- a/DATA-LICENSES.md +++ b/DATA-LICENSES.md @@ -6,15 +6,15 @@ Every shipped dataset, its source, its licence and the attribution it asks for. | Table | Source | Licence | Attribution | Rebuild | |-------|--------|---------|-------------|---------| -| `geose/locality.tsv`, `postal-code.tsv` | [GeoNames](https://www.geonames.org/) postal codes for SE; populations from SCB tätorter 2023 | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/); CC0 1.0 | "Postal codes from GeoNames, www.geonames.org" | `data-import/geo-se.py` | -| `geose/region.tsv`, `municipality.tsv` | [SCB](https://www.scb.se/) län and kommun codes 2026 and population 2024 | [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/) | none required | `data-import/geo-se.py` | -| `geose/street.tsv` | [Trafikverket NVDB](https://www.trafikverket.se/) Gatunamn, through the open API | CC0 1.0 | none required | `data-import/geo-se.py` | -| `geous/region.tsv`, `municipality.tsv`, `locality.tsv` | [Census Bureau](https://www.census.gov/) Gazetteer 2026 and population estimates 2025 | [public domain](https://www.usa.gov/government-works) | none required | `data-import/geo-us.py` | -| `geous/postal-code.tsv`, `street.tsv` | Census Bureau ZCTA to place relationships 2020 and TIGER/Line 2025 address ranges and feature names | public domain | none required | `data-import/geo-us.py` | -| `svse/first-name.tsv`, `last-name.tsv` | [SCB](https://www.scb.se/) names with at least two bearers, 31 December 2022 | CC0 1.0 | "Källa: SCB" | `data-import/names-se.py` | -| `enus/first-name.tsv` | [SSA](https://www.ssa.gov/oact/babynames/) baby names, births 1930 to 2020, through [hackerb9/ssa-baby-names](https://github.com/hackerb9/ssa-baby-names) | public domain | none required | `data-import/names-us.py` | -| `enus/last-name.tsv` | Census Bureau surnames occurring 100 or more times, 2010 | public domain | none required | `data-import/names-us.py` | -| `svse/sex.tsv`, `svse/birth-number.tsv`, `svse/title.tsv`, `enus/sex.tsv`, `enus/title.tsv`, `misc/car.tsv` | curated; Skatteverket's test birth numbers are facts, and `car.tsv` waits for an international source (goal 14) | — | — | — | +| `geo/SE/locality.tsv`, `postal-code.tsv` | [GeoNames](https://www.geonames.org/) postal codes for SE; populations from SCB tätorter 2023 | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/); CC0 1.0 | "Postal codes from GeoNames, www.geonames.org" | `data-import/geo-se.py` | +| `geo/SE/region.tsv`, `municipality.tsv` | [SCB](https://www.scb.se/) län and kommun codes 2026 and population 2024 | [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/) | none required | `data-import/geo-se.py` | +| `geo/SE/street.tsv` | [Trafikverket NVDB](https://www.trafikverket.se/) Gatunamn, through the open API | CC0 1.0 | none required | `data-import/geo-se.py` | +| `geo/US/region.tsv`, `municipality.tsv`, `locality.tsv` | [Census Bureau](https://www.census.gov/) Gazetteer 2026 and population estimates 2025 | [public domain](https://www.usa.gov/government-works) | none required | `data-import/geo-us.py` | +| `geo/US/postal-code.tsv`, `street.tsv` | Census Bureau ZCTA to place relationships 2020 and TIGER/Line 2025 address ranges and feature names | public domain | none required | `data-import/geo-us.py` | +| `sv_SE/first-name.tsv`, `last-name.tsv` | [SCB](https://www.scb.se/) names with at least two bearers, 31 December 2022 | CC0 1.0 | "Källa: SCB" | `data-import/names-se.py` | +| `en_US/first-name.tsv` | [SSA](https://www.ssa.gov/oact/babynames/) baby names, births 1930 to 2020, through [hackerb9/ssa-baby-names](https://github.com/hackerb9/ssa-baby-names) | public domain | none required | `data-import/names-us.py` | +| `en_US/last-name.tsv` | Census Bureau surnames occurring 100 or more times, 2010 | public domain | none required | `data-import/names-us.py` | +| `sv_SE/sex.tsv`, `sv_SE/birth-number.tsv`, `sv_SE/title.tsv`, `en_US/sex.tsv`, `en_US/title.tsv`, `misc/car.tsv` | curated; Skatteverket's test birth numbers are facts, and `car.tsv` waits for an international source (goal 14) | — | — | — | | `misc/currency.tsv` | [datasets/currency-codes](https://github.com/datasets/currency-codes); symbols from [Unicode CLDR](https://github.com/unicode-org/cldr) `en.xml` and `root.xml` | PDDL 1.0; [Unicode License v3](https://www.unicode.org/license.txt) | CLDR: "Copyright © 1991-2025 Unicode, Inc. Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the United States and other countries." | `data-import/currency.py` | | `misc/httpmethod.tsv` | [IANA HTTP Method Registry](https://www.iana.org/assignments/http-methods/) | [public domain](https://www.iana.org/help/licensing-terms) | none required | `data-import/httpmethod.py` | | `misc/httpstatus.tsv` | [IANA HTTP Status Code Registry](https://www.iana.org/assignments/http-status-codes/) | [public domain](https://www.iana.org/help/licensing-terms) | none required | `data-import/httpstatus.py` | diff --git a/README.md b/README.md index 4fa02e7..ddce852 100644 --- a/README.md +++ b/README.md @@ -160,10 +160,11 @@ it to a name and read the name ## Data -The shipped data comes in modules, each a Go package under [`data/`](data) named by its -namespace in lower case without separators: one per locale (`enus` for `en_US`, `svse` -for `sv_SE`), one per country's tree of places (`geose` for `geo.SE`, `geous` for -`geo.US`), and the locale-neutral `misc`. Each embeds its files, so nothing is read from +The shipped data comes in modules, each a Go package in the folder under [`data/`](data) +its namespace spells, a dot a slash: one per locale (`data/en_US`, `data/sv_SE`), one per +country's tree of places (`data/geo/SE`, `data/geo/US`), and the locale-neutral +`data/misc`. A package's Go name is its namespace in lower case without separators: +`svse`, `enus`, `geose`, `geous`, `misc`. Each embeds its files, so nothing is read from disk. The CLI carries every module, and a library loads those it passes to `WithDataFS` ([Library](#library)). A directory is a namespace: each JSON file is a category named after the file, each subdirectory a dot-path segment, so `mydata/sv_SE/person.json` is @@ -184,7 +185,7 @@ every category of its source, so a category file it leaves out never loads. The index maps each category's dot path to an entry: `parent`, the table it links to, which needs its own entry in the same folder; and `paths`, every path `List` advertises below the category, `""` for the category itself. Each shipped module's manifest, such as -[`data/svse/.fejkdata.json`](data/svse/.fejkdata.json), carries one, so in a copy you +[`data/sv_SE/.fejkdata.json`](data/sv_SE/.fejkdata.json), carries one, so in a copy you edit, delete its `index` and keep its `namespace`, or keep the index current. A table whose parent column differs from its entry's `parent` fails at first reach, and a table linking under another source's table needs a source without an index. `//go:embed` @@ -194,7 +195,7 @@ the root, with no `namespace`; name the manifest in the pattern too. A manifest's `namespace` is the dot path its source's root sits under: a folder holding `person.json` with `"namespace": "sv_SE"` provides `sv_SE.person`, its subfolders adding segments below that. It needs no index. Each shipped module carries one, so -`data/svse/person.json` is `sv_SE.person`. +`data/sv_SE/person.json` is `sv_SE.person`. Each locale carries `address`, `color`, `company`, `date`, `email`, `first-name`, `ip`, `last-name`, `person`, `phone`, `price`, `sentence`, `sex`, `time`, `url`, @@ -363,8 +364,8 @@ only the ones you read, pass each locale's `FS` with its country's places: ```go import ( "github.com/larvit/fejkdata" - "github.com/larvit/fejkdata/data/geose" - "github.com/larvit/fejkdata/data/svse" + geose "github.com/larvit/fejkdata/data/geo/SE" + svse "github.com/larvit/fejkdata/data/sv_SE" ) f, err := fejkdata.New(fejkdata.WithDataFS(svse.FS, geose.FS)) diff --git a/data-import/geo-se.py b/data-import/geo-se.py index 9e1f254..439b471 100644 --- a/data-import/geo-se.py +++ b/data-import/geo-se.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Rebuild data/geose/*.tsv from SCB (CC0), GeoNames (CC BY 4.0) and Trafikverket NVDB (CC0). +"""Rebuild data/geo/SE/*.tsv from SCB (CC0), GeoNames (CC BY 4.0) and Trafikverket NVDB (CC0). TRAFIKVERKET_API_KEY=… data-import/geo-se.py [--key-file FILE] [--cache DIR] [--streets-per-locality N] [--out DIR] """ diff --git a/data-import/geo-us.py b/data-import/geo-us.py index bc78af1..f3582a2 100644 --- a/data-import/geo-us.py +++ b/data-import/geo-us.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Rebuild data/geous/*.tsv from the Census Bureau's Gazetteer, population estimates, ZCTA relationships and TIGER/Line files (public domain). +"""Rebuild data/geo/US/*.tsv from the Census Bureau's Gazetteer, population estimates, ZCTA relationships and TIGER/Line files (public domain). data-import/geo-us.py [--cache DIR] [--min-population N] [--streets-per-locality N] [--out DIR] """ diff --git a/data-import/geo.py b/data-import/geo.py index 53b6100..8f2cab7 100644 --- a/data-import/geo.py +++ b/data-import/geo.py @@ -5,14 +5,14 @@ import math import sys from pathlib import Path -DATA = Path(__file__).resolve().parent.parent / "data" +DATA = Path(__file__).resolve().parent.parent / "data" / "geo" CACHE = Path(__file__).resolve().parent / "cache" def parser(doc, country, **own): """A parser for the options every country's import takes, plus the script's own: each keyword names one option, with "_" standing for "-".""" - options = {"cache": {"default": str(CACHE)}, "out": {"default": str(DATA / ("geo" + country.lower()))}, "streets_per_locality": {"type": int, "default": 10}, **own} + options = {"cache": {"default": str(CACHE)}, "out": {"default": str(DATA / country)}, "streets_per_locality": {"type": int, "default": 10}, **own} p = argparse.ArgumentParser(description=doc.splitlines()[0]) for name in sorted(options): p.add_argument("--" + name.replace("_", "-"), **options[name]) diff --git a/data-import/names-se.py b/data-import/names-se.py index e59c198..eef8b6e 100644 --- a/data-import/names-se.py +++ b/data-import/names-se.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Rebuild data/svse/first-name.tsv and last-name.tsv from SCB's whole-population name counts (CC0, "Källa: SCB"). +"""Rebuild data/sv_SE/first-name.tsv and last-name.tsv from SCB's whole-population name counts (CC0, "Källa: SCB"). data-import/names-se.py [--source URL_OR_FILE] [--first N] [--last N] [--cache DIR] [--out DIR] @@ -14,7 +14,7 @@ import tsv import xlsx SOURCE = "https://www.scb.se/contentassets/9fe7dbb460994c72b835163dbc491ef9/namn-med-minst-tva-barare-31-december-2022.xlsx" -OUT = Path(__file__).resolve().parent.parent / "data" / "svse" +OUT = Path(__file__).resolve().parent.parent / "data" / "sv_SE" CACHE = Path(__file__).resolve().parent / "cache" SHEETS = {"f": "Tilltalsnamn kvinnor", "m": "Tilltalsnamn män"} SURNAMES = "Efternamn" diff --git a/data-import/names-us.py b/data-import/names-us.py index 94b81a1..8e6d364 100644 --- a/data-import/names-us.py +++ b/data-import/names-us.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Rebuild data/enus/first-name.tsv and last-name.tsv from SSA baby names and the Census 2010 surnames (public domain). +"""Rebuild data/en_US/first-name.tsv and last-name.tsv from SSA baby names and the Census 2010 surnames (public domain). data-import/names-us.py [--names URL_OR_FILE] [--surnames URL_OR_FILE] [--from-year YEAR] [--first N] [--last N] [--cache DIR] [--out DIR] @@ -20,7 +20,7 @@ import tsv NAMES = "https://raw.githubusercontent.com/hackerb9/ssa-baby-names/master/alldata.txt" SURNAMES = "https://www2.census.gov/topics/genealogy/2010surnames/names.zip" -OUT = Path(__file__).resolve().parent.parent / "data" / "enus" +OUT = Path(__file__).resolve().parent.parent / "data" / "en_US" CACHE = Path(__file__).resolve().parent / "cache" MC = re.compile(r"^Mc([a-z])") PLACEHOLDERS = {"Baby", "Female", "Infant", "Male", "Notnamed", "Unknown", "Unnamed"} diff --git a/data/enus/.fejkdata.json b/data/en_US/.fejkdata.json similarity index 100% rename from data/enus/.fejkdata.json rename to data/en_US/.fejkdata.json diff --git a/data/enus/address.json b/data/en_US/address.json similarity index 100% rename from data/enus/address.json rename to data/en_US/address.json diff --git a/data/enus/color.json b/data/en_US/color.json similarity index 100% rename from data/enus/color.json rename to data/en_US/color.json diff --git a/data/enus/company.json b/data/en_US/company.json similarity index 100% rename from data/enus/company.json rename to data/en_US/company.json diff --git a/data/enus/date.json b/data/en_US/date.json similarity index 100% rename from data/enus/date.json rename to data/en_US/date.json diff --git a/data/enus/email.json b/data/en_US/email.json similarity index 100% rename from data/enus/email.json rename to data/en_US/email.json diff --git a/data/enus/first-name.json b/data/en_US/first-name.json similarity index 100% rename from data/enus/first-name.json rename to data/en_US/first-name.json diff --git a/data/enus/first-name.tsv b/data/en_US/first-name.tsv similarity index 100% rename from data/enus/first-name.tsv rename to data/en_US/first-name.tsv diff --git a/data/enus/fs.go b/data/en_US/fs.go similarity index 100% rename from data/enus/fs.go rename to data/en_US/fs.go diff --git a/data/enus/ip.json b/data/en_US/ip.json similarity index 100% rename from data/enus/ip.json rename to data/en_US/ip.json diff --git a/data/enus/itin.json b/data/en_US/itin.json similarity index 100% rename from data/enus/itin.json rename to data/en_US/itin.json diff --git a/data/enus/last-name.json b/data/en_US/last-name.json similarity index 100% rename from data/enus/last-name.json rename to data/en_US/last-name.json diff --git a/data/enus/last-name.tsv b/data/en_US/last-name.tsv similarity index 100% rename from data/enus/last-name.tsv rename to data/en_US/last-name.tsv diff --git a/data/enus/person.json b/data/en_US/person.json similarity index 100% rename from data/enus/person.json rename to data/en_US/person.json diff --git a/data/enus/phone-exchange.json b/data/en_US/phone-exchange.json similarity index 100% rename from data/enus/phone-exchange.json rename to data/en_US/phone-exchange.json diff --git a/data/enus/phone.json b/data/en_US/phone.json similarity index 100% rename from data/enus/phone.json rename to data/en_US/phone.json diff --git a/data/enus/price.json b/data/en_US/price.json similarity index 100% rename from data/enus/price.json rename to data/en_US/price.json diff --git a/data/enus/sentence.json b/data/en_US/sentence.json similarity index 100% rename from data/enus/sentence.json rename to data/en_US/sentence.json diff --git a/data/enus/sex.json b/data/en_US/sex.json similarity index 100% rename from data/enus/sex.json rename to data/en_US/sex.json diff --git a/data/enus/sex.tsv b/data/en_US/sex.tsv similarity index 100% rename from data/enus/sex.tsv rename to data/en_US/sex.tsv diff --git a/data/enus/ssn.json b/data/en_US/ssn.json similarity index 100% rename from data/enus/ssn.json rename to data/en_US/ssn.json diff --git a/data/enus/time.json b/data/en_US/time.json similarity index 100% rename from data/enus/time.json rename to data/en_US/time.json diff --git a/data/enus/title.json b/data/en_US/title.json similarity index 100% rename from data/enus/title.json rename to data/en_US/title.json diff --git a/data/enus/title.tsv b/data/en_US/title.tsv similarity index 100% rename from data/enus/title.tsv rename to data/en_US/title.tsv diff --git a/data/enus/url.json b/data/en_US/url.json similarity index 100% rename from data/enus/url.json rename to data/en_US/url.json diff --git a/data/enus/username.json b/data/en_US/username.json similarity index 100% rename from data/enus/username.json rename to data/en_US/username.json diff --git a/data/enus/version.json b/data/en_US/version.json similarity index 100% rename from data/enus/version.json rename to data/en_US/version.json diff --git a/data/enus/word.json b/data/en_US/word.json similarity index 100% rename from data/enus/word.json rename to data/en_US/word.json diff --git a/data/geose/.fejkdata.json b/data/geo/SE/.fejkdata.json similarity index 100% rename from data/geose/.fejkdata.json rename to data/geo/SE/.fejkdata.json diff --git a/data/geose/address.json b/data/geo/SE/address.json similarity index 100% rename from data/geose/address.json rename to data/geo/SE/address.json diff --git a/data/geose/fs.go b/data/geo/SE/fs.go similarity index 100% rename from data/geose/fs.go rename to data/geo/SE/fs.go diff --git a/data/geose/locality.json b/data/geo/SE/locality.json similarity index 100% rename from data/geose/locality.json rename to data/geo/SE/locality.json diff --git a/data/geose/locality.tsv b/data/geo/SE/locality.tsv similarity index 100% rename from data/geose/locality.tsv rename to data/geo/SE/locality.tsv diff --git a/data/geose/municipality.json b/data/geo/SE/municipality.json similarity index 100% rename from data/geose/municipality.json rename to data/geo/SE/municipality.json diff --git a/data/geose/municipality.tsv b/data/geo/SE/municipality.tsv similarity index 100% rename from data/geose/municipality.tsv rename to data/geo/SE/municipality.tsv diff --git a/data/geose/postal-code.json b/data/geo/SE/postal-code.json similarity index 100% rename from data/geose/postal-code.json rename to data/geo/SE/postal-code.json diff --git a/data/geose/postal-code.tsv b/data/geo/SE/postal-code.tsv similarity index 100% rename from data/geose/postal-code.tsv rename to data/geo/SE/postal-code.tsv diff --git a/data/geose/region.json b/data/geo/SE/region.json similarity index 100% rename from data/geose/region.json rename to data/geo/SE/region.json diff --git a/data/geose/region.tsv b/data/geo/SE/region.tsv similarity index 100% rename from data/geose/region.tsv rename to data/geo/SE/region.tsv diff --git a/data/geose/street.json b/data/geo/SE/street.json similarity index 100% rename from data/geose/street.json rename to data/geo/SE/street.json diff --git a/data/geose/street.tsv b/data/geo/SE/street.tsv similarity index 100% rename from data/geose/street.tsv rename to data/geo/SE/street.tsv diff --git a/data/geous/.fejkdata.json b/data/geo/US/.fejkdata.json similarity index 100% rename from data/geous/.fejkdata.json rename to data/geo/US/.fejkdata.json diff --git a/data/geous/address.json b/data/geo/US/address.json similarity index 100% rename from data/geous/address.json rename to data/geo/US/address.json diff --git a/data/geous/fs.go b/data/geo/US/fs.go similarity index 100% rename from data/geous/fs.go rename to data/geo/US/fs.go diff --git a/data/geous/locality.json b/data/geo/US/locality.json similarity index 100% rename from data/geous/locality.json rename to data/geo/US/locality.json diff --git a/data/geous/locality.tsv b/data/geo/US/locality.tsv similarity index 100% rename from data/geous/locality.tsv rename to data/geo/US/locality.tsv diff --git a/data/geous/municipality.json b/data/geo/US/municipality.json similarity index 100% rename from data/geous/municipality.json rename to data/geo/US/municipality.json diff --git a/data/geous/municipality.tsv b/data/geo/US/municipality.tsv similarity index 100% rename from data/geous/municipality.tsv rename to data/geo/US/municipality.tsv diff --git a/data/geous/postal-code.json b/data/geo/US/postal-code.json similarity index 100% rename from data/geous/postal-code.json rename to data/geo/US/postal-code.json diff --git a/data/geous/postal-code.tsv b/data/geo/US/postal-code.tsv similarity index 100% rename from data/geous/postal-code.tsv rename to data/geo/US/postal-code.tsv diff --git a/data/geous/region.json b/data/geo/US/region.json similarity index 100% rename from data/geous/region.json rename to data/geo/US/region.json diff --git a/data/geous/region.tsv b/data/geo/US/region.tsv similarity index 100% rename from data/geous/region.tsv rename to data/geo/US/region.tsv diff --git a/data/geous/street.json b/data/geo/US/street.json similarity index 100% rename from data/geous/street.json rename to data/geo/US/street.json diff --git a/data/geous/street.tsv b/data/geo/US/street.tsv similarity index 100% rename from data/geous/street.tsv rename to data/geo/US/street.tsv diff --git a/data/modules.go b/data/modules.go index 25d3796..905706d 100644 --- a/data/modules.go +++ b/data/modules.go @@ -4,11 +4,11 @@ package data import ( "io/fs" - "github.com/larvit/fejkdata/data/enus" - "github.com/larvit/fejkdata/data/geose" - "github.com/larvit/fejkdata/data/geous" + enus "github.com/larvit/fejkdata/data/en_US" + geose "github.com/larvit/fejkdata/data/geo/SE" + geous "github.com/larvit/fejkdata/data/geo/US" "github.com/larvit/fejkdata/data/misc" - "github.com/larvit/fejkdata/data/svse" + svse "github.com/larvit/fejkdata/data/sv_SE" ) //go:generate env REGENERATE=1 go test -run ^TestShippedManifestsAreCurrent$ .. diff --git a/data/svse/.fejkdata.json b/data/sv_SE/.fejkdata.json similarity index 100% rename from data/svse/.fejkdata.json rename to data/sv_SE/.fejkdata.json diff --git a/data/svse/address.json b/data/sv_SE/address.json similarity index 100% rename from data/svse/address.json rename to data/sv_SE/address.json diff --git a/data/svse/birth-number.json b/data/sv_SE/birth-number.json similarity index 100% rename from data/svse/birth-number.json rename to data/sv_SE/birth-number.json diff --git a/data/svse/birth-number.tsv b/data/sv_SE/birth-number.tsv similarity index 100% rename from data/svse/birth-number.tsv rename to data/sv_SE/birth-number.tsv diff --git a/data/svse/color.json b/data/sv_SE/color.json similarity index 100% rename from data/svse/color.json rename to data/sv_SE/color.json diff --git a/data/svse/company.json b/data/sv_SE/company.json similarity index 100% rename from data/svse/company.json rename to data/sv_SE/company.json diff --git a/data/svse/date.json b/data/sv_SE/date.json similarity index 100% rename from data/svse/date.json rename to data/sv_SE/date.json diff --git a/data/svse/email.json b/data/sv_SE/email.json similarity index 100% rename from data/svse/email.json rename to data/sv_SE/email.json diff --git a/data/svse/first-name.json b/data/sv_SE/first-name.json similarity index 100% rename from data/svse/first-name.json rename to data/sv_SE/first-name.json diff --git a/data/svse/first-name.tsv b/data/sv_SE/first-name.tsv similarity index 100% rename from data/svse/first-name.tsv rename to data/sv_SE/first-name.tsv diff --git a/data/svse/fs.go b/data/sv_SE/fs.go similarity index 100% rename from data/svse/fs.go rename to data/sv_SE/fs.go diff --git a/data/svse/ip.json b/data/sv_SE/ip.json similarity index 100% rename from data/svse/ip.json rename to data/sv_SE/ip.json diff --git a/data/svse/last-name.json b/data/sv_SE/last-name.json similarity index 100% rename from data/svse/last-name.json rename to data/sv_SE/last-name.json diff --git a/data/svse/last-name.tsv b/data/sv_SE/last-name.tsv similarity index 100% rename from data/svse/last-name.tsv rename to data/sv_SE/last-name.tsv diff --git a/data/svse/person.json b/data/sv_SE/person.json similarity index 100% rename from data/svse/person.json rename to data/sv_SE/person.json diff --git a/data/svse/personnummer.json b/data/sv_SE/personnummer.json similarity index 100% rename from data/svse/personnummer.json rename to data/sv_SE/personnummer.json diff --git a/data/svse/phone.json b/data/sv_SE/phone.json similarity index 100% rename from data/svse/phone.json rename to data/sv_SE/phone.json diff --git a/data/svse/price.json b/data/sv_SE/price.json similarity index 100% rename from data/svse/price.json rename to data/sv_SE/price.json diff --git a/data/svse/samordningsnummer.json b/data/sv_SE/samordningsnummer.json similarity index 100% rename from data/svse/samordningsnummer.json rename to data/sv_SE/samordningsnummer.json diff --git a/data/svse/sentence.json b/data/sv_SE/sentence.json similarity index 100% rename from data/svse/sentence.json rename to data/sv_SE/sentence.json diff --git a/data/svse/sex.json b/data/sv_SE/sex.json similarity index 100% rename from data/svse/sex.json rename to data/sv_SE/sex.json diff --git a/data/svse/sex.tsv b/data/sv_SE/sex.tsv similarity index 100% rename from data/svse/sex.tsv rename to data/sv_SE/sex.tsv diff --git a/data/svse/time.json b/data/sv_SE/time.json similarity index 100% rename from data/svse/time.json rename to data/sv_SE/time.json diff --git a/data/svse/title.json b/data/sv_SE/title.json similarity index 100% rename from data/svse/title.json rename to data/sv_SE/title.json diff --git a/data/svse/title.tsv b/data/sv_SE/title.tsv similarity index 100% rename from data/svse/title.tsv rename to data/sv_SE/title.tsv diff --git a/data/svse/url.json b/data/sv_SE/url.json similarity index 100% rename from data/svse/url.json rename to data/sv_SE/url.json diff --git a/data/svse/username.json b/data/sv_SE/username.json similarity index 100% rename from data/svse/username.json rename to data/sv_SE/username.json diff --git a/data/svse/version.json b/data/sv_SE/version.json similarity index 100% rename from data/svse/version.json rename to data/sv_SE/version.json diff --git a/data/svse/word.json b/data/sv_SE/word.json similarity index 100% rename from data/svse/word.json rename to data/sv_SE/word.json diff --git a/docs/comprehension-history.md b/docs/comprehension-history.md index 65c547d..81bf7b4 100644 --- a/docs/comprehension-history.md +++ b/docs/comprehension-history.md @@ -417,3 +417,35 @@ Inherited architect, decided by: - Navigation, Self-sufficiency: `data/svse/.fejkdata.json:26` `namespace`: a namespace no longer mirrors its folder, so the path alone no longer finds the file - Self-sufficiency: `internal/datafiles/manifest.go:23` `Manifest.Reads`: its comment and withMissingModules' only make sense after the README - Locality: `internal/datafiles/datafiles.go:77` `Source.Walk`: the mount is translated in opposite directions by Walk and Load + +## 2026-10-11T11:30:01Z, PR #203 at 2a4694b, against bf1becb + +Ruling: worse + +Fell: Navigation. Under the floor of 7.0: Navigation 6.88, so the same ruling counts as worse. + +| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall | +|---|---|---|---|---|---| +| Mid A | worse | better | same | same | same | +| Inherited architect | worse | same | same | same | same | + +| Seat | Navigation | Locality | Shape | Self-sufficiency | Overall | +|---|---|---|---|---|---| +| Junior A | 7 | 5.5 | 6 | 6 | 6 | +| Mid A | 7 | 5.5 | 6.5 | 6 | 6 | +| Maintainability senior | 7 | 6 | 6.5 | 6.5 | 6.5 | +| Inherited architect | 6.5 | 5.5 | 5.5 | 6.5 | 6 | +| Mean | 6.88 | 5.63 | 6.13 | 6.25 | 6.13 | + +Mid A, decided by: + +- Locality: `fejkdata.go:66` `WithDataFS`: every module is named at the call site, where the base silently started each generator from a package-level embed +- Navigation: `data/geose/fs.go:1` `geose`: a dotfile manifest decides the namespace and the folder follows a lowered, no-separator rule, one translation step from a failing path to its file +- Navigation: `internal/datafiles/datafiles.go:57` `Source.labelled`: a shipped file's error prints sv_SE (address.json), where the base printed the openable data/sv_SE/address.json +- Locality: `data.go:27` `addSource`: where a category lands depends on a field in a hidden file, a partial offset + +Inherited architect, decided by: + +- Navigation: `data/svse/fs.go:1` `svse`: the step from a dot path to a folder goes through the lowered-namespace rule, stated only in the README and each package doc +- Navigation: `internal/datafiles/datafiles.go:57` `labelled`: errors name sv_SE (address.json), not a path that opens as written +- Locality: `fejkdata.go:99` `New`: New loads exactly its options, cancelled by `data/svse/fs.go:1`'s dependency on geose that nothing in Go expresses diff --git a/docs/decisions.md b/docs/decisions.md index 1b5e95a..e841534 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -138,7 +138,7 @@ A directory a machine happens to have would make `--seed 42` machine-dependent; ## The shipped data is Go packages a library imports by choice, and the CLI carries every one, from 0.1.0 -2026-10-04, Lilleman auf Larv; revised 2026-10-09 to put the packages in the core's Go module. Serves goals 2.3, 6.2, 7.3, 9 and 10.1. Carried out by `todo.md` items 181, 184, 185 and 186. The CLI binary may grow to hundreds of MB. +2026-10-04, Lilleman auf Larv; revised 2026-10-09 to put the packages in the core's Go module. Serves goals 2.3, 6.2, 7.3, 9 and 10.1. Carried out by `todo.md` items 181, 184, 185, 186 and 196. The CLI binary may grow to hundreds of MB. - One Go package per locale, one per country's `geo` tree, and one for `misc`, all in the core's Go module. A package registers nothing when imported. - A bare `New()` loads no data and fails, naming the option to add. `WithoutShippedData` goes. @@ -152,15 +152,19 @@ A directory a machine happens to have would make `--seed 42` machine-dependent; Valid while the shipped data stays under 100 MiB, which a gate test holds (`todo.md` item 192): `go get` fetches the whole Go module, and the `go` command refuses a Go module zip over 500 MiB (`MaxZipFile` in `golang.org/x/mod/zip`). Past it, `todo.md` item 193 moves the largest packages into nested Go modules that keep their import paths, each requiring the core release that drops the package, so no build sees it twice. -## A shipped package is named by its namespace in lower case without separators, and its manifest mounts it there with `namespace` +## A shipped package's folder spells its namespace, its Go name is that namespace in lower case without separators, and its manifest mounts it with `namespace` -2026-10-11, Lilleman auf Larv, from a bench of a Go test author, a data author and a -custom-CLI builder. Serves goals 1 and 3.3. `sv_SE` ships as `data/svse`, `en_US` as -`data/enus`, `geo.SE` as `data/geose`, `geo.US` as `data/geous`, and `misc` as `data/misc`: -Go linters flag a capital or an underscore in a package name, and `SE.FS` read as a type. -Each package holds its files at its root, and its manifest's `namespace` puts them under -the namespace, so no path repeats it. Valid until a locale's lowered name clashes with -another's. +2026-10-11, Lilleman auf Larv, from two benches of a Go test author, a data author and a +custom-CLI builder. Serves goals 1 and 3.3. `sv_SE` ships in `data/sv_SE` as package +`svse`, `en_US` in `data/en_US` as `enus`, `geo.SE` in `data/geo/SE` as `geose`, `geo.US` in +`data/geo/US` as `geous`, and `misc` in `data/misc`: Go linters flag a capital or an +underscore in a package name, and `SE.FS` read as a type, while a folder spelling its +namespace takes a reader from a dot path in an error or a template to its file. The second +bench chose that over flat folders such as `data/svse`, 2 to 1, at the cost of a package +name that differs from its folder. A locale is one folder, never a language folder holding +regions: `en_US` and `en_GB` are different languages that share a name. Each package +holds its files at its root, and its manifest's `namespace` puts them under the namespace, +so no path repeats it. Valid until a locale's lowered name clashes with another's. ## A source whose manifest carries an index loads each category on first reach; any other loads in `New`, with what it reads diff --git a/internal/datafiles/datafiles.go b/internal/datafiles/datafiles.go index d436722..0d83bc3 100644 --- a/internal/datafiles/datafiles.go +++ b/internal/datafiles/datafiles.go @@ -58,6 +58,8 @@ func (s Source) labelled(p string) string { switch { case s.label != "": return path.Join(s.label, p) + case s.mount != nil && p == ".": + return strings.Join(s.mount, ".") case s.mount != nil: return fmt.Sprintf("%s (%s)", strings.Join(s.mount, "."), p) } diff --git a/todo.md b/todo.md index 7ae2e5e..5682623 100644 --- a/todo.md +++ b/todo.md @@ -76,7 +76,7 @@ | 129 | 0.1.0 | decision | **Take a template wherever the library renders, so `fake:"{/sv_SE.person.first}"` and `Fake("{/sv_SE.person}")` render, and text with no `{…}` prints as written, as the CLI already does.** | 5 | 8 | 8 | 10 | 5.9, 7 | 25.0 | | 163 | 0.1.0 | | **Lift the CLI's `--repeat` cap, since the CLI streams each render, and give the builtins' count and decimal caps a technical reason in the README.** | 2 | 2 | 7 | 7 | 2, 5.7 | 24.8 | | 57 | 0.1.0 | | **Rewrite `CHANGELOG.md`'s `[Unreleased]` as what v0.1.0 holds.** | 1 | 2 | 6 | 6 | 1.1 | 22.5 | -| 196 | 0.1.0 | decision | **Name, in the error for a reference nothing loaded provides, the module the reader's manifest reads by default that would provide it, or say none does.** | 3 | 4 | 6 | 8 | 6.2 | 20.0 | +| 196 | 0.1.0 | decision | **Name, in the error for a reference nothing loaded provides, the module the reader's manifest reads by default that would provide it, or say none does.** | 3 | 4 | 6 | 8 | 6.2, 9.2 | 20.0 | | 164 | 0.1.0 | | **Let a table's format or a cell bind a name, which lives in that format or cell and keeps one pick through the draw.** | 2 | 2 | 5 | 7 | 4.1, 5.3 | 19.4 | | 157 | 0.1.0 | | **Show in the README's CLI section how PowerShell and cmd.exe pipe a template, one line per shell family.** | 1 | 1 | 5 | 6 | 7.2 | 17.1 | | 181 | 0.1.0 | decision | **Fail a load where two sources define one category, unless the library's option or the CLI's flag says the later replaces the earlier, and then make every read reach the replacement.** | 5 | 4 | 6 | 9 | 9.3 | 16.8 |