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

This commit is contained in:
2026-10-11 14:11:46 +02:00
committed by Lillem4n
parent 26f3c95031
commit 203486a9d3
97 changed files with 81 additions and 42 deletions
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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.
+9 -9
View File
@@ -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` |
+9 -8
View File
@@ -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))
+1 -1
View File
@@ -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]
"""
+1 -1
View File
@@ -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]
"""
+2 -2
View File
@@ -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])
+2 -2
View File
@@ -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"
+2 -2
View File
@@ -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"}
+4 -4
View File
@@ -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$ ..
+32
View File
@@ -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
+13 -9
View File
@@ -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
+2
View File
@@ -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)
}
+1 -1
View File
@@ -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 |