Skip to content

Model the set and sets Commands - #84

Open
ax3l wants to merge 1 commit into
pals-project:mainfrom
ax3l:sets-command
Open

Model the set and sets Commands#84
ax3l wants to merge 1 commit into
pals-project:mainfrom
ax3l:sets-command

Conversation

@ax3l

@ax3l ax3l commented Aug 6, 2026

Copy link
Copy Markdown
Member

A facility entry keyed by a reserved node keyword is a command, not a lattice element. This models the two the standard specifies in its Setting Parameters section.

The problem

sets carries a sequence, so it never got past the {name: properties} unpacker:

TypeError: Value for element key 'sets' must be a dict (the element's properties),
           but we got [{'Q1>MagneticMultipoleP.Kn1L': 0.25}, {'D1>length': '2 * 1.5'}]

set is worse, because it did not error. It satisfies the {name: properties} shape, and since BaseElement does not forbid extras and the facility union is not discriminated, it landed on whichever member accepted it:

$ pals.load("unit_tests/sets/set_pattern.pals.yaml")
BeamLine | main
BeamBeam | set      # <- the set command, read as a BeamBeam element
Lattice  | lat1

So two files in the standard's corpus were reporting PASS while being read wrongly.

The change

  • a new src/pals/commands/ package, sibling to kinds/ and parameters/, holding SetCommand, SetsCommand and a shared FacilityCommand base. all_commands.py is the one module that maps a keyword to its model, mirroring kinds/all_elements.py;
  • unpack_element_items gains allow_commands, which only the facility passes. BeamLine.line, Lattice.branches and UnionEle.elements keep rejecting commands, as the standard places set under facility;
  • commands keep their place in the ordered facility list, because lattice expansion only lets a command act on what was defined before it;
  • values are recorded verbatim, whether a number (0.25) or an expression (2*PARAMETER + atan(SELF.BendP.g_ref)). This is the exact representation, so nothing is evaluated;
  • absolute_error / relative_error default to None rather than the documented 0, so a property the file did not write stays out of the output and round trips stay faithful.

The compact form desugars into SetCommand pairs, so a reader can treat both forms alike, and is written back out in its compact form.

Result

unit_tests/sets/sets_compact.pals.yaml leaves the known-failures list, and set_pattern.pals.yaml and set_single_definition.pals.yaml now pass for the right reason.

Since a bare PASS turned out to prove so little, validate_standard_examples.py grows a spot-check table alongside the existing check_fodo, and the new entry asserts the sets node really is a SetsCommand with its two pairs.

tests/test_commands.py covers both forms, the error terms, YAML and JSON round trips, documents assembled from Python objects, and the structural errors.

Verified

  • pytest tests -v — 63 passed, 2 skipped (was 49 passed, 2 skipped)
  • the corpus at the pinned commit pals-project/pals@7ffec92, which is what CI checks out — 65 files, 0 unexpected results
  • pre-commit run --all-files, python examples/fodo.py

Deliberately not in this PR

  • constants and variables still misparse the same way set did — the map form silently becomes an element, the sequence form raises. variables is also, as far as I can tell, not documented in the standard's source/*.md; it appears only in the examples corpus and pals-cpp.
  • inline_expressions.pals.yaml stays a known failure. The variables sequence form alone would not clear it: it also needs expressions accepted where a parameter is typed as a number (length: 0.1*log(abs(b_var)), Kn1: expr(...)) and a kind: constant element.
  • expand_lattice and Controller are unmodeled.
  • Separately, and pre-existing: an element that fails its own validator degrades silently to a PlaceholderName rather than erroring. Q1 in sets_compact.pals.yaml is a Quadrupole with no multipole group, so it trips validate_at_least_one_multipole and is read as a bare reference, losing kind and length. Worth its own issue — the fix is likely to make the element union discriminated on kind.

🤖 Generated with Claude Code

A `facility` entry keyed by a reserved node keyword is a command, not a
lattice element. `sets` carries a sequence, so it never got past the
`{name: properties}` unpacker; `set` did get past it and was read as
whichever element of the union happened to accept it (a BeamBeam).

Add a `commands` package holding SetCommand and SetsCommand, per the
standard's Setting Parameters section, and recognize their keywords in
the facility list only. Values are recorded verbatim, whether a number
or an expression string: this is the exact representation, so nothing is
evaluated.

Clears unit_tests/sets/sets_compact.pals.yaml from the known-failures
list, and makes set_pattern.pals.yaml and set_single_definition.pals.yaml
pass for the right reason. Since a bare PASS turned out to prove so
little, the corpus validator grows a spot-check table.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ax3l ax3l added the commands label Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant