Metadata-Version: 2.4
Name: verysimpletree
Version: 2.0.2
Summary: lightweight tree data structure
Author: Alex Gorji
Author-email: Alex Gorji <aligorji@hotmail.com>
License-Expression: MIT
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.11
Project-URL: Homepage, https://gitlab.com/alexgorji/verysimpletree.git
Project-URL: Repository, https://gitlab.com/alexgorji/verysimpletree.git
Description-Content-Type: text/markdown

An abstract lightweight tree class for managing tree structures.

Requires Python 3.11 or newer.

## Typed list representations

`TreeNodeListRepresentation[ValueT]` describes `[value, child, ...]` recursively.
`create_tree_from_list()` accepts the same value type as
`get_list_representation()`, including scalar values for a single attribute:

```python
from verysimpletree.tree import TreeNodeListRepresentation

representation: TreeNodeListRepresentation[int] = [
    10,
    [3, [2, [1], [1]], [1]],
    [7, [4], [3]],
]
# For a concrete Tree subclass whose constructor accepts value:
tree = MyTree.create_tree_from_list(representation, "value")
```

For multiple attributes, each node value is a list of attribute values, ordered
to match `represented_attribute_names`. Child representations must be lists.
The value type checks the representation's contents; it does not verify that
attribute names or values match the subclass constructor.

## Development

Use a current uv release; development and package builds are verified with
uv 0.13.1. Older uv releases may fail to extract archives used by the current
build backend.

```sh
uv sync --locked
uv run pytest
uv run mypy verysimpletree --strict
uv run ruff check .
uv run ruff format --check .
uv build
```

## GitLab CI and releases

The root `.gitlab-ci.yml` runs lint and strict type checks, tests Python
3.11-3.14, and builds a wheel and source distribution. Merge requests, branch
pushes, and tags run validation; duplicate branch pipelines are skipped for
pushes with an open merge request. Jobs explicitly select their Python
interpreter rather than relying on the development `.python-version` pin.
JUnit test reports and built distributions are retained as job artifacts.

To enable publishing on GitLab:

1. Use a runner that supports the configured Python Docker images.
2. Protect release tags matching `v*` and restrict who can create them.
3. Add `UV_PUBLISH_TOKEN` as a masked, protected CI/CD variable containing a
   PyPI API token scoped to the `verysimpletree` project.
4. Set the version in `pyproject.toml`, update `uv.lock`, and commit the changes.
5. Push a matching stable version tag, such as `v2.0.1`.

Publishing runs automatically only for protected stable version tags, after
checks, tests, and the build pass. The tag must match the package version.
The publish job uploads the build job's artifacts without rebuilding them.
Branch and merge request pipelines never publish.

## Structural mutations

- `parent.add_child(child)` appends a detached child and returns it.
- `parent.insert_child(index, child)` inserts a detached child and returns it.
  Indices follow `list.insert()`: negative indices count from the end, and
  out-of-range indices are clamped.
- `parent.remove(child)` detaches a direct child.
- `parent.replace_child(old, new, index=0)` replaces a direct child in place.
  `old` can also be a predicate; `index` selects among matching children.
  Replacing a child with itself is a no-op. The method returns `None`.

Children must have no parent before attachment. Self-insertion, ancestor
insertion, and attaching an already-parented child raise `ValueError`.
Subclass child-type checks still apply. Invalid attachments leave the tree
unchanged. To move a child, remove it from its old parent first:

```python
old_parent.remove(child)
new_parent.add_child(child)
```

Mutation methods update parent pointers, leaf status, and affected traversal,
leaf, and ancestor-path caches.

## Subclass contract

Implement `_check_child_to_be_added()` to validate allowed child types, raising
an exception for invalid children without mutating the tree. Structural checks
are shared by `add_child()`, `insert_child()`, and `replace_child()` through
`_validate_child_attachment()`.

Inherited structural operations use `_children` as their authoritative child
storage. Overriding `get_children()` alone does not provide alternative-storage
support. Subclasses using `_children` should reuse the mutation methods rather
than assign parent pointers or edit child lists directly.

`get_children()` still returns the mutable backing list for compatibility.
Direct edits bypass validation and cache invalidation.
