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())