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)
dict subclass with keylist/keypath support, normalized I/O operations (base64, csv, ini, json, pickle, plist, query-string, toml, xml, yaml) and many utilities.

python-benedict python-benedict is a dict subclass with keylist/keypath support, I/O shortcuts (base64, csv, ini, json, pickle, plist, query-string, t

Fabio Caccamo 799 Jan 09, 2023
Python collections that are backended by sqlite3 DB and are compatible with the built-in collections

sqlitecollections Python collections that are backended by sqlite3 DB and are compatible with the built-in collections Installation $ pip install git+

Takeshi OSOEKAWA 11 Feb 03, 2022
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 01, 2022
A JSON-friendly data structure which allows both object attributes and dictionary keys and values to be used simultaneously and interchangeably.

A JSON-friendly data structure which allows both object attributes and dictionary keys and values to be used simultaneously and interchangeably.

Peter F 93 Dec 01, 2022
A collection of data structures and algorithms I'm writing while learning

Data Structures and Algorithms: This is a collection of data structures and algorithms that I write while learning the subject Stack: stack.py A stack

Dhravya Shah 1 Jan 09, 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 01, 2023
CLASSIX is a fast and explainable clustering algorithm based on sorting

CLASSIX Fast and explainable clustering based on sorting CLASSIX is a fast and explainable clustering algorithm based on sorting. Here are a few highl

69 Jan 06, 2023
Al-Quran dengan Terjemahan Indonesia

Al-Quran Rofi Al-Quran dengan Terjemahan / Tafsir Jalalayn Instalasi Al-Quran Rofi untuk Archlinux untuk pengguna distro Archlinux dengan paket manage

Nestero 4 Dec 20, 2021
A simple tutorial to use tree-sitter to parse code into ASTs

A simple tutorial to use py-tree-sitter to parse code into ASTs. To understand what is tree-sitter, see https://github.com/tree-sitter/tree-sitter. Tr

Nghi D. Q. Bui 7 Sep 17, 2022
This repository contains code for CTF platform.

CTF-platform Repository for backend of CTF hosting website For starting the project first time : Clone the repo in which you have to work in your syst

Yash Jain 3 Feb 18, 2022
Basic sort and search algorithms written in python.

Basic sort and search algorithms written in python. These were all developed as part of my Computer Science course to demonstrate understanding so they aren't 100% efficent

Ben Jones 0 Dec 14, 2022
Map single-cell transcriptomes to copy number evolutionary trees.

Map single-cell transcriptomes to copy number evolutionary trees. Check out the tutorial for more information. Installation $ pip install scatrex SCA

Computational Biology Group (CBG) 12 Jan 01, 2023
Array is a functional mutable sequence inheriting from Python's built-in list.

funct.Array Array is a functional mutable sequence inheriting from Python's built-in list. Array provides 100+ higher-order methods and more functiona

182 Nov 21, 2022
Google, Facebook, Amazon, Microsoft, Netflix tech interview questions

Algorithm and Data Structures Interview Questions HackerRank | Practice, Tutorials & Interview Preparation Solutions This repository consists of solut

Quan Le 8 Oct 04, 2022
Common sorting algorithims in Python

This a Github Repository with code for my attempts for commonly used sorting algorithims, tested on a list with 3000 randomly generated numbers.

Pratham Prasoon 14 Sep 02, 2021
Programming of a spanning tree algorithm with Python : In depth first with a root node.

ST Algorithm Programming of a spanning tree algorithm with Python : In depth first with a root node. Description This programm reads informations abou

Mathieu Lamon 1 Dec 16, 2021
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 09, 2022
A high-performance immutable mapping type for Python.

immutables An immutable mapping type for Python. The underlying datastructure is a Hash Array Mapped Trie (HAMT) used in Clojure, Scala, Haskell, and

magicstack 996 Jan 02, 2023
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
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