Node 类
Node 类¶
Node 类提供对 YamlDocument AST 的借用视图,支持树遍历、查询和修改操作。节点通过 doc.node()、doc.find("$.path") 或 doc.walk() 创建。
概述¶
class Node:
"""A node in the YAML AST, backed by a YamlDocument and a path."""
每个 Node 存储对其父 YamlDocument 的引用以及一个路径元组,该元组定位到文档 AST 中的目标节点。当文档被修改或释放时,节点会过期。
构造函数¶
Node.__init__()¶
Node.__init__(document: YamlDocument, path: tuple = ()) -> None
Parameters:
document— 父YamlDocumentpath— 定位到目标节点的路径段(键/索引)元组
属性¶
value¶
获取此节点的标量值。
value -> Any | None
对于非标量节点(映射、序列)返回 None。
root_type¶
获取此节点的类型。
root_type -> str
返回 "scalar"、"mapping"、"sequence"、"null" 之一。
_path¶
定位到文档 AST 中此节点的路径元组。
_path -> tuple
path¶
Get this node's path segments (tuple of keys and indices). The public accessor for logging, error messages, and re-finding a node after it becomes stale.
path -> tuple
children¶
获取此节点的子节点。
children -> list[Node]
对于标量/空节点返回空列表。
parent¶
获取父 Node,如果是根节点则返回 None。
parent -> Node | None
comment¶
获取此节点的注释文本,无注释时返回 None。
comment -> str | None
anchor¶
获取此节点的锚点名称,无锚点时返回 None。
anchor -> str | None
tag¶
获取此节点的 YAML 标签字符串(如 !!str),无标签时返回 None。
tag -> str | None
scalar_style¶
获取标量 style("plain"、"single_quoted"、"double_quoted"、"literal"、"folded"),非标量节点返回 None。
scalar_style -> str | None
flow_style¶
获取 flow style(True = flow {}/[],False = block),非容器节点返回 None。
flow_style -> bool | None
chomping¶
获取 chomping 指示符("strip"、"clip"、"keep"),非标量节点返回 None。
chomping -> str | None
方法¶
find()¶
通过 JSONPath 类路径查找节点。
find(path: str) -> Node | list[Node]
支持的路径语法:
| Pattern | 描述 |
|---|---|
$.key |
根键 |
$.key.subkey |
嵌套键 |
$.arr[0] |
序列索引 |
$.arr[*] |
序列中所有项 |
$..key |
任意深度搜索键 |
$..* |
所有后代节点 |
返回: 精确路径返回单个 Node,通配符/深度扫描查询返回 list[Node]。
find_first()¶
Find the first matching node by JSONPath-like path. Always returns a single Node or None (never a list) — for wildcard paths ([*]), returns the first element.
find_first(path: str) -> Node | None
walk()¶
遍历所有后代节点(深度优先前序)。
walk() -> Iterator[Node]
生成: 节点自身,然后递归所有后代。
filter()¶
通过谓词函数过滤后代节点。
filter(predicate: Callable[[Node], bool]) -> list[Node]
Parameters:
predicate— 接收Node并返回bool的函数
Example:
scalars = root.filter(lambda n: n.root_type == "scalar")
set_value()¶
替换此节点的值,保留其元数据(注释、锚点、标签、样式)。
set_value(value: Any, create_missing: bool = False) -> None
当 create_missing=True 时,路径上缺失的中间映射键会被创建为嵌套映射。索引段缺失仍然会报错。
append()¶
向序列节点追加值。
append(value: Any) -> None
insert()¶
在序列节点的指定索引处插入值。
insert(index: int, value: Any) -> None
delete()¶
移除该节点及其注释。之后节点变为过期。
delete() -> None
rename()¶
重命名此节点的映射键。该节点必须是映射值。
rename(new_key: str) -> None
set_comment()¶
设置(或替换)此节点的注释。standalone=True(默认)时注释输出在节点上方独立行;standalone=False 时注释内联输出在节点之后。
set_comment(text: str, standalone: bool = True) -> None
remove_comment()¶
删除此节点的注释。
remove_comment() -> None
set_anchor()¶
设置(或替换)此节点的锚点。
set_anchor(name: str) -> None
remove_anchor()¶
删除此节点的锚点。
remove_anchor() -> None
set_tag()¶
设置(或替换)此节点的 YAML 标签。"!custom" 生成局部标签,"!!int" 生成主(!!)标签,"!<tag:yaml.org,2002:str>" 生成 verbatim 标签。
set_tag(tag: str) -> None
remove_tag()¶
删除此节点的 YAML 标签。
remove_tag() -> None
set_scalar_style()¶
设置(或替换)此节点的标量 style。非标量节点 no-op。值:"plain"、"single_quoted"、"double_quoted"、"literal"、"folded"。
set_scalar_style(style: str) -> None
set_flow_style()¶
设置(或替换)此节点的 flow style。True 输出 flow({}/[]),False 输出 block。非容器节点 no-op。
set_flow_style(flow: bool) -> None
set_chomping()¶
设置(或替换)此节点的 chomping 指示符。值:"strip"(-)、"clip"(默认)、"keep"(+)。非标量节点 no-op。
set_chomping(chomp: str) -> None
sort_keys()¶
Sort the keys of this mapping node in place. No-op on non-mapping nodes.
sort_keys() -> None
move()¶
Move this subtree to a new path in the same document (copies the subtree to new_path, then removes the source). new_path is an absolute JSONPath.
move(new_path: str) -> None
to_yaml()¶
将此子树序列化为 YAML 字符串。
to_yaml() -> str
copy()¶
深度复制此子树为与文档分离的独立 Python 值(dict/list/scalar)。可用于通过 set_value() 将子树复制粘贴到别处。
copy() -> Any
is_valid()¶
检查父文档是否仍然存活且未被修改。
is_valid() -> bool
release()¶
释放对父文档的引用,将此节点标记为过期。
release() -> None
调用 release() 后,对该节点的任何访问都会发出 RuntimeWarning 并抛出 YamlDocumentError。
特殊方法¶
__repr__()¶
__repr__() -> str
有效节点返回 Node(root_type=<type>, path=<path>),已释放节点返回 Node(released),过期节点返回 Node(invalid)。
__eq__()¶
__eq__(other: object) -> bool
两个 Node 实例在共享相同文档、路径和存活状态时相等。
value_eq()¶
Compare this node's resolved value with another node or Python value. Unlike __eq__ (reference identity), this compares the actual YAML value.
value_eq(other: object) -> bool
过期节点行为¶
过期节点
Node 与文档的修订号绑定,文档编辑后之前获取的 Node 会过期。每次编辑后重新查找节点以继续工作。
节点在以下情况下过期:
- 父
YamlDocument被垃圾回收 - 显式调用
release() - 创建节点后文档被修改
访问过期节点会发出 RuntimeWarning 并抛出 YamlDocumentError:
>>> node = doc.node()
>>> doc.set("$.key", "new_value")
>>> node.value # (1)!
RuntimeWarning: Node is stale: the document was modified after this node was created
YamlDocumentError: document has been modified; re-find the node # (2)!
- 访问过期节点会先触发
RuntimeWarning。 - 然后抛出
YamlDocumentError。请通过doc.node().find(path)重新获取节点。
示例¶
import pyrs_yaml
doc = pyrs_yaml.parse("""
a:
b: 1
c: [2, 3, 4]
d: hello
""")
# 获取根节点
root = doc.node()
print(root.root_type) # "mapping"
# 导航
node = root.find("$.a.c[1]")
print(node.value) # 3
# 遍历
for n in root.walk():
print(n._path, n.root_type)
# 过滤
numbers = root.filter(lambda n: n.root_type == "scalar" and isinstance(n.value, int))
for n in numbers:
print(n._path, n.value) # ('a', 'b') 1, ('a', 'c', 0) 2, ...
# 修改
root.find("$.a.b").set_value(42)
root.find("$.a.c").append(5)
root.find("$.d").rename("greeting")
root.find("$.a.c[0]").delete()
print(doc.to_yaml())
# a:
# b: 42
# c: [3, 4, 5]
# greeting: hello