Answer prose round 1: the seed advice says to log a new seed in the error, the doc and the README alike, the changelog says each run takes a new seed, New's failures read in one pass, and the concurrency lines say who draws

This commit is contained in:
2026-10-12 18:24:47 +02:00
committed by Lillem4n
parent e0f5493daa
commit bf61527363
4 changed files with 19 additions and 18 deletions
+4 -4
View File
@@ -18,8 +18,8 @@ and any release may change what a seed draws, so pin one exact version
- The CLI, `fejkdata`, renders exactly the template on its stdin and adds nothing:
`echo '{/sv_SE.person} hihi' | fejkdata` prints e.g. `Sara Eriksson hihi`. `--seed`
repeats a run's output while the version and data stay the same, and without it the
CLI seeds from the system; `-n` renders the template that many times, and `--list`
repeats a run's output while the version and data stay the same, and without it each
run takes a new seed; `-n` renders the template that many times, and `--list`
prints the paths the data offers.
`--data-path` layers a directory of your own data over the shipped set, and
`--no-shipped-data` loads that directory alone. `--format json|ndjson|csv|sql` writes
@@ -27,8 +27,8 @@ and any release may change what a seed draws, so pin one exact version
error such as data that fails to load, and `2` on misuse.
- The library, `github.com/larvit/fejkdata`, for Go 1.22 or later on a 64-bit target.
`New` loads the modules `WithDataFS` names and the folders `WithDataPath` names, drawing
from the seed `WithSeed` gives. It fails naming `WithSeed` where no seed is given, and
`WithDataFS` where neither option names the data. The same seed repeats the draws
from the seed `WithSeed` gives. Without a seed, `New` fails and names `WithSeed`;
without data, it fails and names `WithDataFS`. The same seed repeats the draws
while the version and data stay the same. `Fake` renders a path, and `FakeTemplate`
and `NewTemplate` render a template. `FakeRecord`, `FakeRecordTemplate` and
`NewRecordTemplate` render a record, whose `JSON`, `CSVHeader`, `CSVLine` and
+9 -8
View File
@@ -360,7 +360,7 @@ ok, err := fejkdata.IsTemplate(arg) // an inline template by its shape, el
| Option | |
|--------|--|
| `WithSeed(n)` | required; same seed, version and data: identical sequence. `WithSeed(s)` with `s := rand.Uint64()`, from `math/rand/v2`, takes a new seed each run; log `s` to replay a run |
| `WithSeed(n)` | required; the same seed, version and data give the same sequence. For a new seed each run, set `n := rand.Uint64()` (`math/rand/v2`), and log `n` to replay the run |
| `WithDataPath(dir)` | layer a directory; repeat to layer several, the last wins a clash |
| `WithDataFS(modules...)` | layer modules in order, each an `fs.FS`: a shipped package's `Modules()...`, or your own `embed.FS`; `WithDataFS()` loads none |
@@ -372,7 +372,7 @@ links all of them. Two locales, with `enus` from `github.com/larvit/fejkdata/dat
are `WithDataFS(append(svse.Modules(), enus.Modules()...)...)`. To stand in your
own places, pass the locale's `FS` alone beside a tree providing `geo.SE.address`, a record
with a `format` and the columns `sv_SE.address` reads, `street`, `street-number`,
`postal-code` and `locality`: `WithDataFS(svse.FS, myPlaces)`. `New` fails where no `WithSeed` gives the seed, or no
`postal-code` and `locality`: `WithDataFS(svse.FS, myPlaces)`. `New` fails where no
`WithDataFS` or `WithDataPath` names the data to load.
`New` refuses data that breaks the grammar, could mean two things or cannot render a valid
@@ -431,8 +431,8 @@ error on every later call; a `datatype` in a tag other than the one its Go type
refused, naming that type.
A `*Generator` is safe for concurrent use; a sequence is reproducible only
when drawn from one goroutine. Changing how a value is composed shifts the
stream for that value and everything drawn after it.
when drawn from one goroutine. Editing a template shifts what it draws, and
everything drawn after it.
### Your own CLI
@@ -459,10 +459,11 @@ func main() { os.Exit(cli.Main(append(data.Modules(), mydata)...)) }
The embed's folders are the paths: `//go:embed acme` serves `acme/customer.json` as
`{/acme.customer}`. Add `*.tsv` to the embed where your data holds a table. The CLI loads
its data only when it runs. To catch broken data at `go test`, call
`fejkdata.New(fejkdata.WithDataFS(...), fejkdata.WithSeed(1))` over the same modules, and render each path once:
a module with an index checks a category only when a call first reaches it. The CLI takes `fejkdata`'s flags
and exit codes, and names itself by the file it runs from in its help and errors. `--no-shipped-data` leaves out the modules passed to `Main`, and
`--version` prints your module's version beside the fejkdata version it is built with.
`fejkdata.New(fejkdata.WithDataFS(...), fejkdata.WithSeed(1))` over the same modules, and
render each path once: a module with an index checks a category only when a call first
reaches it. The CLI takes `fejkdata`'s flags and exit codes, and names itself by the file
it runs from in its help and errors. `--no-shipped-data` leaves out the modules passed to
`Main`, and `--version` prints your module's version beside the fejkdata version it is built with.
## Data format
+4 -4
View File
@@ -36,7 +36,7 @@ type config struct {
seeded bool
sources []datafiles.Source
nilModules error
// dataGiven is whether an option named the data to load, though it may name none.
// dataGiven is whether a data option was passed, even WithDataFS(), which loads none.
dataGiven bool
}
@@ -44,8 +44,8 @@ type config struct {
type Option func(*config)
// WithSeed seeds the generator, as [New] requires: two generators with the same seed,
// version and data emit identical sequences. WithSeed(rand.Uint64()), with math/rand/v2,
// takes a new seed each run.
// version and data emit identical sequences. For a new seed each run, set
// seed := rand.Uint64() (math/rand/v2), and log it to replay the run.
func WithSeed(seed uint64) Option {
return func(c *config) { c.seed, c.seeded = seed, true }
}
@@ -75,7 +75,7 @@ func WithDataFS(modules ...fs.FS) Option {
}
}
var errNoSeed = errors.New(`fejkdata: no seed: add fejkdata.WithSeed(n) to repeat a run's output, or WithSeed(rand.Uint64()) (import "math/rand/v2") for a new seed each run`)
var errNoSeed = errors.New(`fejkdata: no seed: add fejkdata.WithSeed(n), where the same n repeats a run's output; for a new seed each run, set n := rand.Uint64() (import "math/rand/v2") and log n to replay the run`)
var errNoData = errors.New(`fejkdata: no data: add fejkdata.WithDataFS(data.Modules()...) (import "github.com/larvit/fejkdata/data") for all shipped data, WithDataFS/WithDataPath for your own, or WithDataFS() for none`)
+2 -2
View File
@@ -11,8 +11,8 @@ import (
// Template is an inline template compiled, referenced and validated against a
// generator's loaded data once, ready to render many times with [Template.Fake].
// It is safe for concurrent use: Fake serializes on its generator's lock, so a
// sequence is reproducible only when a generator — and its templates — are
// drawn from one goroutine.
// sequence is reproducible only when one goroutine makes every draw from a generator
// and its templates.
type Template struct {
g *Generator
n node