Record the audience, the id cardinality, the date ranges and why --list stays a plain path list
Tests / vet + fmt + tests (pull_request) Successful in 1m21s
Tests / Gitea release from CHANGELOG.md (pull_request) Has been skipped

This commit is contained in:
2026-09-18 19:55:50 +02:00
parent 7eb891dd80
commit 6b0a2a60a8
3 changed files with 59 additions and 16 deletions
+17 -8
View File
@@ -34,15 +34,24 @@ replacement, and each removed path, column or flag.
`en_US.address` read those records, so `en_US.address.street` no longer carries
`name` and `suffix`, and a locale folder loads only beside `geo`.
- `{date(from,to,'layout')}` and `{time('layout')}`: a second between two days, or
within one, in a quoted Go layout. `sv_SE.date`, `en_US.date`, `sv_SE.time` and
`en_US.time` render through them, so `date.year`, `date.month`, `date.day` and
`time.hour` are no longer paths, and `misc.datetime` is an RFC 3339 instant.
within one, in a single-quoted Go layout, drawn in UTC; `from` may equal `to`.
`sv_SE.date`, `en_US.date`, `sv_SE.time` and `en_US.time` render through them, so
`date.year`, `date.month`, `date.day`, `time.hour`, `time.minute`, `time.minute.t`,
`time.sec` and `time.ampm` are no longer paths — a part of a date is now its own
`{date(…,'2006')}`. `misc.datetime` is an RFC 3339 instant.
- `sex`, `first-name` and `last-name` tables in `sv_SE` and `en_US`, weighted by
bearers from SCB, the SSA and the Census Bureau; `first-name` links to `sex`, and a
name both sexes carry is a row under each. `person` reads them, so its columns are
`first`, `last`, `prefix` and `sex`, and `person.femalefirst` and
`person.malefirst` are no longer paths.
`first`, `last`, `prefix` and `sex`; `person.femalefirst` and `person.malefirst` are
no longer paths — draw `sex[f].first-name` and `sex[m].first-name` instead.
`en_US.title` links to `sex` as well, so `en_US.person.prefix` draws `Mr` or `Ms`
without contradicting the record's `sex`.
- `sv_SE.personnummer` and `sv_SE.samordningsnummer`, Skatteverket's test series
from a `sv_SE.birth-number` table under `sex`, in place of `sv_SE.ssn`; `en_US.ssn`
in the ranges the SSA assigns, and `en_US.itin`. `en_US.person.prefix` no longer
draws `Mr`, `Mrs`, `Ms` or `Miss`, which could contradict the record's `sex`.
from a `sv_SE.birth-number` table under `sex`, in place of `sv_SE.ssn`, whose
`ssn.mmdd`, `ssn.mmdd.m` and `ssn.mmdd.d` go with it. `en_US.ssn` now draws the
ranges the SSA assigns and carries the columns `area`, `group` and `serial`, so
`--format csv en_US.ssn` writes a header where it used to fail; `en_US.itin` is new.
- An error names a spelling that runs: a layout is named single-quoted and free of
its own quotes, a row of a table with no key is named as the path that selects it,
`sv_SE.sex[f].first-name[Kim]`, and a category with no columns names the record
that gives it one.
+35 -5
View File
@@ -22,6 +22,7 @@ fejkdata 'geo.SE.locality[Lund].street' # Fjelievägen — a linked tabl
fejkdata --data-path ./mydata sv_SE.word # layer a directory over the shipped data
fejkdata --no-shipped-data -d ./mydata --list # only your data
fejkdata 'name: {/sv_SE.person.last}' # name: <a surname> — an inline template
fejkdata "{date(1990-01-01,2010-12-31,'2006-01-02')}" # 2003-11-27 — the argument in "…", the layout in '…'
fejkdata '{"format":"name: {x}","x":["bosse","lina"]}' # name: bosse or name: lina
```
@@ -237,7 +238,16 @@ draws a woman's name, and a name both sexes carry is a row under each, so
`person` reads one draw of the three, so its `first` and `sex` columns agree, and so
does a `personnummer` in the same render: its birth number, `sv_SE.birth-number`
under `sex`, is Skatteverket's test series, 238 for a woman and 239 for a man, which no
real person is ever given.
real person is ever given. `en_US.title` links to `sex` too, so a person's prefix
never contradicts it.
A person of a chosen sex is assembled from the tables — `sex[f].first-name` beside
`last-name` — while a shipped `personnummer` agrees with the sex its own render
*drew*, not with one a path selects. That test series is also small: a personnummer
is one of about 70,000 values, a day in 1930–2025 against the two birth numbers, so a
fixture past a few hundred rows repeats one and a `UNIQUE` column needs a category of
your own. `sv_SE.date` and `en_US.date` are uniform over 1970-01-01 to 2029-12-31,
`misc.datetime` over 2000-01-01 to 2029-12-31.
A `geo` folder holds one tree per country under its alpha-2 code: five
[linked tables](#linked-tables) named alike, and an `address` record over one
@@ -536,12 +546,14 @@ them a birthdate:
Renders e.g. `811218-2389`. A layout is Go's: the reference time `Mon Jan 2
15:04:05 MST 2006` spelled as the output should look, quoted, since a layout may
carry the comma that separates arguments, with English names. Every second
between the two days is reachable, so a layout with a clock draws the time too.
between the two days is reachable, so a layout with a clock draws the time too, and
`from` may equal `to`, which is that one day. The instant is UTC, so a zone in the
layout prints `UTC` or `Z`.
The quotes delimit a layout outside a selector only, so `[O'Fallon]` in an
argument stays a name. Rejected at `New`: a bound that is no calendar date, or not
before the other; an unquoted layout, naming the quoted one; a layout naming no field, which is text;
for `date` a layout naming no date field, naming `time`; and for `time` a layout
naming a date field, naming `date`. `{seq()}` spans `Fake`
before the other; an unquoted layout, naming the single-quoted one; a layout naming no field, which is
text, as is one day in a layout with no clock; for `date` a layout naming no date
field, naming `time`; and for `time` a layout naming a date field, naming `date`. `{seq()}` spans `Fake`
calls and `repeat`, resets with a new generator, and is the natural primary key for
the SQL example above.
@@ -721,6 +733,15 @@ datatype and nullability, and each table's key, name, weight and parent columns;
changes it or `data/` adds its `CHANGELOG.md` entry, which CI checks. A removed,
renamed or retyped line is a major.
## Audience
App developers writing tests and fixtures, in Go and at a shell:
- a **bulk fixture author**, thousands of rows into CSV or SQL
- a **Go test author**, filling a struct with `FakeStruct`
- a **hand fixture author**, one value at a shell
- a **validator-facing author**, who needs a value a real checker accepts
## Goals
1. **Valid by construction** — every value passes the check its real consumer
@@ -1063,12 +1084,21 @@ renamed or retyped line is a major.
bigger neighbour ship no address; counting the land outside every place too would
drop a quarter of the places, whose codes straddle unincorporated land, for a
postal city the USPS mostly names the same way.
- **`--list` stays a plain list of paths.** It is what a script reads, so every line
has to be a path that `Fake` takes; a marker for the tables a `[selector]` follows,
or a legend above them, would make the output something to parse before use.
`--help` names the selector spelling instead, and the Table section teaches it.
- **A layout is always quoted.** A layout may carry the comma that separates
arguments, `'January 2, 2006'`, and one spelling for every layout beats a rule
about which ones need the quotes, so the bare spelling is refused naming the
quoted one. The layout is Go's reference time because the library renders with
it and a Go caller already knows it; its names are English, and a locale's own
month and weekday names are data.
- **A title is a table under `sex`.** A prefix drawn apart would put `Mr` on a record
whose `sex` column says `female`, which is the disagreement the record exists to
prevent; the tables this set already has are what a title needs, so `en_US.title`
links to `sex` as `first-name` does. Swedish has no everyday sexed honorific, so
`sv_SE` keeps an unsexed `dr` and `prof`.
- **No builtin reads the clock, so a date is bounded by days, never by an age.**
An `age(min,max)` would make a seeded fixture change with the day it runs on,
which is what a seed exists to prevent; a birthdate for someone 20 to 60 is
+7 -3
View File
@@ -164,9 +164,13 @@ address, phone, national id, company and date names each.
1. Table node, key and name selection, parent links, consistent draws, the
choice-of-rows fence, `DATA-LICENSES.md`, `data-import/` — done.
2. `geo/SE` and `geo/US`, and `address` in both locales on top of them — done.
3. Weighted person names and valid ids in both locales; `date()` — done. Middle
names wait for a draw group that shares its family's pins, so a second name
is drawn under the same sex.
3. Weighted person names and valid ids in both locales; `date()` — done. Left for
later: middle names, and drawing a shipped `personnummer` inside a *selected*
sex, both of which want a draw group that shares its family's pins — until then
the conflict error can name a rewrite that returns a different value when the
read it conflicts with sits inside another category. Give the national ids one
record shape in step 6, and report a struct column's draw conflict with the path
spelling a tag takes rather than the reference spelling.
4. `misc` conversions and the new `misc` tables.
5. The remaining locale categories: company, phone, finance, vehicle, words.
6. Records with building-block columns across the shipped set; shape re-pin.