def _eq_dict(ca, cb, ignore=None): # assume ca and cb can be destructively modified if ignore: for key in ignore: if key in ca: del ca[key] if key in cb: del cb[key] # this needs to be recursive so we can '&ignore'-out ids anywhere # in a json stream for key in set(list(ca.keys()) + list(cb.keys())): if key not in ca: log.error('%s!= %s\n key "%s" not in first argument' % (ca, cb, key)) return False if key not in cb: log.error('%s!= %s\n key "%s" not in second argument' % (ca, cb, key)) return False v1 = ca[key] v2 = cb[key] log.info('Comparing values for key: %s', key) if v1 == '&ignore' or v2 == '&ignore': log.info('Ignored comparison for key: %s', key) continue if not isinstance(v2, six.text_type) and isinstance(v1, six.text_type): if not eq_pprint(type(v1), type(v2)): log.error( 'The types of values for "%s" do not match (%s vs. %s)' % (key, v1, v2)) return False if isinstance(v1, list): if not _eq_list(v1, v2, ignore=ignore): return False elif isinstance(v1, dict): if not _eq_dict(v1, v2, ignore=ignore): return False elif isinstance(v1, float) and isinstance(v2, float): if not approx_equal(v1, v2): log.error( 'The values for "%s" do not match (%.30f vs. %.30f)' % (key, v1, v2)) return False else: if not v1 == v2: log.error( 'The values for "%s" do not match (%s vs. %s)' % (key, v1, v2)) return False return True
def eq_pprint(a, b, msg=None): if a != b: log.error(msg) return False return True