blob: c98ae5ae780caf776ec7be4b8819f8ddf9fca1a0 [file] [log] [blame]
#!/usr/bin/env python
from argparse import ArgumentParser
from collections.abc import Mapping, Sequence
from codecs import open as codecs_open
from itertools import zip_longest
from json import loads
from logging import basicConfig, DEBUG, getLogger
from math import isnan
from pathlib import Path
from pyjson5 import decode, encode
def eq_with_nans(left, right):
if left == right:
return True
elif isnan(left):
return isnan(right)
elif isnan(right):
return False
if not isinstance(left, Sequence) or not isinstance(right, Sequence):
return False
elif len(left) != len(right):
return False
left_mapping = isinstance(left, Mapping)
right_mapping = isinstance(right, Mapping)
if left_mapping != right_mapping:
return False
sentinel = object()
if left_mapping:
for k, left_value in left.items():
right_value = right.pop(k, sentinel)
if not eq_with_nans(left_value, right_value):
return False
if right:
# extraneous keys
return False
else:
for l, r in zip_longest(left, right, fillvalue=sentinel):
if not eq_with_nans(l, r):
return False
return True
argparser = ArgumentParser(description="Run JSON5 parser tests")
argparser.add_argument("input", type=Path)
argparser.add_argument("output", nargs="?", type=Path)
if __name__ == "__main__":
basicConfig(level=DEBUG)
logger = getLogger(__name__)
args = argparser.parse_args()
try:
# open() does not work with Paths in Python 3.5
with codecs_open(str(args.input.resolve()), "r", "UTF-8") as f:
data = f.read()
except Exception:
logger.error("Could not even read file: %s", args.input, exc_info=True)
raise SystemExit(-1)
try:
obj = decode(data)
except Exception:
logger.error("Could not parse content: %s", args.input)
raise SystemExit(1)
try:
json_obj = loads(data)
except Exception:
pass
else:
if not eq_with_nans(obj, json_obj):
logger.error(
"JSON and PyJSON5 did not read the same data: %s, %r != %r",
args.input,
obj,
json_obj,
)
raise SystemExit(2)
try:
data = encode(obj)
except Exception:
logger.error("Could open stringify content: %s", args.input, exc_info=True)
raise SystemExit(2)
if args.output is not None:
try:
# open() does not work with Paths in Python 3.5
with codecs_open(str(args.output.resolve()), "w", "UTF-8") as f:
f.write(data)
except Exception:
logger.error("Could open output file: %s", args.output, exc_info=True)
raise SystemExit(-1)
raise SystemExit(0)