Skip to content

feat(spec): the entries of each section and the regions under cases: are sorted by name as a spec loads, so every output lists them in that order - #921

Closed
FBumann wants to merge 3 commits into
feat/write-as-setfrom
claude/friendly-euler-xw49b2
Closed

FBumann wants to merge 3 commits into
feat/write-as-setfrom
claude/friendly-euler-xw49b2

Conversation

@FBumann

@FBumann FBumann commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Prompt: I think ordering everything might be the best and easiest choice for now.
Custom order for entries might be desireable later...

Prompt: THe entries of the top level blocks i mean. (dimensions, variables, expressions, ...)
I think we should do it like this for now!

Prompt: This breaks our rule
Sort them too
Also in canonical!?

Note

The following content was generated by AI.

What this changes

to_spec sorts by name the entries of every section, those under each kind of given:, and the regions under cases:. The program, the typeset document, to_yaml() and the canonical form all list them in that order.

Stacked on #918.

Order Before Now
entries of a section, and under each kind of given: as the file lists them, in the spec, the program, the document and to_yaml() sorted by name everywhere
regions under cases: as the file lists them, also in the canonical form sorted by name everywhere, otherwise: still last
the legend's dimensions, and which dimension takes a shared first letter the order of dimensions: sorted by name: period prints as p and plant as l, whatever the order
sections, piecewise links, macro arguments unchanged unchanged
  • The canonical form sorts nothing itself any more: _sorted_entries is now _canonical_entries, and the form's "regions as written" exception is gone.
  • docs/reference/language/file.md states the rule. dimensions.md again says the order of dimensions: changes nothing, which is now true. named.md says the cases print sorted by name. reading.md, glossary.md, typeset.md and five docstrings no longer say "file order".
  • Two refusal messages said "another variable declared before it". Entry order never mattered there, so they now say "another variable". The overlap refusal names its two cases in name order.

Why

One rule: no order a file writes reaches a value a reader sees. Since #914 and #916 this held for dims: lists and relation sides, but entries and regions kept the file's order, and the letters followed dimensions:. The regions are proved apart rather than tried in turn, so their order meant nothing, but two files that differ only in it wrote two canonical texts. A declared order for entries can come later.

Method, tests, gate output, mutation table

Method. A field_validator('*') on Spec and on GivenSpec, and a field_validator('cases') on ExpressionSpec, sort a mapping by key through one helper, _by_name. None of them touches model_fields_set, so #918's writer still writes only the fields the file wrote.

Tests.

  • New: test_the_order_a_file_lists_its_entries_in_reaches_no_value_of_the_spec runs on every example. It reverses every section's entries and asserts the same to_yaml() and the same key order in ten program sections. == is not enough, because dict equality ignores order.
  • New: test_the_order_a_file_lists_its_entries_in_prints_nowhere asserts the same typeset text in all three formats.
  • New: test_the_order_of_the_regions_under_cases_is_no_difference reverses the regions of commitment.yaml and asserts one canonical text, one to_yaml() and one LaTeX document. The the-regions-under-cases case of test_an_order_the_form_keeps_is_a_difference_in_the_text asserted the opposite and is removed.
  • Six tests that expected file order now expect name order: test_the_definitions_print_sorted_by_name (was …_in_file_order, and now writes its six entries in reverse), test_program_structure, the two assumption-order tests in test_lowering and test_piecewise, and the overlap message in test_cases_split_by_a_named_condition_are_proved_apart_through_its_condition.
  • The golden output and every generated page were rewritten by their tools. docs/several-files.md and the second printed block of docs/first-spec.md were rewritten from what the code prints. first-spec.md's legend was already stale since feat(language)!: every entry is indexed by its dimensions sorted by name, whatever order the file writes them in #914 (𝒯 × 𝒢), and it is now 𝒢 × 𝒯.

Gates on 098a799:

  • pixi run lint: passed.
  • pixi run test: 3550 passed, 1 skipped.
  • pixi run docs-build: passed.
  • Every generator re-run: no diff.
  • compile-tex: not run, because Tectonic cannot download its bundle in the sandbox. CI runs it.

Mutation table. Each validator was changed by hand to return its input, and the suite ran. __pycache__ was dropped before and after each run. Rows 1 and 2 ran on 8e21fb5, restored with git checkout --, with the full suite. Row 3 ran before its commit, with tests/test_canonical.py only, and was restored by editing the line back. Each time the tree came back as it was.

Change Caught by
GivenSpec keeps the file's order 121 failures, among them test_the_order_a_file_lists_its_entries_in_reaches_no_value_of_the_spec[pypsa/cost.yaml]
Spec keeps the file's order 346 failures, among them test_two_files_that_mean_the_same_thing_write_the_same_text
ExpressionSpec.cases keeps the file's order 1 failure: test_the_order_of_the_regions_under_cases_is_no_difference
Not done

🤖 Generated with Claude Code

https://claude.ai/code/session_01JzRHmodLpxhaZRQc9sgBdZ

…loads, so every output lists them in that order

`to_spec` sorts the entries of every section, and of each kind under
`given:`, by name. The program, the typeset document, `to_yaml()` and the
canonical form list them in that order, so the order a file lists its
entries in changes nothing. The legend lists the dimensions by name, and
a shared first letter goes to the first dimension by name.

The canonical form no longer sorts the entries itself. Five tests that
expected file order now expect name order, and the golden output, the
generated pages, `several-files.md` and `first-spec.md` are rewritten
from what the code prints.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JzRHmodLpxhaZRQc9sgBdZ
@read-the-docs-community

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

Copy link
Copy Markdown

…oads

The regions are proved apart rather than tried in turn, so their order
means nothing. The spec held them as the file wrote them, so two files
that state one spec wrote two canonical texts and printed their rows in
two orders. The canonical form, `to_yaml()` and the typeset document now
list them by name, with `otherwise:` last, and an overlap refusal names
the two cases in name order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JzRHmodLpxhaZRQc9sgBdZ
@FBumann FBumann changed the title feat(spec): the entries of each section are sorted by name as a spec loads, so every output lists them in that order feat(spec): the entries of each section and the regions under cases: are sorted by name as a spec loads, so every output lists them in that order Oct 21, 2026
@FBumann
FBumann added this pull request to stack #917 October 21, 2026 07:17

FBumann commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Prompt: Could it be condensed into less PRs? Its too chaotic for me atm

Note

The following content was generated by AI.

Superseded by #924, which squashes #914, #916 and #921 into one commit on main. The changes of this PR to src/, tests/ and docs/reference/ came over line for line. The branch is kept.


Generated by Claude Code

@FBumann FBumann closed this Oct 21, 2026
FBumann pushed a commit that referenced this pull request Oct 21, 2026
Each conflict resolves to the tree of #921's head, which already held
#914, #916, #918 and #921 together. The changelog keeps #918's line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019j1TmBS3MvzmuarWjhCHHu
@FBumann
FBumann removed this pull request from stack #917 October 21, 2026 07:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants