Source code for app.util.models.hierarchical

# SPDX-License-Identifier: GPLv3-or-later
# Copyright © 2025 pygaindalf Rui Pinheiro

import weakref

from typing import cast as typing_cast
from typing import override

from pydantic import Field, field_validator

from ..helpers.weakref import WeakRef
from ..mixins import HierarchicalProtocol, NamedProtocol, ParentType
from .hierarchical_root import HierarchicalRootModel


[docs] class HierarchicalModel(HierarchicalRootModel): instance_parent_weakref: WeakRef[ParentType] | None = Field( default=None, repr=False, exclude=True, alias="instance_parent", description="Parent of this instance in the hierarchy. Can be None if this is a root instance.", ) @field_validator("instance_parent_weakref", mode="after") @classmethod def _validate_instance_parent(cls, obj: object | None) -> weakref.ref[ParentType] | None: if obj is None: return None _obj = obj if isinstance(obj, weakref.ref): _obj = obj() if _obj is None: return None else: obj = weakref.ref(obj) if not isinstance(_obj, (HierarchicalProtocol | NamedProtocol)): msg = f"Expected HierarchicalProtocol | NamedProtocol | None, got {type(obj)}" raise TypeError(msg) cls._do_validate_instance_parent(_obj) return typing_cast("weakref.ref", obj) @classmethod def _do_validate_instance_parent(cls, parent: ParentType) -> None: pass @property @override def instance_parent(self) -> ParentType | None: parent = getattr(self, "instance_parent_weakref", None) if parent is None: return None return parent() if isinstance(parent, weakref.ref) else parent @instance_parent.setter def instance_parent(self, new_parent: ParentType | None) -> None: self.instance_parent_weakref = weakref.ref(new_parent) if new_parent is not None else None