Python tree data library

Overview
https://img.shields.io/pypi/dm/anytree.svg?label=pypi%20downloads https://travis-ci.org/c0fec0de/anytree.svg?branch=master https://readthedocs.org/projects/anytree/badge/?version=2.8.0 https://codeclimate.com/github/c0fec0de/anytree.png

Links

https://github.com/c0fec0de/anytree/raw/devel/docs/static/buymeacoffee.png

Getting started

Usage is simple.

Construction

>> marc = Node("Marc", parent=udo) >>> lian = Node("Lian", parent=marc) >>> dan = Node("Dan", parent=udo) >>> jet = Node("Jet", parent=dan) >>> jan = Node("Jan", parent=dan) >>> joe = Node("Joe", parent=dan)">
>>> from anytree import Node, RenderTree
>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> dan = Node("Dan", parent=udo)
>>> jet = Node("Jet", parent=dan)
>>> jan = Node("Jan", parent=dan)
>>> joe = Node("Joe", parent=dan)

Node

>>> print(udo)
Node('/Udo')
>>> print(joe)
Node('/Udo/Dan/Joe')

Tree

>>> for pre, fill, node in RenderTree(udo):
...     print("%s%s" % (pre, node.name))
Udo
├── Marc
│   └── Lian
└── Dan
    ├── Jet
    ├── Jan
    └── Joe

For details see Node and RenderTree.

Visualization

>>> from anytree.exporter import DotExporter
>>> # graphviz needs to be installed for the next line!
>>> DotExporter(udo).to_picture("udo.png")

https://anytree.readthedocs.io/en/latest/_images/udo.png

The DotExporter can be started at any node and has various formatting hookups:

>>> DotExporter(dan,
...             nodeattrfunc=lambda node: "fixedsize=true, width=1, height=1, shape=diamond",
...             edgeattrfunc=lambda parent, child: "style=bold"
... ).to_picture("dan.png")

https://anytree.readthedocs.io/en/latest/_images/dan.png

There are various other Importers and Exporters.

Manipulation

A second tree:

>> urs = Node("Urs", parent=mary) >>> chris = Node("Chris", parent=mary) >>> marta = Node("Marta", parent=mary) >>> print(RenderTree(mary)) Node('/Mary') ├── Node('/Mary/Urs') ├── Node('/Mary/Chris') └── Node('/Mary/Marta')">
>>> mary = Node("Mary")
>>> urs = Node("Urs", parent=mary)
>>> chris = Node("Chris", parent=mary)
>>> marta = Node("Marta", parent=mary)
>>> print(RenderTree(mary))
Node('/Mary')
├── Node('/Mary/Urs')
├── Node('/Mary/Chris')
└── Node('/Mary/Marta')

Append:

>>> udo.parent = mary
>>> print(RenderTree(mary))
Node('/Mary')
├── Node('/Mary/Urs')
├── Node('/Mary/Chris')
├── Node('/Mary/Marta')
└── Node('/Mary/Udo')
    ├── Node('/Mary/Udo/Marc')
    │   └── Node('/Mary/Udo/Marc/Lian')
    └── Node('/Mary/Udo/Dan')
        ├── Node('/Mary/Udo/Dan/Jet')
        ├── Node('/Mary/Udo/Dan/Jan')
        └── Node('/Mary/Udo/Dan/Joe')

Subtree rendering:

>>> print(RenderTree(marc))
Node('/Mary/Udo/Marc')
└── Node('/Mary/Udo/Marc/Lian')

Cut:

>>> dan.parent = None
>>> print(RenderTree(dan))
Node('/Dan')
├── Node('/Dan/Jet')
├── Node('/Dan/Jan')
└── Node('/Dan/Joe')

Extending any python class to become a tree node

The enitre tree magic is encapsulated by NodeMixin add it as base class and the class becomes a tree node:

>>> from anytree import NodeMixin, RenderTree
>>> class MyBaseClass(object):  # Just an example of a base class
...     foo = 4
>>> class MyClass(MyBaseClass, NodeMixin):  # Add Node feature
...     def __init__(self, name, length, width, parent=None, children=None):
...         super(MyClass, self).__init__()
...         self.name = name
...         self.length = length
...         self.width = width
...         self.parent = parent
...         if children:
...             self.children = children

Just set the parent attribute to reflect the tree relation:

>>> my0 = MyClass('my0', 0, 0)
>>> my1 = MyClass('my1', 1, 0, parent=my0)
>>> my2 = MyClass('my2', 0, 2, parent=my0)
>>> for pre, fill, node in RenderTree(my0):
...     treestr = u"%s%s" % (pre, node.name)
...     print(treestr.ljust(8), node.length, node.width)
my0      0 0
├── my1  1 0
└── my2  0 2

The children can be used likewise:

>>> my0 = MyClass('my0', 0, 0, children=[
...     MyClass('my1', 1, 0),
...     MyClass('my2', 0, 2),
... ])
>>> for pre, fill, node in RenderTree(my0):
...     treestr = u"%s%s" % (pre, node.name)
...     print(treestr.ljust(8), node.length, node.width)
my0      0 0
├── my1  1 0
└── my2  0 2

Documentation

Please see the Documentation for all details.

Installation

To install the anytree module run:

pip install anytree

If you do not have write-permissions to the python installation, try:

pip install anytree --user
Comments
  • Determination of direct children counts

    Determination of direct children counts

    I would like to determine the number of direct children (for non-leaf nodes). I imagine that unique identifiers will be needed then as references for relevant nodes. But the tree iteration is working with the attribute “name” (which might not be unique) so far. Thus I imagine also that the usage of paths would become helpful (so that an auxiliary node attribute can be avoided as long as pointer alternatives would not be applicable).

    Will a configurable formatting become relevant for the display and further data processing of the calculated counts?

    opened by elfring 9
  • Plans to persist tree to file and create a tree from file?

    Plans to persist tree to file and create a tree from file?

    First of all, amazing work in here. I'm planing to use anytree to a huge kind of backtracking implementation. I will need to persist the tree to a file at some point, and of course, get the tree back from a file.

    Are you planning to do it? Is it possible? Should i give it a try and then send the pull request?

    Thank you

    opened by ArgiesDario 9
  • Remove try-except overload to check if some attribute exists

    Remove try-except overload to check if some attribute exists

    In the current implementation, there are some try-except blocks to check if an object has some attribute. To reduce the generated overhead by the exception handling logic, I propose to start using the getattr builtin function with a default value instead.

    This change doesn't provide a big performance improvement, but it's a constant-factor cost removal with no public API implications.

    To check the difference, I build a 1 million node random tree with a height of 25. The logic to build the anynode.AnyNode instances from the tree encoded as raw dictionaries decreased from ~11 seconds to ~8 seconds on my computer (not a big change, but better than nothing 🙂).

    opened by garciparedes 7
  • NodeMixin - TypeError: multiple bases have instance lay-out conflict

    NodeMixin - TypeError: multiple bases have instance lay-out conflict

    Works: 2.4.3 Breaks: 2.6.0

    >>> from munch import Munch
    >>> from anytree import NodeMixin
    >>> class MyClass(Munch, NodeMixin):
    ...     pass
    ... 
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: multiple bases have instance lay-out conflict
    

    Where munch is https://github.com/Infinidat/munch

    Googling around a bit this seems to be about conflicts in C implementations of classes on __foo__ attributes. So I did this:

    >>> [k for k in dir(Munch) if k in dir(NodeMixin)]
    ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
    

    but it didn't make me feel much smarter.

    Does this mean anything to you anytree peeps? I came here because obviously NodeMixin is meant to be mixed in so this feels like a bug rather than just a stupid thing I should not be attempting to do. Especially as it used to work until this version.

    opened by bakert 7
  • RenderTreeGraph(root).to_picture(

    RenderTreeGraph(root).to_picture("tree.png") Not building tree

    getting this error

    FileNotFoundError: [Errno 2] No such file or directory: 'dot'

    While I Run RenderTreeGraph(udo).to_picture("tree.png") Not building tree

    opened by pcakhilnadh 6
  • Resolver.glob returns IndexError where Resolver.get does not

    Resolver.glob returns IndexError where Resolver.get does not

    Example:

    from anytree import Node
    top = Node("top", parent=None)
    sub0 = Node("sub0", parent=top)
    sub0sub0 = Node("sub0sub0", parent=sub0)
    sub0sub1 = Node("sub0sub1", parent=sub0)
    sub1 = Node("sub1", parent=top)
    
    from anytree import Resolver
    r = Resolver('name')
    

    Getting the top node from sub0:

    >>> r.get(sub0, '..')
    Node('/top')
    

    Using glob:

    >>> r.glob(sub0, '..')
    .../anytree/resolver.py in __glob(self, node, parts)
        165     def __glob(self, node, parts):
        166         nodes = []
    --> 167         name = parts[0]
        168         remainder = parts[1:]
        169         # handle relative
    
    IndexError: list index out of range
    
    opened by zegervdv 5
  • remove nodes recursively with a lambda filtering function

    remove nodes recursively with a lambda filtering function

    Hi, I would like to know if it's possible to remove children nodes from a Node with a lambda function criteria, something like:

    outputnode = createnode(inputnode, filter_=lambda n: does_bbox_intersect(n.boundingbox, bounds))

    question 
    opened by DerouineauNicolas 5
  • Use length of children returned from RenderTree.childiter

    Use length of children returned from RenderTree.childiter

    This is just a small fix, but it allows to use the childiter function to not just sort, but also filter nodes when rendering. I need to "hide" some node types when rendering, and thus do this in childiter:

        def childiter(items):
            items = [i for i in items if i.type in lbuild.format.SHOW_NODES]
            return sorted(items, key=lambda item: (item.type, item.name))
    

    However, this renders an additional node line without the node:

        ├── Module(modm:build)   Build System Generators
        │   ├── Module(modm:build:scons)   SCons Build Script Generator
        │   │   ╰── EnumerationOption(info.git) = Disabled in [Disabled, Info, Info+Status]
        ├── Module(modm:cmsis)   ARM CMSIS Support
    

    After this fix:

        ├── Module(modm:build)   Build System Generators
        │   ╰── Module(modm:build:scons)   SCons Build Script Generator
        │       ╰── EnumerationOption(info.git) = Disabled in [Disabled, Info, Info+Status]
        ├── Module(modm:cmsis)   ARM CMSIS Support
    

    cc @c0fec0de

    opened by salkinium 5
  • Works and does not work in an python notebook (anaconda 3)

    Works and does not work in an python notebook (anaconda 3)

    Hallo, Just busy programming an Binary puzzle solver. What works: creating the nodes of the search tree for a solution works fine directly. But if i put the commands in a def ... The nodes are not to be found in command alinea of the notebook. It is probably my missing knowledge of ... How to get the nodes accessibke out of the function .. Help is apreciated

    opened by PKHG 5
  • Enhancement/question: Find lowest common ancestor of two or more nodes?

    Enhancement/question: Find lowest common ancestor of two or more nodes?

    Is there any way to extract lowest common ancestor of nodes without iterating over the ancestor names and finding the common ancestor "manually"? For two nodes it's not too bad, but for more nodes I'm not actually sure how one would accomplish this.

    opened by helske 5
  • Create tree from list of indented strings

    Create tree from list of indented strings

    Hi,

    I am using anytree to generate a tree-view of pytest hooks based on a log file with indented hooks. https://github.com/pytest-dev/pytest/issues/3261

    For that I needed to create a function to convert a list of indented strings to a tree. Apparently another users on stackoverflow have needed it: https://codereview.stackexchange.com/questions/176391/parsing-indented-text-and-inserting-its-data-into-a-tree https://stackoverflow.com/questions/17858404/creating-a-tree-deeply-nested-dict-from-an-indented-text-file-in-python https://stackoverflow.com/questions/32101253/converting-a-string-to-a-tree-structure-in-python?rq=1

    I have created the following script for doing this and it is quite simple: https://github.com/Sup3rGeo/pytest/blob/master/doc/pytesthooks.py

    I believe it makes sense to make this part of anytree as a "indented strings importer".

    So if you agree I would gladly add a pull request for this. Thanks!

    opened by Sup3rGeo 5
  • assert isinstance(data, dict) error

    assert isinstance(data, dict) error

    I am trying to load JSON data formatted as in the documentation and end up with

    Traceback (most recent call last):
      File "d:\dev-pro\searchad\addm123.py", line 10, in <module>
        root = importer.import_(data)
      File "C:\Python310\lib\site-packages\anytree\importer\dictimporter.py", line 38, in import_
        return self.__import(data)
      File "C:\Python310\lib\site-packages\anytree\importer\dictimporter.py", line 47, in __import
        self.__import(child, parent=node)
      File "C:\Python310\lib\site-packages\anytree\importer\dictimporter.py", line 47, in __import
        self.__import(child, parent=node)
      File "C:\Python310\lib\site-packages\anytree\importer\dictimporter.py", line 47, in __import
        self.__import(child, parent=node)
      [Previous line repeated 5 more times]
      File "C:\Python310\lib\site-packages\anytree\importer\dictimporter.py", line 41, in __import
        assert isinstance(data, dict)
    AssertionError
    

    What does it mean, or more precisely - what kind of data can raise it?

    ~~I have empty children entries ("children": []), is this allowed? (just an idea of where the issue could come from)~~ removing "children" entries when empty does not change the issue.

    opened by wsw70 0
  • do you have functionality to count how many time particular branch was added

    do you have functionality to count how many time particular branch was added

    per https://stackoverflow.com/questions/2358045/how-can-i-implement-a-tree-in-python

    do you have functionality to count how many time particular branch was added

    lets say marc = Node("Marc", parent=udo) lian = Node("Lian", parent=marc)

    was added 12 times , then we want to see counts ?

    opened by Sandy4321 0
  • Documentation example for Utilities confusing

    Documentation example for Utilities confusing

    I might misunderstand something, but the example for, e.g., leftsibling in the documentation of anytree/util/__init__.py states two things

    1. It suggest only from anytree import Node
    2. To directly call, e.g., leftsibling(dan)

    For me, both did not work out. I had to

    1. Import the method via from anytree.util import leftsibling
    2. Do a, e.g., print(leftsibling(joe)) in order to get the desired output.
    opened by ArneMeier 0
  • Error in post-attach does not undo the operation

    Error in post-attach does not undo the operation

    Taking the read-only example and implementing checks on post_attach instead of pre_attach, it does not undo the operation that is supposed to be atomic.

    Sample code to replicate the issue below,

    from anytree import NodeMixin
    
    
    class SampleNode(NodeMixin):
        def __init__(self, foo, parent=None):
            super(SampleNode, self).__init__()
            self.foo = foo
            self.readonly = False
            self.parent = parent
        def _post_attach(self, parent):
            if self.root.readonly:
                raise ValueError()
        def _post_detach(self, parent):
            if self.root.readonly:
                raise ValueError()
    
    a = SampleNode("a")
    a0 = SampleNode("a0", parent=a)
    a1 = SampleNode("a1", parent=a)
    a1a = SampleNode("a1a", parent=a1)
    a2 = SampleNode("a2", parent=a)
    
    assert a1.parent == a
    
    a.readonly = True
    with pytest.raises(ValueError):
        a1.parent = a2
    
    a1.parent == a2 # returns True, it should undo the operation
    
    opened by kayjan 0
  • Tree from python nested dictionary

    Tree from python nested dictionary

    Hi there,

    Hi there,

    is there any easy way to create a tree from a python nested dictionary? For instance, I would like to turn: {'tax': {'a':{'c':{}, 'd':{}}, 'b': {'e':{}, 'f':{}}}}

    tax --- a ------- c ------- d --- b ------- e ------- f

    In general, I do not understand what format the json_importer takes as input. Could you please provide some examples? It there any online editor to first manually design the tree with nodes and arrows and then export it in the right format?

    Thank you.

    opened by GiorgioBarnabo 0
  • Performance issues from slow assertion

    Performance issues from slow assertion

    A few days ago I had an issue where anytree operations significantly slowed down over time. cProfile attributed the added time to this assertion. If I'm reading it correctly, it makes adding a child node take O(N) time, where N is the number of its siblings-to-be.

    That N gets rather large in my case. Probably I should refactor my code to avoid that, but I felt I should report it anyway. Setting PYTHONOPTIMIZE=TRUE (to disable assertions) does work as a workaround.

    opened by andrew-vant 0
Releases(2.8.0)
Owner
null
pyprobables is a pure-python library for probabilistic data structures

pyprobables is a pure-python library for probabilistic data structures. The goal is to provide the developer with a pure-python implementation of common probabilistic data-structures to use in their work.

Tyler Barrus 86 Dec 25, 2022
Integrating C Buffer Data Into the instruction of `.text` segment instead of on `.data`, `.rodata` to avoid copy.

gcc-bufdata-integrating2text Integrating C Buffer Data Into the instruction of .text segment instead of on .data, .rodata to avoid copy. Usage In your

Jack Ren 1 Jan 31, 2022
Python library for doing things with Grid-like structures

gridthings Python library for doing things with Grid-like structures Development This project uses poetry for dependency management, pre-commit for li

Matt Kafonek 2 Dec 21, 2021
A Python library for electronic structure pre/post-processing

PyProcar PyProcar is a robust, open-source Python library used for pre- and post-processing of the electronic structure data coming from DFT calculati

Romero Group 124 Dec 7, 2022
This repository is a compilation of important Data Structures and Algorithms based on Python.

Python DSA ?? This repository is a compilation of important Data Structures and Algorithms based on Python. Please make seperate folders for different

Bhavya Verma 27 Oct 29, 2022
This Repository consists of my solutions in Python 3 to various problems in Data Structures and Algorithms

Problems and it's solutions. Problem solving, a great Speed comes with a good Accuracy. The more Accurate you can write code, the more Speed you will

SAMIR PAUL 1.3k Jan 1, 2023
My notes on Data structure and Algos in golang implementation and python

My notes on DS and Algo Table of Contents Arrays LinkedList Trees Types of trees: Tree/Graph Traversal Algorithms Heap Priorty Queue Trie Graphs Graph

Chia Yong Kang 0 Feb 13, 2022
Data Structure With Python

Data-Structure-With-Python- Python programs also include in this repo Stack A stack is a linear data structure that stores items in a Last-In/First-Ou

Sumit Nautiyal 2 Jan 9, 2022
Final Project for Practical Python Programming and Algorithms for Data Analysis

Final Project for Practical Python Programming and Algorithms for Data Analysis (PHW2781L, Summer 2020) Redlining, Race-Exclusive Deed Restriction Lan

Aislyn Schalck 1 Jan 27, 2022
RLStructures is a library to facilitate the implementation of new reinforcement learning algorithms.

RLStructures is a lightweight Python library that provides simple APIs as well as data structures that make as few assumptions as possibl

Facebook Research 262 Nov 18, 2022
An esoteric data type built entirely of NaNs.

NaNsAreNumbers An esoteric data type built entirely of NaNs. Installation pip install nans_are_numbers Explanation A floating point number is just co

Travis Hoppe 72 Jan 1, 2023
This repository is for adding codes of data structures and algorithms, leetCode, hackerrank etc solutions in different languages

DSA-Code-Snippet This repository is for adding codes of data structures and algorithms, leetCode, hackerrank etc solutions in different languages Cont

DSCSRMNCR 3 Oct 22, 2021
Data Structures and algorithms package implementation

Documentation Simple and Easy Package --This is package for enabling basic linear and non-linear data structures and algos-- Data Structures Array Sta

null 1 Oct 30, 2021
One-Stop Destination for codes of all Data Structures & Algorithms

CodingSimplified_GK This repository is aimed at creating a One stop Destination of codes of all Data structures and Algorithms along with basic explai

Geetika Kaushik 21 Sep 26, 2022
This repo is all about different data structures and algorithms..

Data Structure and Algorithm : Want to learn data strutrues and algorithms ??? Then Stop thinking more and start to learn today. This repo will help y

Priyanka Kothari 7 Jul 10, 2022
This repo represents all we learned and are learning in Data Structure course.

DataStructure Journey This repo represents all we learned and are learning in Data Structure course which is based on CLRS book and is being taught by

Aprime Afr (Alireza Afroozi) 3 Jan 22, 2022
Svector (pronounced Swag-tor) provides extension methods to pyrsistent data structures

Svector Svector (pronounced Swag-tor) provides extension methods to pyrsistent data structures. Easily chain your methods confidently with tons of add

James Chua 5 Dec 9, 2022
Webtesting for course Data Structures & Algorithms

Selenium job to automate queries to check last posts of Module Data Structures & Algorithms Web-testing for course Data Structures & Algorithms Struct

null 1 Dec 15, 2021
schemasheets - structuring your data using spreadsheets

schemasheets - structuring your data using spreadsheets Create a data dictionary / schema for your data using simple spreadsheets - no coding required

Linked data Modeling Language 23 Dec 1, 2022