Исходный код EJIO.utils.component.tree.general_tree

## /utils/component/tree/general_tree.py

from threading import RLock
from typing import Any
from collections.abc import Iterable, Iterator
from ...struct import TreeNode

__all__ = [
    'GeneralTreeNode',
]


[документация] class GeneralTreeNode(TreeNode): """ Узел универсального дерева общего вида (N-арное дерево). Может содержать неограниченное количество дочерних потомков. """ __slots__ = ('_value', '_children', '_lock') def __init__(self, *args: Any) -> None: """ Инициализирует узел дерева. Примеры: GeneralTreeNode("Корень") # Одиночный узел GeneralTreeNode(["Корень", "Child1", "Child2"]) # Из списка/итератора """ self._value: Any = None self._children: list[TreeNode] = [] self._lock: RLock = RLock() if args: # Если передан один аргумент и это итерируемая коллекция (не строка) if len(args) == 1 and isinstance(args[0], Iterable) and not isinstance(args[0], str): iterator: Iterator[Any] = iter(args[0]) try: self._value = next(iterator) for item in iterator: self.add_child(GeneralTreeNode(item)) except StopIteration: pass else: # Если переданы обычные позиционные элементы if len(args) == 1: self._value = args[0] else: self._value = args[0] for item in args[1:]: self.add_child(GeneralTreeNode(item)) @property def value(self) -> Any: """ Возвращает значение текущего узла. :return: Значение текущего узла. """ with self._lock: return self._value @value.setter def value(self, new_value: Any) -> None: """ Устанавливает значение текущего узла. :param new_value: Новое значение. """ with self._lock: self._value = new_value @property def children(self) -> Iterable[TreeNode]: """ Возвращает изолированную потокобезопасную копию списка потомков. :return: Список потомков. """ with self._lock: return list(self._children)
[документация] def add_child(self, child_node: 'GeneralTreeNode') -> 'GeneralTreeNode': """ Потокобезопасно добавляет дочерний узел в дерево. :param child_node: Новый дочерний узел. :return: Новый узел. """ with self._lock: if child_node not in self._children: self._children.append(child_node) return child_node
[документация] def remove_child(self, child_node: 'GeneralTreeNode') -> None: """ Потокобезопасно удаляет дочерний узел из дерева. :param child_node: Дочерний узел. """ with self._lock: if child_node in self._children: self._children.remove(child_node)
[документация] def destroy(self) -> None: """Потокобезопасное каскадное уничтожение N-арного дерева.""" with self._lock: # 1. Рекурсивно запускаем уничтожение для всех дочерних узлов for child in self._children: if child is not None: child.destroy() # 2. Полностью очищаем ссылки на детей текущего узла self._children.clear() # 3. Обнуляем полезную нагрузку (важно, если там лежали тяжелые объекты или виджеты) self._value = None # Зануляем ссылку на замок, завершая деструкцию self._lock = None # type: ignore[assignment]
def __repr__(self) -> str: """ Строковое представление узла. :return: Представление узла в виде строки. """ with self._lock: return f"GeneralTreeNode({self._value!r}, children_count={len(self._children)})"