Code Monkey home page Code Monkey logo

treelib's Introduction

treelib

Tree implementation in python: simple for you to use.

Build Status Code style: black Documentation Status Status Latest PyV PyPI download month GitHub contributors

PRs Welcome GitHub pull-requests GitHub pull-requests closed

Quick Start

pip install -U treelib

Documentation

For installation, APIs and examples, see http://treelib.readthedocs.io/en/latest/

Code Style

treelib complies with black formatter and specific flake8 validations. Before creating a pull request, please make sure you pass the local validation with scripts/flake8.sh.

Contributors

Thank you all, committers.

treelib's People

Contributors

1xch avatar arhoads avatar bebesparkelsparkel avatar brettbates avatar c0fec0de avatar caesar0301 avatar ctengiz avatar dbrgn avatar evandrocoan avatar gaoyukid avatar hbast avatar hollowman6 avatar ilya-spy avatar leonardbinet avatar liamlundy avatar miguellissimo avatar mondwan avatar msindhuja29 avatar natim avatar neverfox avatar ordahan avatar pg avatar redoubts avatar samuelsh avatar savioratharv avatar suizokukan avatar tpflueger avatar tsoj avatar umanshahzad avatar ycd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

treelib's Issues

About setup instructions

I am very new to Python but I have a lot of programming experience. So please excuse me for my ignorance. I downloaded the zip file and renamed the extracted folder as pyTree. Then I placed it in my project folder. In my code, I have to do

from pyTree.node import Node
from pyTree.tree import Tree

If I put from pyTree import tree, node, it fails. Any idea?

Possibility of Dependency trees

I am looking to solve a problem I have about building a dependency tree for tickets that we need to execute in a specified order. I came across your library while looking to solve this issue, but wanted to know if it would be possible using this library.

Here is what I have:

TICKET-1
├── TICKET-2
    └── TICKET-3
└── TICKET-5
    ├── TICKET-6
    └── TICKET-3

Note that TICKET-2 and TICKET-5 both depend on TICKET-3 being executed first.

I wanted each child node to be a tree in itself, but it doesn't look like that is possible. And if I try to add TICKET-3 to the parent TICKET-5 after I have added it to TICKET-2 I get a DuplicateNode exception.

Am I going beyond what this library was designed to do? Or is there something I can workaround to get it working?

I liked your library because I could use the .expand_tree function to get my list in reverse order.

tree.to_json() method not working

Hi,
I saw in the documentation that the Tree object has a method to_json(). However, when I create a Tree object and try calling this method, I get the error: "'Tree' object has no attribute 'to_json'"

Am I missing something?

Thanks

Tree and custom Node

Hello,

I need to add custom data on Node Class and use the classic Tree Class for managing the data structure.

Take the family as an example, I would like to pack age, sex of the family member into a Node instead of knowing their name only.

Currently, it seems there is no api for me to inject attributes into Node or force Tree to create a custom Node Class instead of the classic one.

Although I can create a new Tree class and a new Node class to solve the above problem, I am wondering is it possible for me to achieve the same goal without creating new class?

expand_tree and deleting the result gives key error

I may submit my 'answer' to this issue but i don't think it is the correct solution, so wanted to discuss with you first.

example:

t = Tree()
t.create_node("x","x")
for node in t.expand_tree(): t.remove_node(node)

I solved it for now in the expand_tree generator after the first yield by doing:

if self.size() == 0:        
    queue = []            
else:                          
    queue = [self[i] for i in self[nid].fpointer if filter(self[i])]  

To stop it trying to access self[nid] that doesn't exist. (i am only getting this issue with trees of size 1, probably due to using two yields. Where I think you may want to be using one??

I think there is probably a better solution though. Any thoughts?

AttributeError: 'str' object has no attribute 'decode'

python3.4, OSX 10.10

>>> from treelib import Tree, Node
>>> tree = Tree()
>>> tree.create_node("Harry", "harry")
>>> tree.create_node("Jane", "jane", parent="harry")
>>> tree.show()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.4/site-packages/treelib/tree.py", line 517, in show
    func=print)
  File "/usr/local/lib/python3.4/site-packages/treelib/tree.py", line 560, in _print_backend
    if idhidden \
AttributeError: 'str' object has no attribute 'decode'

Issues with `__getitem__`

Today I stumbled across a problem when using treelib with Django.

In Django templates, when you use the . operator, it queries an object's __getitem__ before it looks at the attributes. This is used to access dictionary keys using the dot.

In the case of a treelib Tree object, this makes it impossible to directly access tree.root, because Django first does tree['root'], which returns None.

The question is whether the direct lookup functionality is too much of a convenience to get rid of it (explicit is better than implicit).

If you think the functionality should be kept, there could be a disable_getitem (or similar) parameter in the constructor that would be checked in __getitem__. If it is set, __getitem__ would then delegate the functionality to getattr(self, key).

What do you think? If you agree about the last part, I could create a pull request.

Serious issue with subtrees!

Hi guys,

I was trying your library out, it looks great.
Yet I believe there is a design issue with how you implemented the subtrees. Right now a tree is defined by a dictionary of nodes and the id of the root node, the hierarchy being expressed in the bpointer and fpointer of the individual node instances.

What happens when I create a subtree? A new tree object is created, that has a subset of the nodes of the original tree. As you mention the copy is shallow, so the nodes themselves are not deep copied. This is useful, because in principle it allows to operate on the subtrees influencing the structure of the main tree, and vice-versa.

But what if I first create a subtree out of a tree, then add a node either to this subtree or to the original tree? What happens is that the fpointers and bpointers of the nodes in question will be updated to include the new node, but just the nodes dictionary of either the tree or subtree will be updated.

So when for example the function _print_backend(...) gets invoked on the tree if I modified the subtree, or on the subtree if I modified the tree, it will throw an error at the line:

queue = [self[i] for i in self[nid].fpointer if filter(self[i])]

because there will be identifiers that are in the list of fpointers but NOT in the nodes of the tree/subtree.

How would you go about fixing that?

Have a great day and thanks,

Francesco

Unjsonify Function

Hey guys, I noticed that treelib has a to_json function, but not an unjsonify function that inputs a JSON string and builds the original tree as the output. I decided to go ahead and write an unjsonify function, which I thought might be useful:

import json                                                                                                              
from treelib import Node, Tree
from collections import Hashable

# takes in a jsonified tree and returns the correct tree structure
def unjsonify(jsonTree):
    def giveKey(d):
        return d.keys()[0]
    def unjsonifyHelper(node, subtree):
        for childStruct in subtree[node]['children']: # childStruct is immutable element if base case, else dict
            if type(childStruct) == list: childStruct = tuple(childStruct) # tuples in original tree
            if isinstance(childStruct, Hashable): # base case
                newTree.create_node(childStruct, childStruct, parent=node)
            else:
                childNode = giveKey(childStruct)
                newTree.create_node(childNode, childNode, parent=node)
                unjsonifyHelper(childNode, childStruct)
    jsonTree = json.loads(jsonTree)
    root = giveKey(jsonTree)
    newTree = Tree()
    newTree.create_node(root, root)
    unjsonifyHelper(root, jsonTree)
    return newTree

# simple test
tree = Tree()
tree.create_node('home', 'home')
tree.create_node('phone', 'phone', parent='home')
tree.create_node('laptop', 'laptop', parent='home')
tree.create_node('screen', 'screen', parent='laptop')
tree.create_node(19, 19, parent='home')
tree.create_node((1,2), (1,2), parent='screen')
j = tree.to_json()
unjsonify(j).show()   

There's some stuff to note here about the code:

  1. The to_json function as it's written only preserves keys and not values in the tree. Would you guys be interested in a custom to_json function that saves both keys and values (which json.dumps currently doesn't do right now)?
  2. I'm not 100% sure why, but json.dumps converts tuples into lists. Because treelib doesn't allow mutable elements to be keys, I've decided to turn lists back into tuples before I determine if an element is hashable or not (and would be a leaf if it's hashable), since there couldn't have been any lists as keys in the original tree anyway.

Please let me know what you guys think!

JSON Output

Would be cool to have an option for JSON output, which I can then use in D3.js. I'm trying to figure it out... Something like this... formatting added for visibility but probably unnecessary

{
   "name": "node1", 
   "children": [
       {
           "name": "node1a", 
           "children": [
               {
                  "name": "node1a1"
               },
               {
                  "name": "node1a2"
               }
            ]
       },
       {
          "name": "node1b"
       }
   ]
}

provide node data in dictionary (and json)

Hi,
I've recently been using treelib/pytree in a larger project. We mainly use the .json() functionality to return subtrees that are parsable into menus. Recently one developer wanted to also access other node data in the menu data structure. I noticed that the .data attribute is dropped in dictionary construction. I method patched a class instance to provide this. I'm wondering if you would consider adding it to the code.

def _to_dict(self, nid=None, key=None, reverse=False):
    """transform self into a dict"""

    nid = self.root if (nid is None) else nid
    #print('adding',nid,self[nid].data)
    tree_dict = {self[nid].tag: { "children":[] , "data":self[nid].data } }

    if self[nid].expanded:
        queue = [self[i] for i in self[nid].fpointer]
        key = (lambda x: x) if (key is None) else key
        queue.sort(key=key, reverse=reverse)

        for elem in queue:
            tree_dict[self[nid].tag]["children"].append(
                self.to_dict(elem.identifier))
        if tree_dict[self[nid].tag]["children"] == []:
            tree_dict = {self[nid].tag: { "data":self[nid].data } }
        return tree_dict

i have a error

from pyTree.Tree import Tree

----> 1 t = Tree()

F:\winpython27\python-2.7.5.amd64\Lib\site-packages\pyTree\Tree.pyc in init(self, data, children)
22 @param children: sub node(s) of Tree, could be None, child (single) or children (multiple)
23 '''
---> 24 self.data = data
25 self.__children = []
26 self.__parent=None #private parent attribute

F:\winpython27\python-2.7.5.amd64\Lib\site-packages\pyTree\Tree.pyc in setattr(self, name, value)
54 raise AttributeError("To add children, please use addChild or addChildren method.")
55 else:
---> 56 super().setattr(name, value)
57
58 def str(self, _args, *_kwargs):

TypeError: super() takes at least 1 argument (0 given)

what?

bug on tree.subtree() + tree.level()

Hi all,

It seems level() cannnot work with subtree().

Below is the illustration. I copy the example from README.md.

You can see level() get an error since it is going to find "jane" which is a node from the old 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("George", "george", parent = "diane")

>>> tree.create_node("Mary", "mary", parent = "diane")

>>> tree.create_node("Jill", "jill", parent = "george")

>>> tree.create_node("Mark", "mark", parent = "jane")

>>> tree.show()
Harry
├── Bill
└── Jane
    ├── Diane
    │   ├── George
    │   │   └── Jill
    │   └── Mary
    └── Mark
>>> a = tree.subtree("diane")
>>> a.show()
Diane
├── George
│   └── Jill
└── Mary
>>> a.level("george")
Traceback (most recent call last):
  File "", line 1, in 
  File "build/bdist.linux-x86_64/egg/treelib/tree.py", line 289, in level
  File "build/bdist.linux-x86_64/egg/treelib/tree.py", line 479, in rsearch
  File "build/bdist.linux-x86_64/egg/treelib/tree.py", line 80, in __getitem__
treelib.tree.NodeIDAbsentError: Node 'jane' is not in the tree
>>> 

move_node() allows you to create loops

Example:

>>> from treelib import Tree
>>> tree = Tree()
>>> tree.create_node('a', 'a')
>>> tree.create_node('b', 'b', parent='a')
>>> tree.show()
a
└── b
>>> tree.move_node('a', 'b')
>>> tree.show()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/mg/src/tilaajavastuu/bolagsfakta/server/env/lib/python3.5/site-packages/treelib/tree.py", line 626, in show
    key, reverse, line_type, data_property, func=write)
  File "/home/mg/src/tilaajavastuu/bolagsfakta/server/env/lib/python3.5/site-packages/treelib/tree.py", line 205, in __print_backend
    filter, key, reverse, line_type, data_property, func, iflast)
...
  File "/home/mg/src/tilaajavastuu/bolagsfakta/server/env/lib/python3.5/site-packages/treelib/tree.py", line 198, in <listcomp>
    queue = [self[i] for i in self[nid].fpointer if filter(self[i])]
RecursionError: maximum recursion depth exceeded

Support integers as identifiers

For some reasons integers don't work as identifiers:

>>> from googletools.vendor.pyTree.node import Node
>>> from googletools.vendor.pyTree.tree import Tree
>>> tree = Tree()
>>> tree.create_node('spam', 1)
<googletools.vendor.pyTree.node.Node object at 0xe175d0>
>>> tree.create_node('ham', 2, parent=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "googletools/vendor/pyTree/tree.py", line 72, in create_node
    self.add_node(node, parent)
  File "googletools/vendor/pyTree/tree.py", line 64, in add_node
    self.__update_fpointer(parent, node.identifier, _ADD)
  File "googletools/vendor/pyTree/tree.py", line 241, in __update_fpointer
    self[nid].update_fpointer(identifier, mode)
AttributeError: 'NoneType' object has no attribute 'update_fpointer'

Would be great if you could change that.

Filter with the '==' operator

Great library, to start with. I really find it useful.

One quick doubt. Is there a straightforward way to search for nodes with a specific tag instead of by nid?

Either using tree.show() or tree.expand_tree() with a filter, everything works fine if one uses something like:

nodes = tree.expand_tree('root', filter=lambda x: x.tag != 'ART')
for node in nodes: print(node)

But if we use the equality operator, nothing is returned.

nodes = ctree.expand_tree('root', filter=lambda x: x.tag == 'ART')
for node in nodes: print(node)

Looking at the source code, I can kind of understand why. But is there a canonical way of searching nodes by tag instead of by nid? The idea is to easily get all nodes with a given tag.

Thanks for the great library.

Restrictions for fork of treelib

Hi!

I've forked treelib and make many significant changes into library (inherit Tree from OrderedDict directly, simplify some methods, drop Python 2 support etc). So, do you have any restrictions for fork in case it will be released as separate lib (ttree) on PyPI? All copyrights and license will be remained.

I don't want to merge my changes into treelib, because of its very subjective. If some of my decisions make sense in treelib, I am ready to create some PRs.

Thank you!

p.s. Link to fork

Show with Data

Hey can we modify show function in order to show tree with data some thing like in to_json(with_data=True)

tree.show(with_data = True)

OUTPUT

Harry
├── Bill {"data":{"weight":"54KG","height":"5.6"}}
└── Jane{"data":{"weight":"64KG","height":"5.2"}}
    ├── Diane{"data":{"weight":"62KG","height":"4.9"}}
    │   └── Mary{"data":{"weight":"61KG","height":"5.5"}}
    └── Mark{"data":{"weight":"59KG","height":"5.1"}}

treelib.tree.NodeIDAbsentError: Parent node '...' is not in the tree

treelib.tree.NodeIDAbsentError: Parent node '...' is not in the tree

Running this code:

from treelib import Node, Tree


class Apple():
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return self.name

harryApple = Apple("Harry")
addonApple = Apple("Addons")

tree      = Tree()
harryNode = Node( harryApple )  # root node
addonNode = Node( addonApple )

tree.add_node( harryNode )
tree.add_node( addonNode, parent=harryNode )
tree.show()

Results in:

Traceback (most recent call last):
  File "D:\User\Dropbox\Applications\SoftwareVersioning\ComputerScienceGraduation\Semester20171\treelib\test.py", line 19, in <module>
    tree.add_node( addonNode, parent=harryNode )
  File "D:\User\Dropbox\Applications\SoftwareVersioning\ComputerScienceGraduation\Semester20171\treelib\treelib\tree.py", line 279, in add_node
    "is not in the tree" % parent)
treelib.tree.NodeIDAbsentError: Parent node 'Node(tag=<__main__.Apple instance at 0x0250DF58>, identifier='7b806e1e-17c5-11e7-95e9-6c626d784ee9', data=None)' is not in the tree

I added the node harry, but why it is not in the tree?

How to use this with mysql ?

Hi,
I need to work with mysql database but i can not know how to query insert, delete , show data.
The examples is only run on console. So, how to interact on mysql database with django? I am a newbie on django.
Thank you.

order problem

now children display order is not according to the insert order but the node.tag order .
is there any way to change the order parameter?

not change the node or branch order when create a tree

hi,

Your program works very well. But I have another related problem to ask for you.

I create a tree. The script is the following:
tree = Tree()
tree.create_node("HH", "hh")
tree.create_node("JJ", "jj", parent='hh')
tree.create_node("AA", "aa", parent='hh')
tree.show()
The tree will show like this:
HH
--- AA
--- JJ

But, Node JJ should be created before AA, as the code expects. I expect that the tree branching order is consistent with the order that the node is created.
The expected result is:
HH
--- JJ
--- AA

Then, how could I achieve that? Do your program provide this function?

Thanks a lot for your help.

Documentation says method name is `tree.all_nodes_iter()`, but it is actually `itr` without an `e`

The documentation says the tree class has a method named tree.all_nodes_iter(), but the method name is actually itr without an e

http://treelib.readthedocs.io/en/latest/pyapi.html#tree-objects
http://treelib.readthedocs.io/en/latest/pyapi.html#tree.all_nodes_iter

Attempts to call all_nodes_iter() raise AttributeError
Recommend creating an alias so that Tree.all_nodes_iter and Tree.all_nodes_itr are references to the same function object.

Inside the tree class just write all_nodes_itr = all_nodes_iter

An alias is a better solution than correcting the documentation, because -- I assure you -- users will sometimes type "iter," out of habit, instead of writing "itr." You can prevent alot of interpreter errors from occurring by making an alias.

Modifying the identifier of a node is not working properly

Hello,

tree = Tree()
tree.create_node("Harry", "harry")
tree.create_node("Jane", "jane", parent="harry")
n= tree.get_node("jane")
n.identifier=("xyz")

tree.get_node("xyz") ### returns None 
tree.get_node("jane") ### return a Node object whose identifier is "xyz" ! 

Hope you can address this,

Thnaks.

I find two questions in the codes.

When I try to store files and folders info in the tree structure, the file name or folder name assignment identifier, but there may have same files or folders in different paths, i think this may be a problem, at least when try to store folders or URLs in the tree structure.
For example:
Root
|___ home
| |___ dev
| |___ mysql
| |___ python
|___ etc
|___ dev
| |___ mysql
Another problem is that I need to query a depth for a specific number of all nodes of the identifier ,i find that there is no such interface. So I codeing this function myself. I think it is necessary to add this interface, if there is a need I can paste my code.eg:
Root
|___ home
| |___ dev
| |___ mysql
| |___ python
|___ etc
|___ dev
| |___ mysql
give the layer=3,return a list [ dev,mysql]
Finally, I would like to say that your program is very good.

Problem when the specified parent contains spaces

Using the following code, I would have expected the third node to be a child of the second node. Due to the space in the second node's identifier, this doesn't work.

Code:

t = Tree()
t.create_node('1','1')
t.create_node('2','2 2','1')
t.create_node('3','3','2 2')
t.show()

Output:

1 [1]
('+', '2 [22]')

Should this be expected behavior, or can it be improved? (through sanitizing of ids or through using the Node object as the 'parent' parameter itself)

Read only?

Is there a way to make a tree read only?

I want to build a tree of data and let users lose on it. Since they are users, I want to make sure that they cannot change what is in the tree… Whether they want to or not!

Is this possible?

tree.leaves return different type of elements

  1. tree.leaves() returns the nodes list.
  2. while tree.leaves(tree.identifier) return a list of identifier.

this behavior is puzzling.

def leaves(self, root=None):
        """Get leaves of the whole tree of a subtree."""
        leaves = []
        if root is None:
            for node in self._nodes.values():
                if node.is_leaf():
                    leaves.append(node)
        else:
            for node in self.expand_tree(root):
                if self[node].is_leaf():
                    leaves.append(node)
        return leaves

tree.show prints a byte literal

for example,

>>> from treelib import Node, 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.show()
b'Harry\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Bill\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Jane\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Diane\n    \xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Mary\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Mark\n'

To fix this, replace this line

print(self.reader.encode('utf-8'))

with:
print(self.reader)

Implement object pickling

I am using libtree to implement an API. The API configuration is stored in a text file and parsed into a libtree. In order to avoid doing this for every request, I am trying to save the tree in memcached, but this can not be done since libtree is not pickable.

Could it be possible to add this feature to libtree? According to the pickle documentation this does not seem too difficult, but unfortunately I have no experience adding pickling interfaces.

readme typos

Thanks for merging in those things. Will try to think up a better way of giving leaves (it worked for what i needed at the time :) )

Two minor typo's in the readme. It should be:

Remove a node link its children to its parent (root is not allowed)

t.link_past_node(nid)

instead of:

Remove a node link its children to its parent (root is not allowd)

r.link_past_node(nid)

Documentation

In read the docs it implies that most tree functions need a nid but I have found that some of them do not require the nid like Tree.leaves

I think that those cases should be noted in the docs stating that they use the root of the tree that they are called on.

TypeError: not all arguments converted during string formatting

http://treelib.readthedocs.io/en/latest/examples.html

it defined that it can use Object, but i pass tuple, it has error

tree.create_node((0,0),(0,0))
Traceback (most recent call last):
File "", line 1, in
File "C:\Python27\lib\site-packages\treelib\node.py", line 142, in repr
"tag=%r" % self.tag,
TypeError: not all arguments converted during string formatting

tree = Tree()
#create root
tree.create_node((0,0), "root")
result = [aa[0]]
previousnode = (0,0)

#create root
... tree.create_node((0,0), "root")
Traceback (most recent call last):
File "", line 2, in
File "C:\Python27\lib\site-packages\treelib\node.py", line 142, in repr
"tag=%r" % self.tag,
TypeError: not all arguments converted during string formatting

How to display tree properly?

Hi, I have started using treelib and I like it very much! However, I cannot display the tree properly in python 3.4, for example I get this
b'Harry'
b'\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Bill'
b'\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Jane'
b' \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Diane'
b' \xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Mary'
b' \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Mark'

instead of this on python 2.7

Harry
├── Bill
└── Jane
├── Diane
│ └── Mary
└── Mark

Is there anyway to fix this?

Load tree from json

Is there any way to restaure, load,or parse a tree from json, string or file?

After all we already have those methods for to save an existing tree object, it would be useful.

Thanks for your work

Dot export crashes when node tag is not a string

When creating a tree which does not hold string objects the export to the dot file format crashes.
See the minimal working example below

import treelib
from treelib.plugins import export_to_dot

t = treelib.Tree()
t.create_node([1,2,3])
export_to_dot(t, 'mwe.dot')

Shallow pastes to multiple trees breaks level/depth

sent1 = Tree()
S1 = sent1.create_node('S')

sent2 = Tree()
S2 = sent2.create_node('S')

left = Tree()
NP = left.create_node('NP')

right = ParseTree()
VP = right.create_node('VP')

sent1.paste(S1.identifier, left)
sent1.paste(S1.identifier, right)
sent2.paste(S2.identifier, left)
sent2.paste(S2.identifier, right)

sent1.level(NP.identifier)
KeyError                                  Traceback (most recent call last)
~/.pyenv/versions/ling571/lib/python3.4/site-packages/treelib/tree.py in __getitem__(self, key)
    101         try:
--> 102             return self._nodes[key]
    103         except KeyError:

KeyError: '8dae1426-ff23-11e7-9421-34363bd0ba28'

During handling of the above exception, another exception occurred:

NodeIDAbsentError                         Traceback (most recent call last)
<ipython-input-416-169f4a8c57e3> in <module>()
----> 1 sent1.level(NP.identifier)

~/.pyenv/versions/ling571/lib/python3.4/site-packages/treelib/tree.py in level(self, nid, filter)
    424         exclusive nodes.
    425         """
--> 426         return len([n for n in self.rsearch(nid, filter)])-1
    427 
    428     def link_past_node(self, nid):

~/.pyenv/versions/ling571/lib/python3.4/site-packages/treelib/tree.py in <listcomp>(.0)
    424         exclusive nodes.
    425         """
--> 426         return len([n for n in self.rsearch(nid, filter)])-1
    427 
    428     def link_past_node(self, nid):

~/.pyenv/versions/ling571/lib/python3.4/site-packages/treelib/tree.py in rsearch(self, nid, filter)
    627         current = nid
    628         while current is not None:
--> 629             if filter(self[current]):
    630                 yield current
    631             # subtree() hasn't update the bpointer

~/.pyenv/versions/ling571/lib/python3.4/site-packages/treelib/tree.py in __getitem__(self, key)
    102             return self._nodes[key]
    103         except KeyError:
--> 104             raise NodeIDAbsentError("Node '%s' is not in the tree" % key)
    105 
    106     def __len__(self):

NodeIDAbsentError: Node '8dae1426-ff23-11e7-9421-34363bd0ba28' is not in the tree

During rsearch it appears to follow a back-pointer into the other copy. This makes sense, I suppose, given that the bpointer is set during pasting (and the last paste dominates). I'm not sure what the solution might be without storing multiple bpointers and then filtering them against nodes in the tree.

Unknown children created from node is created on subtree

from treelib import Tree, Node

tree = Tree()
tree.create_node(tag="first", data={})
sub0 = tree.subtree(tree.root)

root_id = sub0.root
root_node = sub0.get_node(root_id)

sub0.create_node(tag='second', parent=root_id)
sub0.create_node(tag='third', parent=root_id)

tree.show()

Error:
/Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/williamrusnack/Documents/nesting/test2.py
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/treelib/tree.py", line 109, in getitem
return self._nodes[key]
KeyError: '8eee35be-f09a-11e5-9ae0-34363b5dfe74'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Users/williamrusnack/Documents/nesting/test2.py", line 13, in
tree.show()
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/treelib/tree.py", line 615, in show
key, reverse, line_type, func=write)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/treelib/tree.py", line 187, in print_backend
queue = [self[i] for i in self[nid].fpointer if filter(self[i])]
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/treelib/tree.py", line 187, in
queue = [self[i] for i in self[nid].fpointer if filter(self[i])]
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/treelib/tree.py", line 111, in __getitem

raise NodeIDAbsentError("Node '%s' is not in the tree" % key)
treelib.tree.NodeIDAbsentError: Node '8eee35be-f09a-11e5-9ae0-34363b5dfe74' is not in the tree

Process finished with exit code 1

How to order by data?

Is there a good way to order the dictionary by a property found in the data properties?

I am trying to order the children of each node according to the volume field in the data dict

 "Root": {
            "data": {
                "volume": 88829.0,
                "display_name": "Root",
            },
            "children": [
                {
                    "softw": {
                        "data": {
                            "volume": 82229.0,
                            "display_name": "software",
                        },
                        "children": [
                            {
                                "best": {
                                    "data": {
                                        "volume": 139.0,
                                        "display_name": "best",
                                    },
                                    "children": [
                                        {
                                            "songwrit_139": {
                                                "data": {
                                                    "volume": 139.0,
                                                    "display_name": "songwrite", 
                                                }
                                            }
                                        }
                                    ]
                                }
                            },

test code coverage

Hey Xiaming
Could it be possible for you to enable the use of code coverage for the library with Coveralls?
I don't know if you know it, but with it you can check how much of your code is being covered with your tests.

It is for free for open source projects and you can use your github account to use it.

Check it here: https://coveralls.io/

Cheers

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.