from __future__ import annotations import argparse from typing import Any from typing import Generator from typing import NamedTuple from typing import Sequence import ruamel.yaml yaml = ruamel.yaml.YAML(typ='safe') def _exhaust(gen: Generator[str, None, None]) -> None: for _ in gen: pass def _parse_unsafe(*args: Any, **kwargs: Any) -> None: _exhaust(yaml.parse(*args, **kwargs)) def _load_all(*args: Any, **kwargs: Any) -> None: _exhaust(yaml.load_all(*args, **kwargs)) class Key(NamedTuple): multi: bool unsafe: bool LOAD_FNS = { Key(multi=False, unsafe=False): yaml.load, Key(multi=False, unsafe=True): _parse_unsafe, Key(multi=True, unsafe=False): _load_all, Key(multi=True, unsafe=True): _parse_unsafe, } def main(argv: Sequence[str] | None = None) -> int: parser = argparse.ArgumentParser() parser.add_argument( '-m', '--multi', '--allow-multiple-documents', action='store_true', ) parser.add_argument( '--unsafe', action='store_true', help=( 'Instead of loading the files, simply parse them for syntax. ' 'A syntax-only check enables extensions and unsafe contstructs ' 'which would otherwise be forbidden. Using this option removes ' 'all guarantees of portability to other yaml implementations. ' 'Implies --allow-multiple-documents' ), ) parser.add_argument('filenames', nargs='*', help='Filenames to check.') parser.add_argument( '--allow_duplicate_keys', '--allow-duplicate-keys', action='store_true', help=( 'In JSON mapping keys should be unique, in YAML they must be unique.' 'PyYAML never enforced this although the YAML 1.1 specification already required this.' 'Duplicate keys in mappings are no longer allowed by default.' 'Use this parameter to allow duplicate keys in yaml files.' ), ) args = parser.parse_args(argv) yaml.allow_duplicate_keys = args.allow_duplicate_keys load_fn = LOAD_FNS[Key(multi=args.multi, unsafe=args.unsafe)] retval = 0 for filename in args.filenames: try: with open(filename, encoding='UTF-8') as f: load_fn(f) except ruamel.yaml.YAMLError as exc: print(exc) retval = 1 return retval if __name__ == '__main__': raise SystemExit(main())