Skip to content

How wend works

pathlib composes a path from its parts, and the result is a concrete value:

>>> from pathlib import Path
>>> split, i = "train", 7
>>> Path("data") / split / f"chunk_{i:04d}.parquet"
PosixPath('data/train/chunk_0007.parquet')

split and i have been substituted and the 04d format has been applied, and the value records neither the parameters nor the format. Code that needs the layout again, to read split and i back out of a filename, to list the chunks that exist or to check that one is present, has to state it again, for example as a regular expression or a glob pattern.

A wend expression is the description of the path:

from wend import Param, T

root, split, idx = Param("root"), Param("split"), Param("idx", type=int)
shard = root / split / T(t"chunk_{idx:04d}.parquet")
>>> shard
PathExpr('{root}/{split}/chunk_{idx:04d}.parquet')
>>> shard.render(root="data", split="train", idx=7)
'data/train/chunk_0007.parquet'
>>> shard.match("data/train/chunk_0007.parquet")
Match('data/train/chunk_0007.parquet', {'root': 'data', 'split': 'train', 'idx': 7})

It keeps its parameters (with their kinds, types and choices), its literal parts, its formatting and the operations applied to it. It becomes a concrete path only when it is rendered. For every set of values it accepts, the rendered path is the path pathlib computes from the same values. Everything else wend does is done with the description.

With one expression you can

with one expression you can using concepts
render it with values render, resolve, bind, defaults, bindings from objects Rendering and matching, Parameters
read values back out of a path match, match_all Rendering and matching
transform it before any value is known parent, with_suffix, relative_to Operations
find the existing paths it describes glob, unions, queries Effects
keep its relations to other paths base, rebase, sibling, cousin, under Relations
say what must be true when it is used conditions, Step Effects
map one tree onto another Lens
describe a whole project Tree, validate, scaffold
recover it from an existing tree infer, from_inferred
render it fast and in bulk compile, compile_many, resolve_frame
record where a file came from explain, tags, Ledger, content_key

The rows without a concept page are documented in the API reference.

The concept pages

Together with the Quickstart, this page is enough to use the library. The other pages explain one part each, and can be read in any order.

  • Expressions: what an expression records, and how P, T and / build one from text, parameters and t-strings.
  • Parameters: the four kinds of parameter, type=, choices= and default=, and why a value bound to a segment parameter cannot leave its directory.
  • Operations: which path operations are computed from structure, which wait for values, and which are rejected.
  • Rendering and matching: the two directions, how matches are verified, and why an ambiguous path is an error.
  • Relations: how an expression remembers the paths it was built from, and how rebasing one path moves the paths derived from it.
  • Effects: which operations touch the filesystem, and how conditions declare what a path must be.

The precise rules are in SEMANTICS.md, the contract that the tests check wend against.