From 2f56bd116a0b29aef3d3475ad4d70d6935a41727 Mon Sep 17 00:00:00 2001 From: Matěj Cepl Date: Tue, 29 Nov 2011 18:56:25 +0100 Subject: Add option -a to ignore appended keys (for comparing changing piglit tests). Fix #35 --- json_diff.py | 52 +++++++++++++++++++++++++++++++++++++--------------- test_json_diff.py | 17 ++++++++++------- test_strings.py | 19 +++++++++++++++++++ 3 files changed, 66 insertions(+), 22 deletions(-) diff --git a/json_diff.py b/json_diff.py index d7d8aeb..4522ceb 100755 --- a/json_diff.py +++ b/json_diff.py @@ -132,7 +132,7 @@ class Comparator(object): """ Main workhorse, the object itself """ - def __init__(self, fn1=None, fn2=None, included_attrs=(), excluded_attrs=()): + def __init__(self, fn1=None, fn2=None, opts=None): self.obj1 = None self.obj2 = None if fn1: @@ -144,22 +144,37 @@ class Comparator(object): try: self.obj2 = json.load(fn2) except (TypeError, OverflowError, ValueError), exc: - raise BadJSONError("Cannot decode object from JSON\n%s" % unicode(exc)) - self.excluded_attributes = excluded_attrs - self.included_attributes = included_attrs + raise BadJSONError("Cannot decode object from JSON\n%s" % + unicode(exc)) + + if opts and ("excluded_attrs" in opts): + self.excluded_attributes = opts['excluded_attrs'] + else: + self.excluded_attributes = () + if opts and ("included_attrs" in opts): + self.included_attributes = opts['included_attrs'] + else: + self.included_attributes = () + + if opts and ('ignore_append' in opts): + self.ignore_appended = opts['ignore_append'] + else: + self.ignore_appended = False def _is_incex_key(self, key, value): - """Is this key excluded or not among included ones? If yes, it should be ignored. - """ - key_out = ((self.included_attributes and (key not in self.included_attributes)) or - (key in self.excluded_attributes)) + """Is this key excluded or not among included ones? If yes, it should + be ignored.""" + key_out = ((self.included_attributes and + (key not in self.included_attributes)) or + (key in self.excluded_attributes)) value_out = True if isinstance(value, dict): for change_key in value: if isinstance(value[change_key], dict): for key in value[change_key]: - if ((self.included_attributes and (key in self.included_attributes)) or - (key not in self.excluded_attributes)): + if ((self.included_attributes and + (key in self.included_attributes)) or + (key not in self.excluded_attributes)): value_out = False return key_out and value_out @@ -173,8 +188,12 @@ class Comparator(object): for change_type in result: temp_dict = {} for key in result[change_type]: - logging.debug("result[change_type] = %s, key = %s", unicode(result[change_type]), key) - logging.debug("self._is_incex_key(key, result[change_type][key]) = %s", + logging.debug("change_type = %s", change_type) + if self.ignore_appended and (change_type == "_append"): + continue + logging.debug("result[change_type] = %s, key = %s", + unicode(result[change_type]), key) + logging.debug("self._is_incex_key = %s", self._is_incex_key(key, result[change_type][key])) if not self._is_incex_key(key, result[change_type][key]): temp_dict[key] = result[change_type][key] @@ -306,8 +325,11 @@ if __name__ == "__main__": action="append", dest="exclude", metavar="ATTR", default=[], help="attributes which should be ignored when comparing") parser.add_option("-i", "--include", - action="append", dest="include", metavar="ATTR", default=[], - help="attributes which should be exclusively used when comparing") + action="append", dest="include", metavar="ATTR", default=[], + help="attributes which should be exclusively used when comparing") + parser.add_option("-a", "--ignore-append", + action="store_true", dest="ignore_append", metavar="BOOL", default=False, + help="ignore appended keys") parser.add_option("-H", "--HTML", action="store_true", dest="HTMLoutput", metavar="BOOL", default=False, help="program should output to HTML report") @@ -316,7 +338,7 @@ if __name__ == "__main__": if len(args) != 2: parser.error("Script requires two positional arguments, names for old and new JSON file.") - diff = Comparator(open(args[0]), open(args[1]), options.include, options.exclude) + diff = Comparator(open(args[0]), open(args[1]), options) if options.HTMLoutput: diff_res = diff.compare_dicts() # we want to hardcode UTF-8 here, because that's what's in element diff --git a/test_json_diff.py b/test_json_diff.py index 5b93044..21cd7af 100644 --- a/test_json_diff.py +++ b/test_json_diff.py @@ -14,11 +14,12 @@ import codecs from test_strings import ARRAY_DIFF, ARRAY_NEW, ARRAY_OLD, \ NESTED_DIFF, NESTED_DIFF_EXCL, NESTED_DIFF_INCL, NESTED_NEW, NESTED_OLD, \ NO_JSON_NEW, NO_JSON_OLD, SIMPLE_ARRAY_DIFF, SIMPLE_ARRAY_NEW, \ + NESTED_DIFF_IGNORING, \ SIMPLE_ARRAY_OLD, SIMPLE_DIFF, SIMPLE_DIFF_HTML, SIMPLE_NEW, SIMPLE_OLD class OurTestCase(unittest.TestCase): - def _run_test(self, oldf, newf, difff, msg="", inc=(), exc=()): - diffator = json_diff.Comparator(oldf, newf, inc, exc) + def _run_test(self, oldf, newf, difff, msg="", opts=None): + diffator = json_diff.Comparator(oldf, newf, opts) diff = diffator.compare_dicts() expected = json.load(difff) self.assertEqual(json.dumps(diff, sort_keys=True), json.dumps(expected, sort_keys=True), @@ -26,11 +27,12 @@ class OurTestCase(unittest.TestCase): (json.dumps(expected, sort_keys=True, indent=4, ensure_ascii=False), json.dumps(diff, sort_keys=True, indent=4, ensure_ascii=False))) - def _run_test_strings(self, olds, news, diffs, msg="", inc=(), exc=()): - self._run_test(StringIO(olds), StringIO(news), StringIO(diffs), msg, inc, exc) + def _run_test_strings(self, olds, news, diffs, msg="", opts=None): + self._run_test(StringIO(olds), StringIO(news), StringIO(diffs), + msg, opts) - def _run_test_formatted(self, oldf, newf, difff, msg=""): - diffator = json_diff.Comparator(oldf, newf) + def _run_test_formatted(self, oldf, newf, difff, msg="", opts=None): + diffator = json_diff.Comparator(oldf, newf, opts) diff = ("\n".join([line.strip() \ for line in unicode( \ json_diff.HTMLFormatter(diffator.compare_dicts())).split("\n")])).strip() @@ -133,7 +135,8 @@ class TestPiglitData(OurTestCase): def test_piglit_result_only(self): self._run_test(open("test/old-testing-data.json"), open("test/new-testing-data.json"), open("test/diff-result-only-testing-data.json"), - "Large piglit reports diff (just resume field).", inc=('result',)) + "Large piglit reports diff (just resume field).", + {'included_attrs': ("result",)}) if __name__ == "__main__": unittest.main() diff --git a/test_strings.py b/test_strings.py index 1935912..31ab50f 100644 --- a/test_strings.py +++ b/test_strings.py @@ -173,6 +173,25 @@ NESTED_DIFF_INCL = u""" } """ +NESTED_DIFF_IGNORING = u""" +{ + "_remove": { + "b": 2, + "ignore": { + "else": true + } + }, + "_update": { + "a": 2, + "child": { + "_update": { + "nome": "Maruška" + } + } + } +} +""" + ARRAY_OLD = u""" { "a": 1, -- cgit