ATLAS Offline Software
Loading...
Searching...
No Matches
python.MetaDiff Namespace Reference

Functions

 summary (content)
 truncateDict (value)
 print_diff (parent_key, obj1, obj2, diff_format, filter_key, key_only)
 print_diff_type (parent_key, obj1, obj2, diff_format, filter_key, key_only)
 print_diff_dict_keys (parent_key, obj1, obj2, diff_format, filter_key, key_only)
 compare (obj1, obj2, parent_key=None, ordered=False, diff_format="simple", filter_key=None, filter_metadata_items=None, key_only=False)
 compare_dicts (test, reference, ordered=False, diff_format="simple", filter_key=None, filter_metadata_items=None, key_only=False)
 meta_diff (files, verbose=False, ordered=False, drop=None, mode="lite", meta_key_filter=None, file_type=None, promote=False, diff_format="simple", regex=False, key_only=False, ignore_trigger=False, normalize_type_names=False)

Detailed Description

The function in this module you should look to be using is meta_diff

Function Documentation

◆ compare()

compare ( obj1,
obj2,
parent_key = None,
ordered = False,
diff_format = "simple",
filter_key = None,
filter_metadata_items = None,
key_only = False )
Caclulate difference between two objects

Keyword arguments:
obj1       -- first object in comparision
obj2       -- second object in comparision
parent_key -- the key of the objects in the parent, used in recursion
ordered    -- whether to check order of list content

Definition at line 198 of file MetaDiff.py.

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
200
201 Keyword arguments:
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
206 """
207 result = list()
208
209 if not ordered and isinstance(obj1, list):
210 obj1.sort()
211
212 if not ordered and isinstance(obj2, list):
213 obj2.sort()
214
215 if obj1 == obj2:
216 return result
217
218 if isinstance(obj1, type(obj2)):
219
220 if isinstance(obj1, dict):
221 # filter out ignored metadata items
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:
225 obj1.pop(key, None)
226 obj2.pop(key, None)
227
228 if sorted(obj1.keys()) != sorted(obj2.keys()):
229 result += [
230 print_diff_dict_keys(parent_key, obj1, obj2, diff_format, filter_key, key_only)
231 ]
232 else:
233 for key in sorted(set(obj1.keys()) | set(obj2.keys())):
234 if parent_key:
235 child_key = "{}/{}".format(parent_key, key)
236 else:
237 child_key = key
238 result += compare(
239 obj1[key], obj2[key], child_key, ordered, diff_format, filter_key, filter_metadata_items, key_only
240 )
241
242 else:
243 result += [print_diff(parent_key, obj1, obj2, diff_format, filter_key, key_only)]
244
245 else:
246 result += [print_diff_type(parent_key, obj1, obj2, diff_format, filter_key, key_only)]
247
248 return result
249
250
STL class.

◆ compare_dicts()

compare_dicts ( test,
reference,
ordered = False,
diff_format = "simple",
filter_key = None,
filter_metadata_items = None,
key_only = False )
Show the differences between two dictionaries

Args:
    test          (dict): first object in comparision
    reference     (dict): second object in comparision
    ordered       (bool): whether to check order of list content
    diff_format (string): specify a format to display the difference in

Definition at line 251 of file MetaDiff.py.

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
253
254 Args:
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
259 """
260 result = list()
261
262 keys = set(test.keys()).union(reference.keys())
263 for key in keys:
264
265 try:
266 val1 = test[key]
267 except KeyError:
268 val1 = None
269 try:
270 val2 = reference[key]
271 except KeyError:
272 val2 = None
273
274 result += compare(
275 obj1=val1,
276 obj2=val2,
277 parent_key=key,
278 ordered=ordered,
279 diff_format=diff_format,
280 filter_key=filter_key,
281 filter_metadata_items=filter_metadata_items,
282 key_only=key_only
283 )
284 return result
285

◆ meta_diff()

meta_diff ( files,
verbose = False,
ordered = False,
drop = None,
mode = "lite",
meta_key_filter = None,
file_type = None,
promote = False,
diff_format = "simple",
regex = False,
key_only = False,
ignore_trigger = False,
normalize_type_names = False )
Compare the in-file metadata in two given files. Uses PyUtils.MetaReader
to obtain file content. Generates list of string that show difference.
Returns empty list if no difference is found

Keyword arguments:
files   -- Names of two files to compare
verbose -- toggle to get debug information
ordered -- whether to check order of lists in the metadata
drop    -- keys to drop from metadata retrieved by MetaReader
mode    -- MetaReader argument setting amount of content (default 'lite').
           Allowed values are: tiny, lite, peeker, and full
meta_key_filter -- MetaReader argument selecting keys to retrieve (default
                   get all)
file_type    -- Type of files, POOL or BS (default: auto-configure)
promote      -- MetaReader argument (default: False)
diff_format  -- Return 'simple' or 'diff' style string (default: 'simple')
regex        -- Use regex for the drop filter (default: False)
key_only     -- Show only the keys instead of their value (default: False)
normalize_type_names -- MetaReader argument to report RNTuple item types
                        using TTree class names and TTree item names
                        using RNTuple field names, with the items sorted
                        (default: False)

Definition at line 286 of file MetaDiff.py.

300):
301 """
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
305
306 Keyword arguments:
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
314 get all)
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
323 (default: False)
324 """
325 if len(files) != 2:
326 raise ValueError("Wrong number of files passes, need two")
327
328 reader_msg = logging.getLogger("MetaReader")
329 reader_msg.setLevel(logging.INFO if verbose else logging.WARNING)
330
331 msg = logging.getLogger("MetaDiff")
332 msg.setLevel(logging.DEBUG if verbose else logging.INFO)
333
334 msg.debug("Reading from %s and %s", files[0], files[1])
335
336 metadata = read_metadata(
337 files,
338 file_type,
339 mode=mode,
340 meta_key_filter=meta_key_filter,
341 promote=promote,
342 normalize_type_names=normalize_type_names,
343 )
344
345 if drop is not None and regex:
346 for i in range(len(drop)):
347 drop[i] = re.compile( drop[i] )
348
349 def filter_metadata_items(key):
350 key_str = str(key) # force conversion to plain Python string
351
352 if drop is not None:
353 for drop_key in drop:
354 if not regex:
355 if not drop_key.startswith("metadata_items/"):
356 continue
357
358 drop_key = drop_key[len("metadata_items/"):]
359
360 if key_str.startswith(drop_key):
361 return False
362 else:
363 if not drop_key.pattern.startswith("metadata_items/"):
364 continue
365
366 drop_key = re.compile(drop_key.pattern[len("metadata_items/"):])
367
368 if drop_key.match(key_str):
369 return False
370
371 return True
372
373 def filter_key(key):
374 key_str = str(key) # force conversion to plain Python string
375
376 if drop is not None:
377 for drop_key in drop:
378 if not regex:
379 if key_str.startswith(drop_key):
380 return False
381 else:
382 if drop_key.match(key_str):
383 return False
384
385 if ignore_trigger:
386 for trigger_key in trigger_keys:
387 if key_str.startswith(trigger_key):
388 return False
389
390 return True
391
392 result = compare_dicts(
393 metadata[files[0]],
394 metadata[files[1]],
395 ordered=ordered,
396 diff_format=diff_format,
397 filter_key=filter_key,
398 filter_metadata_items=filter_metadata_items,
399 key_only=key_only
400 )
401
402 if not result:
403 msg.info("No differences found")
404
405 return list(sorted([r for r in result if r is not None ]))

◆ print_diff()

print_diff ( parent_key,
obj1,
obj2,
diff_format,
filter_key,
key_only )
build comparison string for two non-dictionary objects

Definition at line 54 of file MetaDiff.py.

54def print_diff(parent_key, obj1, obj2, diff_format, filter_key, key_only):
55 """build comparison string for two non-dictionary objects"""
56
57 if filter_key is not None and filter_key(parent_key) is False:
58 # skip this key
59 return
60
61 result = "\n"
62
63 if diff_format == "simple":
64 if not obj1:
65 result += "{} has been inserted".format(parent_key)
66 elif not obj2:
67 result += "{} has been deleted".format(parent_key)
68 else:
69 if key_only:
70 result += "{} has changed".format( parent_key )
71 else:
72 result += "{} has changed from '{}' to '{}'".format(
73 parent_key, obj1, obj2
74 )
75 result += "\n"
76 else:
77
78 if parent_key is not None:
79
80 if key_only:
81 result += "{}".format(parent_key)
82 else:
83 result += "{}:\n".format(parent_key)
84 try:
85 overlap = set(obj1).intersection(set(obj2))
86 for item in overlap:
87 obj1.remove(item)
88 obj2.remove(item)
89 except (AttributeError, TypeError,):
90 pass
91 result += """\
92 < {}
93 ----------
94 > {}
95 """.format(
96 summary(obj1), summary(obj2)
97 )
98
99 return result
100
101
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)

◆ print_diff_dict_keys()

print_diff_dict_keys ( parent_key,
obj1,
obj2,
diff_format,
filter_key,
key_only )
build diff style string for dictionary objects

Definition at line 146 of file MetaDiff.py.

146def print_diff_dict_keys(parent_key, obj1, obj2, diff_format, filter_key, key_only):
147 """build diff style string for dictionary objects"""
148
149 if filter_key is not None and filter_key(parent_key) is False:
150 # skip this key
151 return
152
153 result = '\n'
154 if diff_format != 'simple':
155 shared_keys = set(obj1.keys()).intersection(obj2.keys())
156 for k in shared_keys:
157 if obj1[k] == obj2[k]:
158 try:
159 obj1.pop(k, None)
160 obj2.pop(k, None)
161 except TypeError:
162 pass
163
164 if diff_format == 'simple':
165 if obj1 is None:
166 result += "{} has been inserted".format(parent_key)
167 elif obj2 is None:
168 result += "{} has been deleted".format(parent_key)
169 else:
170
171 if key_only:
172 result += "{} has changed".format(parent_key)
173 else:
174 value1 = truncateDict(obj1)
175 value2 = truncateDict(obj2)
176 result += "{} has changed from '{}' to '{}'".format(
177 parent_key, value1, value2
178 )
179 else:
180 if parent_key is not None:
181
182
183 if key_only:
184 result += "{}".format(parent_key)
185 else:
186 result += "{}:\n".format(parent_key)
187 result += """\
188 < {}
189 ----------
190 > {}
191 """.format( summary(obj1), summary(obj2) )
192
193 result += "\n"
194
195 return result
196
197

◆ print_diff_type()

print_diff_type ( parent_key,
obj1,
obj2,
diff_format,
filter_key,
key_only )
Build diff string for objet of different type

Definition at line 102 of file MetaDiff.py.

102def print_diff_type(parent_key, obj1, obj2, diff_format, filter_key, key_only):
103 """Build diff string for objet of different type"""
104
105 if filter_key is not None and filter_key(parent_key) is False:
106 # skip this key
107 return
108
109 result = "\n"
110
111 if diff_format == "simple":
112 if obj1 is None:
113 result += "{} has been inserted".format(parent_key)
114 elif obj2 is None:
115 result += "{} has been deleted".format(parent_key)
116 else:
117 if key_only:
118 result += (
119 "{} has changed changed type from {} to {}"
120 ).format(parent_key, type(obj1), type(obj2))
121 else:
122 result += (
123 "{} has changed changed type from {} (value: '{}') to "
124 "{} (value: '{}')"
125 ).format(parent_key,
126 type(obj1), obj1,
127 type(obj2), obj2)
128 result += "\n"
129 else:
130 if parent_key is not None:
131 if key_only:
132 result += "{}".format(parent_key)
133 else:
134 result += "{}:\n".format(parent_key)
135 result += """\
136 < {} (type: {})
137 ----------
138 > {} (type: {})
139 """.format(
140 summary(obj1), type(obj1), summary(obj2), type(obj2)
141 )
142
143 return result
144
145

◆ summary()

summary ( content)
Create a summary string for an object

Definition at line 12 of file MetaDiff.py.

12def summary(content):
13 """Create a summary string for an object"""
14 if isinstance(content, str):
15 return content
16
17 try:
18 try:
19 working_copy = content.items()
20 except AttributeError:
21 working_copy = content
22 result = ''
23 for key, value in working_copy:
24 result += "{}: {}, ".format(key, summary(value))
25 return result
26 except (TypeError, ValueError,):
27 pass
28
29 try:
30 if len(content) < 3:
31 return str(content)
32 return "[{}, {}, ..., {}]".format(
33 summary(content[0]), summary(content[1]), summary(content[-1])
34 )
35 except TypeError:
36 pass
37
38 return str(content)
39
40

◆ truncateDict()

truncateDict ( value)
Create truncted string replaceing dicts with {...}

Definition at line 41 of file MetaDiff.py.

41def truncateDict(value):
42 """Create truncted string replaceing dicts with {...}"""
43 return ', '.join(
44 [
45 '{}: {}'.format(
46 k,
47 '{...}' if isinstance(v, dict) else v
48 )
49 for k, v in sorted(value.items())
50 ]
51 )
52
53