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)
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)
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 ]))