From a4c2cb942c904112ddcf8e73af6198045362ef24 Mon Sep 17 00:00:00 2001 From: Cory Todd Date: Tue, 5 Sep 2023 14:09:49 -0700 Subject: [PATCH] cli: handle malformed input files Do not show a stacktrace on the cli tool when an invalid file is specified. Instead, use the new Serializer class to abstract the load process and handle the unified ValueError. Also handle FileNotFound because that's a fairly normal user input scenario as well. Set return code on sys.exit to indicate abnormal exit. Fixes #71 Signed-off-by: Cory Todd --- jsondiff/cli.py | 66 +++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/jsondiff/cli.py b/jsondiff/cli.py index a6e1a12..49fdcbd 100644 --- a/jsondiff/cli.py +++ b/jsondiff/cli.py @@ -2,6 +2,16 @@ import jsondiff import sys +def load_file(serializer, file_path): + with open(file_path, "r") as f: + parsed = None + try: + parsed = serializer.deserialize_file(f) + except ValueError: + print(f"{file_path} is not a valid {serializer.file_format} file") + except FileNotFoundError: + print(f"{file_path} does not exist") + return parsed def main(): parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) @@ -18,35 +28,33 @@ def main(): args = parser.parse_args() - # pyyaml _can_ load json but is ~20 times slower and has known issues so use - # the json from stdlib when json is specified. - serializers = { - "json": (jsondiff.JsonLoader(), jsondiff.JsonDumper(indent=args.indent)), - "yaml": (jsondiff.YamlLoader(), jsondiff.YamlDumper(indent=args.indent)), - } - loader, dumper = serializers[args.format] - - with open(args.first, "r") as f: - with open(args.second, "r") as g: - jf = loader(f) - jg = loader(g) - if args.patch: - x = jsondiff.patch( - jf, - jg, - marshal=True, - syntax=args.syntax - ) - else: - x = jsondiff.diff( - jf, - jg, - marshal=True, - syntax=args.syntax - ) - - dumper(x, sys.stdout) + serializer = jsondiff.Serializer(args.format, args.indent) + parsed_first = load_file(serializer, args.first) + parsed_second = load_file(serializer, args.second) + + if not (parsed_first and parsed_second): + return 1 + + if args.patch: + x = jsondiff.patch( + parsed_first, + parsed_second, + marshal=True, + syntax=args.syntax + ) + else: + x = jsondiff.diff( + parsed_first, + parsed_second, + marshal=True, + syntax=args.syntax + ) + + serializer.serialize_data(x, sys.stdout) + + return 0 if __name__ == '__main__': - main() + ret = main() + sys.exit(ret)