From 60b8ecaf2afb874b733c1c61be26da68df51d989 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 May 2023 10:46:20 +0200 Subject: Adding upstream version 1.6.4. Signed-off-by: Daniel Baumann --- examples/family_tree.py | 65 ++++++++++ examples/folder_tree.py | 207 ++++++++++++++++++++++++++++++++ examples/recursive_dirtree_generator.py | 89 ++++++++++++++ examples/save_tree_2_file.py | 12 ++ 4 files changed, 373 insertions(+) create mode 100644 examples/family_tree.py create mode 100644 examples/folder_tree.py create mode 100644 examples/recursive_dirtree_generator.py create mode 100644 examples/save_tree_2_file.py (limited to 'examples') diff --git a/examples/family_tree.py b/examples/family_tree.py new file mode 100644 index 0000000..fa2293d --- /dev/null +++ b/examples/family_tree.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# Example usage of treelib +# +# Author: chenxm +# +__author__ = "chenxm" + +from treelib import Tree + + +def create_family_tree(): + # Create the family tree + tree = Tree() + tree.create_node("Harry", "harry") # root node + tree.create_node("Jane", "jane", parent="harry") + tree.create_node("Bill", "bill", parent="harry") + tree.create_node("Diane", "diane", parent="jane") + tree.create_node("Mary", "mary", parent="diane") + tree.create_node("Mark", "mark", parent="jane") + return tree + + +def example(desp): + sep = "-" * 20 + "\n" + print(sep + desp) + + +if __name__ == "__main__": + tree = create_family_tree() + + example("Tree of the whole family:") + tree.show(key=lambda x: x.tag, reverse=True, line_type="ascii-em") + + example("All family members in DEPTH mode:") + print(",".join([tree[node].tag for node in tree.expand_tree()])) + + example("All family members (with identifiers) but Diane's sub-family:") + tree.show(idhidden=False, filter=lambda x: x.identifier != "diane") + + example("Let me introduce Diane family only:") + sub_t = tree.subtree("diane") + sub_t.show() + + example("Children of Diane:") + for child in tree.is_branch("diane"): + print(tree[child].tag) + + example("New members join Jill's family:") + new_tree = Tree() + new_tree.create_node("n1", 1) # root node + new_tree.create_node("n2", 2, parent=1) + new_tree.create_node("n3", 3, parent=1) + tree.paste("bill", new_tree) + tree.show() + + example("They leave after a while:") + tree.remove_node(1) + tree.show() + + example("Now Mary moves to live with grandfather Harry:") + tree.move_node("mary", "harry") + tree.show() + + example("A big family for Mark to send message to the oldest Harry:") + print(",".join([tree[node].tag for node in tree.rsearch("mark")])) diff --git a/examples/folder_tree.py b/examples/folder_tree.py new file mode 100644 index 0000000..695d6ef --- /dev/null +++ b/examples/folder_tree.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python +# A file folder scanner contributed by @holger +# +# You can spicify the scanned folder and file pattern by changing rootPath +# and pattern variables +# + +__author__ = "holger" + +from treelib import tree + +import fnmatch +import os +import zlib +import argparse + +DEBUG = 0 +FILECOUNT = 0 +DIRCOUNT = 0 +DIR_ERRORLIST = [] +FILE_ERRORLIST = [] + + +# Time Profiling +PROFILING = 0 +# 0 - nothing +# 1 - time +# 2 - cProfile + +if PROFILING == 1: + import timeit +if PROFILING == 2: + import cProfile + + +parser = argparse.ArgumentParser( + description="Scan the given folder and print its structure in a tree." +) +parser.add_argument("abspath", type=str, help="An absolute path to be scanned.") +parser.add_argument( + "pattern", type=str, help="File name pattern to filtered, e.g. *.pdf" +) + +args = parser.parse_args() +rootPath = args.abspath +pattern = args.pattern + +folder_blacklist = [] + +dir_tree = tree.Tree() +dir_tree.create_node("Root", rootPath) # root node + + +def crc32(data): + data = bytes(data, "UTF-8") + + if DEBUG: + print("++++++ CRC32 ++++++") + print("input: " + str(data)) + print("crc32: " + hex(zlib.crc32(data) & 0xFFFFFFFF)) + print("+++++++++++++++++++") + return hex( + zlib.crc32(data) & 0xFFFFFFFF + ) # crc32 returns a signed value, &-ing it will match py3k + + +parent = rootPath +i = 1 + +# calculating start depth +start_depth = rootPath.count("/") + + +def get_noteid(depth, root, dir): + """get_noteid returns + - depth contains the current depth of the folder hierarchy + - dir contains the current directory + + Function returns a string containing the current depth, the folder name and unique ID build by hashing the + absolute path of the directory. All spaces are replaced by '_' + + _+++ + e.g. 2_Folder_XYZ_1+++ + """ + return ( + str(str(depth) + "_" + dir).replace(" ", "_") + + "+++" + + crc32(os.path.join(root, dir)) + ) + + +# TODO: Verzeichnistiefe pruefen: Was ist mit sowas /mp3/ + + +def get_parentid(current_depth, root, dir): + # special case for the 'root' of the tree + # because we don't want a cryptic root-name + if current_depth == 0: + return root + + # looking for parent directory + # e.g. /home/user1/mp3/folder1/parent_folder/current_folder + # get 'parent_folder' + + search_string = os.path.join(root, dir) + pos2 = search_string.rfind("/") + pos1 = search_string.rfind("/", 0, pos2) + parent_dir = search_string[pos1 + 1 : pos2] # noqa: E203 + parentid = ( + str(current_depth - 1) + + "_" + + parent_dir.replace(" ", "_") + + "+++" + + crc32(root) + ) + return parentid + # TODO: catch error + + +def print_node(dir, node_id, parent_id): + print("#############################") + print("node created") + print(" dir: " + dir) + print(" note_id: " + node_id) + print(" parent: " + parent_id) + + +def crawler(): + global DIRCOUNT + global FILECOUNT + + for root, dirs, files in os.walk(rootPath): + # +++ DIRECTORIES +++ + for dir in dirs: + # calculating current depth + current_depth = os.path.join(root, dir).count("/") - start_depth + + if DEBUG: + print("current: " + os.path.join(root, dir)) + + node_id = get_noteid(current_depth, root, dir) + parent_id = str(get_parentid(current_depth, root, dir)) + + if parent_id == str(None): + DIR_ERRORLIST.append(os.path.join(root, dir)) + + if DEBUG: + print_node(dir, node_id, parent_id) + + # create node + dir_tree.create_node(dir, node_id, parent_id) + DIRCOUNT += 1 + + # +++ FILES +++ + for filename in fnmatch.filter(files, pattern): + if dir in folder_blacklist: + continue + + # calculating current depth + current_depth = os.path.join(root, filename).count("/") - start_depth + + if DEBUG: + print("current: " + os.path.join(root, filename)) + + node_id = get_noteid(current_depth, root, filename) + parent_id = str(get_parentid(current_depth, root, filename)) + + if parent_id == str(None): + FILE_ERRORLIST.append(os.path.join(root, dir)) + + if DEBUG: + print_node(filename, node_id, parent_id) + + # create node + dir_tree.create_node(filename, node_id, parent_id) + FILECOUNT += 1 + + +if PROFILING == 0: + crawler() +if PROFILING == 1: + t1 = timeit.Timer("crawler()", "from __main__ import crawler") + print("time: " + str(t1.timeit(number=1))) +if PROFILING == 2: + cProfile.run("crawler()") + + +print("filecount: " + str(FILECOUNT)) +print("dircount: " + str(DIRCOUNT)) + +if DIR_ERRORLIST: + for item in DIR_ERRORLIST: + print(item) +else: + print("no directory errors") + +print("\n\n\n") + +if FILE_ERRORLIST: + for item in FILE_ERRORLIST: + print(item) +else: + print("no file errors") + +print("nodes: " + str(len(dir_tree.nodes))) + +dir_tree.show() diff --git a/examples/recursive_dirtree_generator.py b/examples/recursive_dirtree_generator.py new file mode 100644 index 0000000..986cd1a --- /dev/null +++ b/examples/recursive_dirtree_generator.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +""" +Example of treelib usage to generate recursive tree of directories. +It could be useful to implement Directory Tree data structure + +2016 samuelsh +""" + +import treelib +import random +import hashlib +from string import digits, letters +import sys + + +MAX_FILES_PER_DIR = 10 + + +def range2(stop): + if sys.version_info[0] < 3: + return xrange(stop) # noqa: F821 + else: + return range(stop) + + +def get_random_string(length): + return "".join(random.choice(digits + letters) for _ in range2(length)) + + +def build_recursive_tree(tree, base, depth, width): + """ + Args: + tree: Tree + base: Node + depth: int + width: int + + Returns: + + """ + if depth >= 0: + depth -= 1 + for i in range2(width): + directory = Directory() + tree.create_node( + "{0}".format(directory.name), + "{0}".format(hashlib.md5(directory.name)), + parent=base.identifier, + data=directory, + ) # node identifier is md5 hash of it's name + dirs_nodes = tree.children(base.identifier) + for dir in dirs_nodes: + newbase = tree.get_node(dir.identifier) + build_recursive_tree(tree, newbase, depth, width) + else: + return + + +class Directory(object): + def __init__(self): + self._name = get_random_string(64) + self._files = [ + File() for _ in range2(MAX_FILES_PER_DIR) + ] # Each directory contains 1000 files + + @property + def name(self): + return self._name + + @property + def files(self): + return self._files + + +class File(object): + def __init__(self): + self._name = get_random_string(64) + + @property + def name(self): + return self._name + + +tree = treelib.Tree() +base = tree.create_node("Root", "root") +build_recursive_tree(tree, base, 2, 10) + +tree.show() diff --git a/examples/save_tree_2_file.py b/examples/save_tree_2_file.py new file mode 100644 index 0000000..3b564f5 --- /dev/null +++ b/examples/save_tree_2_file.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- + +from treelib import Tree + +tree = Tree() +tree.create_node("Harry", "harry") # root node +tree.create_node("Jane", "jane", parent="harry") +tree.create_node("Bill", "bill", parent="harry") +tree.create_node("Diane", "diane", parent="jane") +tree.create_node("Mary", "mary", parent="diane") +tree.create_node("Mark", "mark", parent="jane") +tree.save2file("tree.txt") -- cgit v1.2.3