abstracttree


Nameabstracttree JSON
Version 0.2.0 PyPI version JSON
download
home_pageNone
SummaryAbstract base classes for tree data structures
upload_time2025-07-20 22:38:29
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseNone
keywords tree datastructure hierarchy taxonomy newick graphviz mermaid
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            Trees are a common data structure and there are many different ways to implement them.
This package provides a common interface to access and operate on these objects.

## Installing ##
 
Use [pip](https://pip.pypa.io/en/stable/getting-started/) to install abstracttree:

```sh
$ pip install --upgrade abstracttree
```

## Usage ##

You can start by implementing the mixins below. Otherwise, a lot of trees are supported out of the box.

### Mixins ###

```mermaid
graph TD;
Tree[Tree];
MutableTree[MutableTree];
DownTree[DownTree];
Tree[Tree];
MutableTree[MutableTree];
MutableDownTree[MutableDownTree];
MutableTree[MutableTree];
BinaryDownTree[BinaryDownTree];
BinaryTree[BinaryTree];
Tree-->MutableTree;
DownTree-->Tree;
DownTree-->MutableDownTree;
MutableDownTree-->MutableTree;
DownTree-->BinaryDownTree;
BinaryDownTree-->BinaryTree;
Tree-->BinaryTree;
```

| ABC               | Inherits from             | Abstract Methods                | Mixin Methods                                                                                                                                                  |
|-------------------|---------------------------|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `DownTree`        |                           | `children`                      | `nodes`, `nodes.preorder()`, `nodes.postorder()`, `nodes.levelorder()`, `descendants`, `leaves`, `levels`, `levels.zigzag()`, `is_leaf`, `transform()`,  `nid` |
| `Tree`            | `DownTree`                | `parent`                        | `root`, `is_root`, `ancestors`, `path`, `siblings`                                                                                                             |
| `MutableDownTree` | `DownTree`                | `add_child()`, `remove_child()` | `add_children()`                                                                                                                                               |
| `MutableTree`     | `MutableDownTree`, `Tree` |                                 | `detach()`                                                                                                                                                     |
| `BinaryDownTree`  | `DownTree`                | `left_child`, `right_child`     | `children`, `nodes.inorder()`, `descendants.inorder()`                                                                                                         |
| `BinaryTree`      | `BinaryDownTree`, `Tree`  |                                 |                                                                                                                                                                |

For example, to create a simple tree with children (but no parent):

```python
from abstracttree import DownTree, print_tree

class MyTree(DownTree):
    def __init__(self, value, children=()):
        self.value = value
        self._children = children
    
    def __str__(self):
        return "MyTree " + str(self.value)

    @property
    def children(self):
        return self._children

tree = MyTree(1, children=[MyTree(2), MyTree(3)])
print_tree(tree)

# This generates the following output:
# MyTree 1
# ├─ MyTree 2
# └─ MyTree 3
```

### Generics ##

Unfortunately, not all trees inherit from the mixins above. Yet, some objects still have treelike behaviour.
Therefore, AbstractTree provides support for a slightly weaker protocol.

The following objects are `TreeLike`:
- All objects that support `obj.children` and `obj.parent`.
- Builtins classes `pathlib.Path` and `zipfile.Path`.
- Third party tree classes from [anytree](https://github.com/c0fec0de/anytree), [bigtree](https://github.com/kayjan/bigtree), [itertree](https://github.com/BR1py/itertree) and [littletree](https://github.com/lverweijen/littletree).

The following objects are `DownTreeLike`:
- All objects that support `obj.children`.
- Anything implementing `DownTree`.
- Recursive collections like lists, tuples, sets, dicts. This can be useful when dealing with json-data.

This can be tested using `isinstance`:

```python
isinstance(Path(r"C:\\Windows\System"), TreeLike)  # True
isinstance(range(100), DownTreeLike)  # True
isinstance(range(100), TreeLike)  # False
isinstance(5, DownTreeLike)  # False
isinstance("some text", DownTreeLike)  # False (even though it might be considered a collection by python).
```

### Basic functions

On downtreelikes:
```python
children(node)  # Children of node
label(node)  # String representation of node (similar to str, but output excludes parent and children)
nid(node)  # Address of node (similar to id, but supports delegates).
eqv(node1, node2)  # Check if 2 nodes have the same identity (similar to is, but supports delegates)
```

Additionally, on treelikes:
```python
parent(node)  # Parent of node or None if node is root of its own tree.
root(node)  # Find root of this tree.
```

Examples:
```python
>>> from abstracttree import *
>>> children([1, 2, 3])
[1, 2, 3]
>>> children({"name": "Philip", "children": ["Pete", "Mariam"]})
[MappingItem(key="name", value="Philip"), MappingItem(key="children", value=["Pete", "Miriam"])]
>>> parent(Path(r"C:\\Windows\System"))
Path(r"C:\\Windows")
>>> label(Path(r"C:\\Windows\System"))
"System"
>>> eqv(Path(r"C:\\Windows\System"), Path(r"C:\\Windows\System"))
True
>>> eqv([1, 2, 3], [1, 2, 3])
False
```

### Iterators

On downtreelikes:
```python
nodes(tree)  # Iterate through all nodes in tree (in no particular order).
descendants(node)  # Children and grand-(grand-*)-children of node.
leaves(root)  # Leaves reachable from root
```

If you want to iterate though the nodes in a specific order, use:
```python
preorder(node)  # Nodes in preorder (root comes first).
postorder(node)  # Nodes in postorder (root comes last).
levelorder(node)  # Nodes near the root come before later nodes.
```
These will return tuples with (node, item). The item-object contains information about the depth of the node.

Additionally, on treelikes:
```python
ancestors(node)  # Ancestors of node.
path(node)  # Path from root to this node including this node.
siblings(node)  # Siblings of node
```

### Adapters ###

To upgrade a `TreeLike` to a full `Tree` use `as_tree`.

```python
path_tree = as_tree(pathlib.Path("my_documents"))  # Optionally pass `children`, `parent`, `label`.

# Iterate over all its descendants
for node in path_tree.descendants:
    path_obj = node.value  # Get back a Path-object from TreeAdapter
```

There is also `TreeAdapter` to help with classes that are very different.

### Exporting ###

Export to various formats
```python
print_tree(tree)

# If matplotlib is installed
plot_tree(tree)

# These may require graphviz or Pillow to be installed.
to_dot(tree)
to_mermaid(tree)
to_latex(tree)
to_reportlab(tree)

to_image(Path('.'), "filetree.png", how="dot")
to_image(DownTree, "tree_hierarchy.svg", how="mermaid")
to_pillow(tree).show()
```

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "abstracttree",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "tree, datastructure, hierarchy, taxonomy, newick, graphviz, mermaid",
    "author": null,
    "author_email": "lverweijen <lauwerund@gmail.com>",
    "download_url": null,
    "platform": null,
    "description": "Trees are a common data structure and there are many different ways to implement them.\r\nThis package provides a common interface to access and operate on these objects.\r\n\r\n## Installing ##\r\n \r\nUse [pip](https://pip.pypa.io/en/stable/getting-started/) to install abstracttree:\r\n\r\n```sh\r\n$ pip install --upgrade abstracttree\r\n```\r\n\r\n## Usage ##\r\n\r\nYou can start by implementing the mixins below. Otherwise, a lot of trees are supported out of the box.\r\n\r\n### Mixins ###\r\n\r\n```mermaid\r\ngraph TD;\r\nTree[Tree];\r\nMutableTree[MutableTree];\r\nDownTree[DownTree];\r\nTree[Tree];\r\nMutableTree[MutableTree];\r\nMutableDownTree[MutableDownTree];\r\nMutableTree[MutableTree];\r\nBinaryDownTree[BinaryDownTree];\r\nBinaryTree[BinaryTree];\r\nTree-->MutableTree;\r\nDownTree-->Tree;\r\nDownTree-->MutableDownTree;\r\nMutableDownTree-->MutableTree;\r\nDownTree-->BinaryDownTree;\r\nBinaryDownTree-->BinaryTree;\r\nTree-->BinaryTree;\r\n```\r\n\r\n| ABC               | Inherits from             | Abstract Methods                | Mixin Methods                                                                                                                                                  |\r\n|-------------------|---------------------------|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|\r\n| `DownTree`        |                           | `children`                      | `nodes`, `nodes.preorder()`, `nodes.postorder()`, `nodes.levelorder()`, `descendants`, `leaves`, `levels`, `levels.zigzag()`, `is_leaf`, `transform()`,  `nid` |\r\n| `Tree`            | `DownTree`                | `parent`                        | `root`, `is_root`, `ancestors`, `path`, `siblings`                                                                                                             |\r\n| `MutableDownTree` | `DownTree`                | `add_child()`, `remove_child()` | `add_children()`                                                                                                                                               |\r\n| `MutableTree`     | `MutableDownTree`, `Tree` |                                 | `detach()`                                                                                                                                                     |\r\n| `BinaryDownTree`  | `DownTree`                | `left_child`, `right_child`     | `children`, `nodes.inorder()`, `descendants.inorder()`                                                                                                         |\r\n| `BinaryTree`      | `BinaryDownTree`, `Tree`  |                                 |                                                                                                                                                                |\r\n\r\nFor example, to create a simple tree with children (but no parent):\r\n\r\n```python\r\nfrom abstracttree import DownTree, print_tree\r\n\r\nclass MyTree(DownTree):\r\n    def __init__(self, value, children=()):\r\n        self.value = value\r\n        self._children = children\r\n    \r\n    def __str__(self):\r\n        return \"MyTree \" + str(self.value)\r\n\r\n    @property\r\n    def children(self):\r\n        return self._children\r\n\r\ntree = MyTree(1, children=[MyTree(2), MyTree(3)])\r\nprint_tree(tree)\r\n\r\n# This generates the following output:\r\n# MyTree 1\r\n# \u251c\u2500 MyTree 2\r\n# \u2514\u2500 MyTree 3\r\n```\r\n\r\n### Generics ##\r\n\r\nUnfortunately, not all trees inherit from the mixins above. Yet, some objects still have treelike behaviour.\r\nTherefore, AbstractTree provides support for a slightly weaker protocol.\r\n\r\nThe following objects are `TreeLike`:\r\n- All objects that support `obj.children` and `obj.parent`.\r\n- Builtins classes `pathlib.Path` and `zipfile.Path`.\r\n- Third party tree classes from [anytree](https://github.com/c0fec0de/anytree), [bigtree](https://github.com/kayjan/bigtree), [itertree](https://github.com/BR1py/itertree) and [littletree](https://github.com/lverweijen/littletree).\r\n\r\nThe following objects are `DownTreeLike`:\r\n- All objects that support `obj.children`.\r\n- Anything implementing `DownTree`.\r\n- Recursive collections like lists, tuples, sets, dicts. This can be useful when dealing with json-data.\r\n\r\nThis can be tested using `isinstance`:\r\n\r\n```python\r\nisinstance(Path(r\"C:\\\\Windows\\System\"), TreeLike)  # True\r\nisinstance(range(100), DownTreeLike)  # True\r\nisinstance(range(100), TreeLike)  # False\r\nisinstance(5, DownTreeLike)  # False\r\nisinstance(\"some text\", DownTreeLike)  # False (even though it might be considered a collection by python).\r\n```\r\n\r\n### Basic functions\r\n\r\nOn downtreelikes:\r\n```python\r\nchildren(node)  # Children of node\r\nlabel(node)  # String representation of node (similar to str, but output excludes parent and children)\r\nnid(node)  # Address of node (similar to id, but supports delegates).\r\neqv(node1, node2)  # Check if 2 nodes have the same identity (similar to is, but supports delegates)\r\n```\r\n\r\nAdditionally, on treelikes:\r\n```python\r\nparent(node)  # Parent of node or None if node is root of its own tree.\r\nroot(node)  # Find root of this tree.\r\n```\r\n\r\nExamples:\r\n```python\r\n>>> from abstracttree import *\r\n>>> children([1, 2, 3])\r\n[1, 2, 3]\r\n>>> children({\"name\": \"Philip\", \"children\": [\"Pete\", \"Mariam\"]})\r\n[MappingItem(key=\"name\", value=\"Philip\"), MappingItem(key=\"children\", value=[\"Pete\", \"Miriam\"])]\r\n>>> parent(Path(r\"C:\\\\Windows\\System\"))\r\nPath(r\"C:\\\\Windows\")\r\n>>> label(Path(r\"C:\\\\Windows\\System\"))\r\n\"System\"\r\n>>> eqv(Path(r\"C:\\\\Windows\\System\"), Path(r\"C:\\\\Windows\\System\"))\r\nTrue\r\n>>> eqv([1, 2, 3], [1, 2, 3])\r\nFalse\r\n```\r\n\r\n### Iterators\r\n\r\nOn downtreelikes:\r\n```python\r\nnodes(tree)  # Iterate through all nodes in tree (in no particular order).\r\ndescendants(node)  # Children and grand-(grand-*)-children of node.\r\nleaves(root)  # Leaves reachable from root\r\n```\r\n\r\nIf you want to iterate though the nodes in a specific order, use:\r\n```python\r\npreorder(node)  # Nodes in preorder (root comes first).\r\npostorder(node)  # Nodes in postorder (root comes last).\r\nlevelorder(node)  # Nodes near the root come before later nodes.\r\n```\r\nThese will return tuples with (node, item). The item-object contains information about the depth of the node.\r\n\r\nAdditionally, on treelikes:\r\n```python\r\nancestors(node)  # Ancestors of node.\r\npath(node)  # Path from root to this node including this node.\r\nsiblings(node)  # Siblings of node\r\n```\r\n\r\n### Adapters ###\r\n\r\nTo upgrade a `TreeLike` to a full `Tree` use `as_tree`.\r\n\r\n```python\r\npath_tree = as_tree(pathlib.Path(\"my_documents\"))  # Optionally pass `children`, `parent`, `label`.\r\n\r\n# Iterate over all its descendants\r\nfor node in path_tree.descendants:\r\n    path_obj = node.value  # Get back a Path-object from TreeAdapter\r\n```\r\n\r\nThere is also `TreeAdapter` to help with classes that are very different.\r\n\r\n### Exporting ###\r\n\r\nExport to various formats\r\n```python\r\nprint_tree(tree)\r\n\r\n# If matplotlib is installed\r\nplot_tree(tree)\r\n\r\n# These may require graphviz or Pillow to be installed.\r\nto_dot(tree)\r\nto_mermaid(tree)\r\nto_latex(tree)\r\nto_reportlab(tree)\r\n\r\nto_image(Path('.'), \"filetree.png\", how=\"dot\")\r\nto_image(DownTree, \"tree_hierarchy.svg\", how=\"mermaid\")\r\nto_pillow(tree).show()\r\n```\r\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Abstract base classes for tree data structures",
    "version": "0.2.0",
    "project_urls": {
        "Changelog": "https://lverweijen.github.io/AbstractTree/CHANGES.html",
        "Documentation": "https://lverweijen.github.io/AbstractTree/",
        "Homepage": "https://github.com/lverweijen/abstracttree",
        "Issues": "https://github.com/lverweijen/abstracttree/issues",
        "Repository": "https://github.com/lverweijen/abstracttree"
    },
    "split_keywords": [
        "tree",
        " datastructure",
        " hierarchy",
        " taxonomy",
        " newick",
        " graphviz",
        " mermaid"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "a68f392e1498a08e150ccdf481bc739e7e3758c0ef43b3d17baab2cf2d4ecbf2",
                "md5": "d13bcbf69223d134365fdfe07f0bb893",
                "sha256": "dc2343d5d312bdfe07624ebcaccc4ffff937147787f0837f3a8df2a88d96be23"
            },
            "downloads": -1,
            "filename": "abstracttree-0.2.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d13bcbf69223d134365fdfe07f0bb893",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 27758,
            "upload_time": "2025-07-20T22:38:29",
            "upload_time_iso_8601": "2025-07-20T22:38:29.827995Z",
            "url": "https://files.pythonhosted.org/packages/a6/8f/392e1498a08e150ccdf481bc739e7e3758c0ef43b3d17baab2cf2d4ecbf2/abstracttree-0.2.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-20 22:38:29",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "lverweijen",
    "github_project": "abstracttree",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "abstracttree"
}
        
Elapsed time: 0.40110s