Skip to content

Port PALSParserJ to Python - #1

Merged
DavidSagan merged 1 commit into
mainfrom
port-from-palsparserj
Aug 6, 2026
Merged

Port PALSParserJ to Python#1
DavidSagan merged 1 commit into
mainfrom
port-from-palsparserj

Conversation

@DavidSagan

Copy link
Copy Markdown
Member

Fills in PALSParserPy — the Python interface to PALSParserCpp — by porting
PALSParserJ, the Julia
interface to the same C library.

What is here

palsparserpy/_clib.py ctypes mirror of PALSParserCpp.h: structs, enums, prototypes, library discovery
palsparserpy/node.py YAMLTree / YAMLNode, parsing, navigation, editing, emitting
palsparserpy/structs.py Problem, Lattices, ProblemSeverity / ProblemOrigin, NodeCorrespondence
palsparserpy/parser.py parse_and_expand_pals, evaluate_pals_expression, node_correspondence, match_names, parameter_value
palsparserpy/to_bmad.py, to_madx.py, to_scibmad.py the three translators, with their shared helpers in _common.py
tests/ the Julia suite ported to pytest (110 tests)
examples/ the seven example scripts and the tree-manipulation notebook
docs/ the documentation site
.github/workflows/ tests, docs, docs-preview cleanup

The binding is ctypes, so there is nothing to compile in this repository. The C
library is located at the first call from $PALS_PARSER_CPP_LIB,
$PALS_PARSER_CPP_DIR, or a PALSParserCpp checkout beside — or around — this
one; import palsparserpy itself never loads it, so the docs build needs no C++
toolchain.

Verification

Beyond the test suite, the translators were checked against the reference
implementation on real lattices: pals_to_bmad and pals_to_madx on
bta.pals.yaml, and pals_to_scibmad on convert.pals.yaml, produce
byte-identical files and identical diagnostics to PALSParserJ. The
match_names, node_correspondence and evaluate_expressions example outputs
match line for line.

Where it departs from a literal transcription

  • 0-based indexing (node[0], add_scalar(index=0)) — Python's convention
    and the C API's, where PALSParserJ is 1-based.
  • A Pythonic surface: key in node, len / keys / values / items,
    node.value / .as_int() / .as_float() / .as_bool(), KeyError /
    IndexError / ValueError / FileNotFoundError, and None where Julia
    returned missing. Every node operation is both a method and a free function,
    so is_map(node) still reads alongside node.is_map().
  • problems="print" | "none" | <path> in place of Julia's Symbol-vs-String
    overload; the two names are reserved and documented.
  • The docs are one Sphinx build — autodoc reads the docstrings from inside
    Sphinx, so the Documenter half PALSParserJ needs has nothing to stitch on.
  • One fix along the way: an ApertureP location: CENTER raised a type error in
    the Julia source (x || (y && println(...)) yields nothing); here it warns
    and sets aperture_at = both_ends, as was clearly intended.

Requires Python 3.9+; CI runs 3.9 and 3.12 on macOS and Ubuntu. The interpreter
has to match the architecture the C library was built for.

🤖 Generated with Claude Code

PALSParserPy is now a Python wrapper around the PALSParserCpp C library,
mirroring PALSParserJ: the YAML tree object model, lattice expansion,
expression evaluation, node correspondence, name matching, parameter
lookup, and the Bmad / MAD-X / SciBmad translators.

The binding is ctypes, so there is nothing to compile here; the C library
is located at first call from $PALS_PARSER_CPP_LIB, $PALS_PARSER_CPP_DIR,
or a PALSParserCpp checkout beside (or around) this one.

The API is Pythonic where Julia's was Julian: 0-based indexing, `key in
node`, len/keys/values/items, node.value / .as_int() / .as_float() /
.as_bool(), KeyError / IndexError / ValueError / FileNotFoundError, and
None where Julia returned missing. Every node operation is both a method
and a free function, so the PALSParserJ spelling still reads. The
`problems` argument takes "print", "none", or a path, in place of Julia's
Symbol-vs-String overload.

Verified against the reference implementation: pals_to_bmad and
pals_to_madx on bta.pals.yaml, and pals_to_scibmad on convert.pals.yaml,
produce byte-identical files and identical diagnostics to PALSParserJ.
The 110 tests are the Julia suite ported to pytest.

Also ported: the seven examples and the tree-manipulation notebook, the
documentation site (one Sphinx build, autodoc replacing the Documenter
half), and the test/docs workflows.

One fix along the way: an ApertureP `location: CENTER` raised a type
error in the Julia source (`x || (y && println(...))` yields nothing);
here it warns and sets aperture_at = both_ends, as intended.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

📖 Documentation preview for this PR: https://pals-project.github.io/PALSParserPy/previews/PR1/

Rebuilt on every push; removed automatically when the PR closes.

@DavidSagan
DavidSagan merged commit cd8a71e into main Aug 6, 2026
5 checks passed
@DavidSagan
DavidSagan deleted the port-from-palsparserj branch August 6, 2026 00:31
github-actions Bot added a commit that referenced this pull request Aug 6, 2026
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.

1 participant