Skip to content

docs: every spec in the docs and examples opens with its given block - #813

Merged
FabianHofmann merged 9 commits into
mainfrom
claude/amazing-ramanujan-mfocq7
Oct 6, 2026
Merged

FabianHofmann merged 9 commits into
mainfrom
claude/amazing-ramanujan-mfocq7

Conversation

@FBumann

@FBumann FBumann commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Prompt: Please fix all specs in the docs etc to start with the given block.

Note

The following content was generated by AI.

Every spec in examples/ and in the hand-written docs that has a given: block now puts it first, after description:. The PyPSA splitter writes its fragments in this order.

What this changes

Method, gate output, alternatives
  • Every hand-written examples/**/*.yaml and the yaml snippets in docs/several-files.md, docs/howto/compose.md and docs/reference/language/declarations.md: the top-level given: block moved to directly after version: and description:, with no other change. Each diff is the block, cut and pasted. The sorted lines of every changed yaml and md file equal those of origin/main.
  • tools/pypsa_split.py: _fragment writes given: before the first section, not after variables:. examples/pypsa/*.yaml is regenerated with python -m tools.pypsa_split split examples/pypsa.
  • Generated pages (docs/examples/**, README, docs/index.md, notation, operators, expansion) and the typesetter golden files are regenerated.
  • CHANGELOG.md: this PR's line.

Re-run after a merge of main. For a conflicted example or page, take main's version, save the script below as move_given.py, then:

pixi run python move_given.py $(git ls-files 'examples/*.yaml' | grep -v '^examples/pypsa/') docs/reference/language/declarations.md docs/howto/compose.md docs/several-files.md
pixi run python -m tools.pypsa_split split examples/pypsa
for t in $(grep -l 'page_main(' tools/*.py | xargs -n1 basename | sed 's/\.py$//'); do pixi run python -m tools.$t; done
pixi run python -m tools.gallery
pixi run python -m tests.typesetting.golden

The script is idempotent. It moves text, so comments and formatting stay.

move_given.py
"""Move the top-level `given:` block to directly after `version:` and `description:`."""
import re
import sys
from pathlib import Path

LEAD = {'version', 'description'}


def blocks(lines):
    """Split into (key, start, end) for top-level keys; end excludes trailing blanks and column-0 comments."""
    starts = [i for i, l in enumerate(lines) if re.match(r'[A-Za-z_]\w*:', l)]
    out = []
    for n, s in enumerate(starts):
        limit = starts[n + 1] if n + 1 < len(starts) else len(lines)
        e = s + 1
        for j in range(s + 1, limit):
            if lines[j].startswith((' ', '\t')):
                e = j + 1
        out.append((lines[s].split(':')[0], s, e))
    return out


def move(lines):
    bs = blocks(lines)
    keys = [k for k, *_ in bs]
    if 'given' not in keys:
        return lines
    g = bs[keys.index('given')]
    chunk = lines[g[1] : g[2]]
    rest = lines[: g[1]] + lines[g[2] :]
    if g[2] < len(lines) and not lines[g[2]].strip() and g[1] > 0 and not lines[g[1] - 1].strip():
        rest = lines[: g[1]] + lines[g[2] + 1 :]
    bs = blocks(rest)
    run = []
    for b in bs:
        if b[0] not in LEAD:
            break
        run.append(b)
    at = run[-1][2] if run else bs[0][1]
    return rest[:at] + chunk + rest[at:]


def fences(text):
    return re.sub(
        r'(```yaml\n)(.*?)(```)',
        lambda m: m[1] + ''.join(move(m[2].splitlines(True))) + m[3],
        text,
        flags=re.S,
    )


for name in sys.argv[1:]:
    p = Path(name)
    text = p.read_text()
    new = fences(text) if p.suffix == '.md' else ''.join(move(text.splitlines(True)))
    if new != text:
        p.write_text(new)
        print('moved', name)

Placement. given: follows description: (and version:), and comes before dimensions:. The reason is that description: is what a typeset document prints first. If "start with" means the very first key, the move is the same script with one line changed.

Gates. Merged with origin/main at eefa8d2 (#837, after #810). pixi run lint: clean. pixi run ci: green, 54 documents compiled. Generated files regenerated; the diff against main is the given-first order only.

Not done. Inline specs in tests/*.py are not reordered. The key table in docs/reference/language/file.md still lists given fifth. No loader or lint rule enforces the order.

Why

The ask above.

🤖 Generated with Claude Code

https://claude.ai/code/session_019i7xNVeQzGJykmE9id6w51


Generated by Claude Code

Each spec that reads another file's names now puts its `given:` block
first, after its `description:`. The PyPSA splitter writes its fragments
in that order, and the gallery pages are regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019i7xNVeQzGJykmE9id6w51
@FBumann
FBumann requested a review from brynpickering as a code owner October 1, 2026 12:58
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019i7xNVeQzGJykmE9id6w51
@read-the-docs-community

read-the-docs-community Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

@FBumann

FBumann commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

@FabianHofmann I think the given blocks should be the first ones in a spec, so its obvious right away that its a fragment.
This also means that we should do a breaking change changing the ordering in to_yaml/to_dict etc!

@FBumann
FBumann requested a review from FabianHofmann October 1, 2026 13:23
@FBumann FBumann added the docs Documentation pages, guides, reference and README label Oct 1, 2026
@FBumann FBumann added the v0.3.0 label Oct 2, 2026
@FabianHofmann
FabianHofmann merged commit 419b11b into main Oct 6, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation pages, guides, reference and README v0.3.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants