Source code for pyretis.tools.convert_settings

"""Convert a legacy PyRETIS ``.rst`` settings file to TOML.

Usage:
    python -m pyretis.tools.convert_settings path/to/retis.rst
    python -m pyretis.tools.convert_settings path/to/retis.rst out.toml

If the output path is omitted, the converter writes alongside the
input with the extension swapped to ``.toml`` (``retis.rst`` →
``retis.toml``). The original ``.rst`` is left in place.

The converter validates each conversion by re-reading the produced
TOML and comparing the resulting raw settings dict to the rst one;
any mismatch aborts with an error.
"""
import argparse
import os
import sys

from pyretis.inout.settings import (
    _read_rst_raw,
    _read_toml_raw,
    write_settings_toml,
)


[docs]def _strip_heading(value): """Drop ``heading`` keys recursively for converter equality checks. The TOML schema intentionally omits the decorative heading text, so any nested copy (created by ensemble-inheritance during defaulting) is ignored when comparing raw dicts. """ if isinstance(value, dict): return {k: _strip_heading(v) for k, v in value.items() if k != 'heading'} if isinstance(value, list): return [_strip_heading(v) for v in value] return value
[docs]def convert(rst_path, toml_path=None, *, force=False, validate=True): """Convert one rst file to TOML and (optionally) verify the round-trip. Returns the path of the written TOML file. """ if not os.path.isfile(rst_path): raise FileNotFoundError(rst_path) if toml_path is None: toml_path = os.path.splitext(rst_path)[0] + '.toml' if os.path.exists(toml_path) and not force: raise FileExistsError( f'{toml_path} already exists (pass --force to overwrite)' ) raw = _strip_heading(_read_rst_raw(rst_path)) write_settings_toml(raw, toml_path, backup=False) if validate: roundtrip = _read_toml_raw(toml_path) if roundtrip != raw: os.unlink(toml_path) raise RuntimeError( f'Round-trip mismatch for {rst_path}: the TOML written to ' f'{toml_path} does not parse back to the same dict. ' f'Conversion aborted.' ) return toml_path
[docs]def main(argv=None): """Run the settings converter command line interface.""" parser = argparse.ArgumentParser( prog='pyretis.tools.convert_settings', description='Convert a PyRETIS .rst settings file to TOML.', ) parser.add_argument('rst', help='input .rst file') parser.add_argument( 'toml', nargs='?', default=None, help='output .toml file (default: same name with .toml extension)', ) parser.add_argument( '--force', '-f', action='store_true', help='overwrite an existing output file', ) parser.add_argument( '--no-validate', dest='validate', action='store_false', help='skip the rst→toml→dict round-trip equality check', ) args = parser.parse_args(argv) try: out = convert( args.rst, args.toml, force=args.force, validate=args.validate, ) except (FileNotFoundError, FileExistsError, RuntimeError) as exc: print(f'error: {exc}', file=sys.stderr) return 1 print(f'wrote {out}') return 0
if __name__ == '__main__': sys.exit(main())