Parsing and writing YAML¶
PALSParserPy represents a parsed document as a tree of YAMLNode values. Each
node knows whether it is a map, a sequence, or a scalar, and supports the
standard Python collection idioms. The owning YAMLTree frees the underlying C
tree automatically when it is garbage-collected, so you never manage memory by
hand.
Making the functions available¶
Everything documented here is exported from the top-level package, so one import brings the whole API into scope:
import palsparserpy as pp
root = pp.parse_file("config.pals.yaml")
Every tree operation is also a method on the node itself, so pp.is_map(node)
and node.is_map() are the same call written two ways. The rest of this guide
uses whichever reads better in context.
Reading¶
Parse from a file or from a string. Both return a YAMLNode pointing at the
tree root:
Function |
Description |
|---|---|
|
Parse a YAML file from disk. |
|
Parse YAML from a string. |
|
Create a new, empty MAP tree to build up from scratch. |
|
Parse a PALS lattice file and return original, combined, expanded, full_expanded and adjunct views. |
root = pp.parse_file("config.pals.yaml")
# or
root = pp.parse_string("""
server:
host: localhost
port: 8080
features:
- auth
- logging
""")
A malformed document raises PALSParseError, whose message carries the offending
line and column.
parse_and_expand_pals is PALS-specific: it returns a Lattices value holding
five independent tree views (original, combined, expanded,
full_expanded, adjunct), each freed on its own when garbage-collected.
Querying the tree¶
Use these to inspect a node’s kind, walk the tree, and read out its structure. None of them modify the document.
Kind checks¶
Every node is exactly one of map, sequence, or scalar:
Function |
Description |
|---|---|
|
|
|
|
|
|
Reading scalar values¶
Convert a scalar leaf node to the Python type you want:
Expression |
Description |
|---|---|
|
The scalar value as a |
|
The scalar parsed as an |
|
The scalar parsed as a |
|
The scalar parsed as a |
host = root["server"]["host"].value # 'localhost'
port = root["server"]["port"].as_int() # 8080
int(node) and float(node) work as well. There is deliberately no
bool(node) conversion: a node is always truthy, so if node: asks whether you
have a node rather than what it says.
Building and editing¶
Create an empty document and add maps, sequences, and scalars to it. Each builder returns the newly created child node:
Expression |
Description |
|---|---|
|
Add a scalar child. |
|
Add an empty map child. |
|
Add an empty sequence child. |
|
Set (or create) a scalar child under |
|
Set or replace a node’s scalar value in place. |
|
Set or replace the key a node is stored under. |
|
Remove a node and all its descendants. |
|
An independent deep copy of |
|
Overwrite |
|
Copy all children of |
Pass key for map children and omit it for sequence elements. index selects
the 0-based position among the existing children; it defaults to None, which
appends at the end, so you usually leave it out.
root = pp.create_empty_tree()
server = root.add_map(key="server")
server["host"] = "localhost"
server["port"] = "8080"
features = root.add_sequence(key="features")
features.add_scalar("auth")
features.add_scalar("logging")
The deep_copy_node / deep_copy_children pair works across different trees,
so you can graft one subtree onto another.
Writing¶
Serialize a node to a string or straight to disk:
Expression |
Description |
|---|---|
|
The node and its descendants as a YAML |
|
Write the whole tree containing |
text = pp.to_yaml_string(root) # YAML as a str -- print(root) does the same
pp.write_yaml(root, "out.pals.yaml")
Both take an exclude argument naming keys to leave out, which is handy for
printing or saving a large lattice without the bulky subtrees. Every MAP entry
with a matching key is dropped, at any depth, together with its subtree; the tree
in memory is not modified.
print(pp.to_yaml_string(root, exclude=["FloorP", "ReferenceP"]))
print(pp.to_yaml_string(root, exclude="FloorP")) # a single key needs no list
pp.write_yaml(root, "out.pals.yaml", exclude=["FloorP", "ReferenceP"])
See the API Reference for the full list of functions and their signatures.