| from __future__ import annotations | |
| import argparse | |
| from collections.abc import Generator | |
| from collections.abc import Sequence | |
| from typing import Any | |
| from typing import NamedTuple | |
| import ruamel.yaml | |
| yaml = ruamel.yaml.YAML(typ='safe') | |
| def _exhaust(gen: Generator[str]) -> 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 constructs ' | |
| '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.') | |
| args = parser.parse_args(argv) | |
| 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()) |