コンテンツにスキップ

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 — 親 YamlDocument
  • path — ターゲットノードに移動するパスセグメント(キー/インデックス)のタプル

プロパティ

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]

スカラー/Null ノードの場合は空のリストを返します。

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 Description
$.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:

  • predicateNode を受け取り 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>" はバーベイタムタグになります。

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

2 つの 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 はドキュメントのリビジョンに結び付けられています。ドキュメントが編集されるとリビジョンが増加し、以前に取得したノードは期限切れになり、YamlDocumentError をスローします。編集後はノードを再取得してください。

ノードは次の場合に期限切れになります:

  • 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)!
  1. 期限切れのノードにアクセスすると、最初に RuntimeWarning がトリガーされます。
  2. 次に YamlDocumentError が発生します。doc.node().find(path) でノードを再取得してください。

import pyrs_yaml

doc = pyrs_yaml.parse("""
a:
  b: 1
  c: [2, 3, 4]
d: hello
""")

# Get root node
root = doc.node()
print(root.root_type)  # "mapping"

# Navigate
node = root.find("$.a.c[1]")
print(node.value)  # 3

# Walk
for n in root.walk():
    print(n._path, n.root_type)

# Filter
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, ...

# Mutate
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