1"""The function in this module you should look to be using is meta_diff"""
9from PyUtils.MetaReader
import read_metadata, trigger_keys
13 """Create a summary string for an object"""
14 if isinstance(content, str):
19 working_copy = content.items()
20 except AttributeError:
21 working_copy = content
23 for key, value
in working_copy:
24 result +=
"{}: {}, ".format(key,
summary(value))
26 except (TypeError, ValueError,):
32 return "[{}, {}, ..., {}]".format(
42 """Create truncted string replaceing dicts with {...}"""
47 '{...}' if isinstance(v, dict)
else v
49 for k, v
in sorted(value.items())
54def print_diff(parent_key, obj1, obj2, diff_format, filter_key, key_only):
55 """build comparison string for two non-dictionary objects"""
57 if filter_key
is not None and filter_key(parent_key)
is False:
63 if diff_format ==
"simple":
65 result +=
"{} has been inserted".format(parent_key)
67 result +=
"{} has been deleted".format(parent_key)
70 result +=
"{} has changed".format( parent_key )
72 result +=
"{} has changed from '{}' to '{}'".format(
73 parent_key, obj1, obj2
78 if parent_key
is not None:
81 result +=
"{}".format(parent_key)
83 result +=
"{}:\n".format(parent_key)
89 except (AttributeError, TypeError,):
103 """Build diff string for objet of different type"""
105 if filter_key
is not None and filter_key(parent_key)
is False:
111 if diff_format ==
"simple":
113 result +=
"{} has been inserted".format(parent_key)
115 result +=
"{} has been deleted".format(parent_key)
119 "{} has changed changed type from {} to {}"
120 ).format(parent_key,
type(obj1),
type(obj2))
123 "{} has changed changed type from {} (value: '{}') to "
130 if parent_key
is not None:
132 result +=
"{}".format(parent_key)
134 result +=
"{}:\n".format(parent_key)
147 """build diff style string for dictionary objects"""
149 if filter_key
is not None and filter_key(parent_key)
is False:
154 if diff_format !=
'simple':
156 for k
in shared_keys:
157 if obj1[k] == obj2[k]:
164 if diff_format ==
'simple':
166 result +=
"{} has been inserted".format(parent_key)
168 result +=
"{} has been deleted".format(parent_key)
172 result +=
"{} has changed".format(parent_key)
176 result +=
"{} has changed from '{}' to '{}'".format(
177 parent_key, value1, value2
180 if parent_key
is not None:
184 result +=
"{}".format(parent_key)
186 result +=
"{}:\n".format(parent_key)
198def compare(obj1, obj2, parent_key=None, ordered=False, diff_format="simple", filter_key=None, filter_metadata_items=None, key_only=False):
199 """Caclulate difference between two objects
202 obj1 -- first object in comparision
203 obj2 -- second object in comparision
204 parent_key -- the key of the objects in the parent, used in recursion
205 ordered -- whether to check order of list content
209 if not ordered
and isinstance(obj1, list):
212 if not ordered
and isinstance(obj2, list):
218 if isinstance(obj1,
type(obj2)):
220 if isinstance(obj1, dict):
222 if parent_key ==
"metadata_items":
223 for key
in set(list(obj1.keys()) + list(obj2.keys())):
224 if filter_metadata_items
is not None and filter_metadata_items(key)
is False:
228 if sorted(obj1.keys()) != sorted(obj2.keys()):
233 for key
in sorted(
set(obj1.keys()) |
set(obj2.keys())):
235 child_key =
"{}/{}".format(parent_key, key)
239 obj1[key], obj2[key], child_key, ordered, diff_format, filter_key, filter_metadata_items, key_only
243 result += [
print_diff(parent_key, obj1, obj2, diff_format, filter_key, key_only)]
246 result += [
print_diff_type(parent_key, obj1, obj2, diff_format, filter_key, key_only)]
251def compare_dicts(test, reference, ordered=False, diff_format="simple", filter_key=None, filter_metadata_items=None, key_only=False):
252 """Show the differences between two dictionaries
255 test (dict): first object in comparision
256 reference (dict): second object in comparision
257 ordered (bool): whether to check order of list content
258 diff_format (string): specify a format to display the difference in
262 keys =
set(test.keys()).union(reference.keys())
270 val2 = reference[key]
279 diff_format=diff_format,
280 filter_key=filter_key,
281 filter_metadata_items=filter_metadata_items,
292 meta_key_filter=None,
295 diff_format="simple",
298 ignore_trigger=False,
299 normalize_type_names=False,
302 Compare the in-file metadata in two given files. Uses PyUtils.MetaReader
303 to obtain file content. Generates list of string that show difference.
304 Returns empty list if no difference is found
307 files -- Names of two files to compare
308 verbose -- toggle to get debug information
309 ordered -- whether to check order of lists in the metadata
310 drop -- keys to drop from metadata retrieved by MetaReader
311 mode -- MetaReader argument setting amount of content (default 'lite').
312 Allowed values are: tiny, lite, peeker, and full
313 meta_key_filter -- MetaReader argument selecting keys to retrieve (default
315 file_type -- Type of files, POOL or BS (default: auto-configure)
316 promote -- MetaReader argument (default: False)
317 diff_format -- Return 'simple' or 'diff' style string (default: 'simple')
318 regex -- Use regex for the drop filter (default: False)
319 key_only -- Show only the keys instead of their value (default: False)
320 normalize_type_names -- MetaReader argument to report RNTuple item types
321 using TTree class names and TTree item names
322 using RNTuple field names, with the items sorted
326 raise ValueError(
"Wrong number of files passes, need two")
328 reader_msg = logging.getLogger(
"MetaReader")
329 reader_msg.setLevel(logging.INFO
if verbose
else logging.WARNING)
331 msg = logging.getLogger(
"MetaDiff")
332 msg.setLevel(logging.DEBUG
if verbose
else logging.INFO)
334 msg.debug(
"Reading from %s and %s", files[0], files[1])
336 metadata = read_metadata(
340 meta_key_filter=meta_key_filter,
342 normalize_type_names=normalize_type_names,
345 if drop
is not None and regex:
346 for i
in range(len(drop)):
347 drop[i] = re.compile( drop[i] )
349 def filter_metadata_items(key):
353 for drop_key
in drop:
355 if not drop_key.startswith(
"metadata_items/"):
358 drop_key = drop_key[len(
"metadata_items/"):]
360 if key_str.startswith(drop_key):
363 if not drop_key.pattern.startswith(
"metadata_items/"):
366 drop_key = re.compile(drop_key.pattern[len(
"metadata_items/"):])
368 if drop_key.match(key_str):
377 for drop_key
in drop:
379 if key_str.startswith(drop_key):
382 if drop_key.match(key_str):
386 for trigger_key
in trigger_keys:
387 if key_str.startswith(trigger_key):
396 diff_format=diff_format,
397 filter_key=filter_key,
398 filter_metadata_items=filter_metadata_items,
403 msg.info(
"No differences found")
405 return list(sorted([r
for r
in result
if r
is not None ]))
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)