From 0f3700d1e33193cc71e6d3a4b404d8ecdc19c8e7 Mon Sep 17 00:00:00 2001 From: ferdymercury Date: Wed, 15 Oct 2025 14:43:56 +0200 Subject: [PATCH 1/3] [rootprint] add recursive directory traversal option as done earlier with rootls Fixes https://github.com/root-project/root/issues/13659 --- main/python/cmdLineUtils.py | 25 +++++++++++++++----- main/python/rootprint.py | 47 ++++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/main/python/cmdLineUtils.py b/main/python/cmdLineUtils.py index c05c44dcf7f4b..ac6dd7e115e13 100644 --- a/main/python/cmdLineUtils.py +++ b/main/python/cmdLineUtils.py @@ -1064,13 +1064,24 @@ def rootMv(sourceList, destFileName, destPathSplit, compress=None, interactive=F # ROOTPRINT -def _keyListExtended(rootFile, pathSplitList): +def _keyListExtended(rootFile, pathSplitList, recursive = False): + prefixList = [] keyList, dirList = keyClassSplitter(rootFile, pathSplitList) for pathSplit in dirList: keyList.extend(getKeyList(rootFile, pathSplit)) + subList = [key for key in keyList if isDirectoryKey(key)] keyList = [key for key in keyList if not isDirectoryKey(key)] - keyListSort(keyList) - return keyList + prefixList = ["" for key in keyList] + if recursive: + for subdir in subList: + subkeyList, subprefixList = _keyListExtended(ROOT.gDirectory.Get(subdir.GetName()), pathSplitList, recursive) + keyList.extend(subkeyList) + prefixList.extend([subdir.GetName() + "_" + prefix for prefix in subprefixList]) + if recursive: + keyList, prefixList = (list(t) for t in zip(*sorted(zip(keyList, prefixList), key=lambda x: x[0].GetName().lower()))) + else: + keyListSort(keyList) + return keyList, prefixList def rootPrint( @@ -1083,6 +1094,7 @@ def rootPrint( sizeOption=None, styleOption=None, verboseOption=False, + recursiveOption=False, ): # Check arguments if sourceList == []: @@ -1162,8 +1174,8 @@ def rootPrint( continue openRootFiles.append(rootFile) # Fill the key list (almost the same as in root) - keyList = _keyListExtended(rootFile, pathSplitList) - for key in keyList: + keyList, prefixList = _keyListExtended(rootFile, pathSplitList, recursiveOption) + for k, key in enumerate(keyList): if isTreeKey(key): pass else: @@ -1182,8 +1194,9 @@ def rootPrint( canvas.Clear() canvas.Divide(x, y) else: + prefix = prefixList[k] if not outputOption: - outputFileName = key.GetName() + "." + formatOption + outputFileName = prefix + key.GetName() + "." + formatOption if directoryOption: outputFileName = os.path.join(directoryOption, outputFileName) if outputOption or formatOption == "pdf": diff --git a/main/python/rootprint.py b/main/python/rootprint.py index ac84b0b145a66..66a43a0f06a19 100755 --- a/main/python/rootprint.py +++ b/main/python/rootprint.py @@ -21,6 +21,7 @@ SIZE_HELP = "specify canvas size on the format 'width'x'height' (ex: 600x400)" STYLE_HELP = "specify a C file name which define a style" VERBOSE_HELP = "print informations about the running" +RECURSIVE_HELP = "Traverse file recursively entering any TDirectory." EPILOG = """Examples: - rootprint example.root:hist @@ -37,30 +38,32 @@ """ def get_argparse(): - # Collect arguments with the module argparse - parser = cmdLineUtils.getParserFile(description, EPILOG) - parser.prog = 'rootprint' - parser.add_argument("-d", "--directory", help=DIRECTORY_HELP) - parser.add_argument("--divide", help=DIVIDE_HELP) - parser.add_argument("-D", "--draw", default="", help=DRAW_HELP) - parser.add_argument("-f", "--format", help=FORMAT_HELP) - parser.add_argument("-o", "--output", help=OUTPUT_HELP) - parser.add_argument("-s", "--size", help=SIZE_HELP) - parser.add_argument("-S", "--style", help=STYLE_HELP) - parser.add_argument("-v", "--verbose", action="store_true", help=VERBOSE_HELP) - return parser + # Collect arguments with the module argparse + parser = cmdLineUtils.getParserFile(description, EPILOG) + parser.prog = 'rootprint' + parser.add_argument("-d", "--directory", help=DIRECTORY_HELP) + parser.add_argument("--divide", help=DIVIDE_HELP) + parser.add_argument("-D", "--draw", default="", help=DRAW_HELP) + parser.add_argument("-f", "--format", help=FORMAT_HELP) + parser.add_argument("-o", "--output", help=OUTPUT_HELP) + parser.add_argument("-s", "--size", help=SIZE_HELP) + parser.add_argument("-S", "--style", help=STYLE_HELP) + parser.add_argument("-v", "--verbose", action="store_true", help=VERBOSE_HELP) + parser.add_argument("-r", "--recursive", action="store_true", help=RECURSIVE_HELP) + return parser def execute(): - parser = get_argparse() + parser = get_argparse() - # Put arguments in shape - sourceList, optDict = cmdLineUtils.getSourceListOptDict(parser) + # Put arguments in shape + sourceList, optDict = cmdLineUtils.getSourceListOptDict(parser) - # Process rootPrint - return cmdLineUtils.rootPrint(sourceList, directoryOption = optDict["directory"], \ - divideOption = optDict["divide"], drawOption = optDict["draw"], \ - formatOption = optDict["format"], \ - outputOption = optDict["output"], sizeOption = optDict["size"], \ - styleOption = optDict["style"], verboseOption = optDict["verbose"]) + # Process rootPrint + return cmdLineUtils.rootPrint(sourceList, directoryOption = optDict["directory"], \ + divideOption = optDict["divide"], drawOption = optDict["draw"], \ + formatOption = optDict["format"], \ + outputOption = optDict["output"], sizeOption = optDict["size"], \ + styleOption = optDict["style"], verboseOption = optDict["verbose"], \ + recursiveOption = optDict["recursive"]) if __name__ == "__main__": - sys.exit(execute()) + sys.exit(execute()) From 3693d42cba38c71980596c5783ad9c0c1a224a87 Mon Sep 17 00:00:00 2001 From: ferdymercury Date: Wed, 15 Oct 2025 14:49:43 +0200 Subject: [PATCH 2/3] [nfc] restore spacing --- main/python/rootprint.py | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/main/python/rootprint.py b/main/python/rootprint.py index 66a43a0f06a19..6684238ee8a90 100755 --- a/main/python/rootprint.py +++ b/main/python/rootprint.py @@ -38,32 +38,32 @@ """ def get_argparse(): - # Collect arguments with the module argparse - parser = cmdLineUtils.getParserFile(description, EPILOG) - parser.prog = 'rootprint' - parser.add_argument("-d", "--directory", help=DIRECTORY_HELP) - parser.add_argument("--divide", help=DIVIDE_HELP) - parser.add_argument("-D", "--draw", default="", help=DRAW_HELP) - parser.add_argument("-f", "--format", help=FORMAT_HELP) - parser.add_argument("-o", "--output", help=OUTPUT_HELP) - parser.add_argument("-s", "--size", help=SIZE_HELP) - parser.add_argument("-S", "--style", help=STYLE_HELP) - parser.add_argument("-v", "--verbose", action="store_true", help=VERBOSE_HELP) - parser.add_argument("-r", "--recursive", action="store_true", help=RECURSIVE_HELP) - return parser + # Collect arguments with the module argparse + parser = cmdLineUtils.getParserFile(description, EPILOG) + parser.prog = 'rootprint' + parser.add_argument("-d", "--directory", help=DIRECTORY_HELP) + parser.add_argument("--divide", help=DIVIDE_HELP) + parser.add_argument("-D", "--draw", default="", help=DRAW_HELP) + parser.add_argument("-f", "--format", help=FORMAT_HELP) + parser.add_argument("-o", "--output", help=OUTPUT_HELP) + parser.add_argument("-s", "--size", help=SIZE_HELP) + parser.add_argument("-S", "--style", help=STYLE_HELP) + parser.add_argument("-v", "--verbose", action="store_true", help=VERBOSE_HELP) + parser.add_argument("-r", "--recursive", action="store_true", help=RECURSIVE_HELP) + return parser def execute(): - parser = get_argparse() + parser = get_argparse() - # Put arguments in shape - sourceList, optDict = cmdLineUtils.getSourceListOptDict(parser) + # Put arguments in shape + sourceList, optDict = cmdLineUtils.getSourceListOptDict(parser) - # Process rootPrint - return cmdLineUtils.rootPrint(sourceList, directoryOption = optDict["directory"], \ - divideOption = optDict["divide"], drawOption = optDict["draw"], \ - formatOption = optDict["format"], \ - outputOption = optDict["output"], sizeOption = optDict["size"], \ - styleOption = optDict["style"], verboseOption = optDict["verbose"], \ - recursiveOption = optDict["recursive"]) + # Process rootPrint + return cmdLineUtils.rootPrint(sourceList, directoryOption = optDict["directory"], \ + divideOption = optDict["divide"], drawOption = optDict["draw"], \ + formatOption = optDict["format"], \ + outputOption = optDict["output"], sizeOption = optDict["size"], \ + styleOption = optDict["style"], verboseOption = optDict["verbose"], \ + recursiveOption = optDict["recursive"]) if __name__ == "__main__": - sys.exit(execute()) + sys.exit(execute()) From f64d925c340e8c2a5094f0563ec77b539cbf2322 Mon Sep 17 00:00:00 2001 From: ferdymercury Date: Wed, 15 Oct 2025 14:50:43 +0200 Subject: [PATCH 3/3] [nfc] spacing --- main/python/rootprint.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main/python/rootprint.py b/main/python/rootprint.py index 6684238ee8a90..21de181ec1225 100755 --- a/main/python/rootprint.py +++ b/main/python/rootprint.py @@ -49,7 +49,7 @@ def get_argparse(): parser.add_argument("-s", "--size", help=SIZE_HELP) parser.add_argument("-S", "--style", help=STYLE_HELP) parser.add_argument("-v", "--verbose", action="store_true", help=VERBOSE_HELP) - parser.add_argument("-r", "--recursive", action="store_true", help=RECURSIVE_HELP) + parser.add_argument("-r", "--recursive", action="store_true", help=RECURSIVE_HELP) return parser def execute(): @@ -63,7 +63,7 @@ def execute(): divideOption = optDict["divide"], drawOption = optDict["draw"], \ formatOption = optDict["format"], \ outputOption = optDict["output"], sizeOption = optDict["size"], \ - styleOption = optDict["style"], verboseOption = optDict["verbose"], \ - recursiveOption = optDict["recursive"]) + styleOption = optDict["style"], verboseOption = optDict["verbose"], \ + recursiveOption = optDict["recursive"]) if __name__ == "__main__": sys.exit(execute())