1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
|
# Copyright (c) 2017-2026 Juancarlo AƱez (apalala@gmail.com)
# SPDX-License-Identifier: BSD-4-Clause
from __future__ import annotations
import functools
import weakref
from collections.abc import Iterable, Mapping
from typing import Any
from .basenode import BaseNode, tatsudataclass
__all__ = ['Node', 'tatsudataclass']
from ..util.deprecate import deprecated
@tatsudataclass
class Node(BaseNode):
def __init__(self, ast: Any = None, **kwargs: Any):
super().__init__(ast=ast, **kwargs)
self.__parent_ref: weakref.ref[Node] | None = ( # pyright: ignore[reportRedeclaration]
None
)
def __post_init__(self):
super().__post_init__()
self.__parent_ref: weakref.ref[Node] | None = None
@property
def parent(self) -> Node | None:
ref = self.__parent_ref
if ref is None:
return None
else:
return ref()
@property
def comments(self) -> Any:
deprecated(replacement=None)(self.comments)
return None
@property
def text(self) -> str | None:
pi = self.parseinfo
if pi and hasattr(pi.tokenizer, "text"):
return pi.tokenizer.text[pi.pos : pi.endpos]
return None
@property
def line(self) -> int | None:
return self.parseinfo.line if self.parseinfo else None
@property
def path(self) -> tuple[Node, ...]:
ancestors: list[Node] = [self]
parent = self.parent
while parent is not None:
ancestors.append(parent)
parent = parent.parent
return tuple(reversed(ancestors))
def children(self) -> tuple[Node, ...]:
return self._cached_children
def children_list(self) -> list[Node]:
return list(self._cached_children)
@functools.cached_property
def _cached_children(self) -> tuple[Node, ...]:
def dfs(obj: Any) -> Iterable[Node]:
match obj:
case Node() as node:
node.__parent_ref = weakref.ref(self)
yield node
case Mapping() as map:
for name, value in map.items():
if name.startswith("_"):
continue
if value is None:
continue
yield from dfs(value)
case (list() | tuple()) as seq:
for item in seq:
yield from dfs(item)
case _:
pass
return tuple(dfs(self.__pub__()))
|