StrictYAML

raw JSON →
1.7.3 verified Tue May 12 auth: no python install: verified

StrictYAML is a type-safe YAML parser and validator for Python, focusing on a restricted, unambiguous subset of the YAML specification. It prioritizes a clear API, strict validation, human-readable exceptions, and the ability to round-trip (read, modify, and write) YAML while preserving comments. The current version is 1.7.3, with an active but irregular release cadence of patches and minor versions.

pip install strictyaml
error MarkedYAMLError: Expected 'Str()' but got 'Map()'
cause The YAML document provides a mapping (object) where the StrictYAML schema expects a string, indicating a type mismatch during validation.
fix
Adjust the YAML content's structure or a specific value's type to conform to the defined schema, or modify the schema to accept the given YAML structure/type.
from strictyaml import load, Map, Str

yaml_string_correct = "user_name: Alice"
schema = Map({"user_name": Str()})
loaded_yaml = load(yaml_string_correct, schema)

# Error case example:
# yaml_string_error = "user_name: {first: Alice, last: Smith}"
# loaded_yaml = load(yaml_string_error, schema) # This would raise the error
error KeyError: 'non_existent_key' not found in document
cause An attempt was made to access a key within the parsed StrictYAML document that does not exist, either because it's missing from the YAML input or not defined in the schema.
fix
Ensure the key exists in the YAML document and is allowed by the schema. Use get() with a default value to handle optional keys safely, or define the key in the schema using Optional().
from strictyaml import load, Map, Str, Int, Optional

yaml_string = "name: Bob\nage: 30"
schema = Map({"name": Str(), "age": Int(), Optional("email"): Str()})
doc = load(yaml_string, schema)

# Correct access:
print(doc["name"].data)

# Accessing an optional key safely:
email_node = doc.get("email")
if email_node:
    print(email_node.data)
else:
    print("Email not provided.")

# Error case example:
# print(doc["phone"].data) # Assuming 'phone' is not in schema or YAML
error MarkedYAMLError: while scanning an unquoted scalar
cause The input YAML string contains a scalar value that is not properly quoted or contains special characters (like a colon followed by a space) that require quoting, leading to a low-level parsing error.
fix
Correct the YAML syntax by ensuring that strings containing special characters are enclosed in single or double quotes, and that indentation and other YAML syntax rules are followed.
from strictyaml import load, Map, Str

# Corrected YAML: quoting a string with a colon
yaml_string_correct = "message: 'This contains a colon: and other stuff'"
schema = Map({"message": Str()})
loaded_yaml = load(yaml_string_correct, schema)

# Error case example (unquoted string with special characters):
# yaml_string_error = "message: This contains a colon: and other stuff"
# loaded_yaml = load(yaml_string_error, schema) # This would raise the error
error TypeError: load() missing 1 required positional argument: 'yaml_string'
cause The `strictyaml.load()` function was called without providing the necessary `yaml_string` argument, which is the YAML content to be parsed.
fix
Always provide the YAML content as the first argument to the strictyaml.load() function.
from strictyaml import load, Map, Str

# Correct usage with yaml_string
yaml_string = "item: Apple"
schema = Map({"item": Str()})
doc = load(yaml_string, schema)

# Error case example:
# doc = load(schema=schema) # This would raise the TypeError
breaking In version 0.5, the default parse result of `load()` changed from directly returning a Python dict/list to returning a `YAML` object. To get the dict/list representation, users must now access the `.data` attribute of the returned object.
fix Access the `.data` attribute (e.g., `load(yaml_str, schema).data`) to retrieve the Python dict/list.
gotcha StrictYAML intentionally refuses implicit typing (e.g., '42' is a string by default). Values are only type-cast according to an explicitly provided schema (e.g., `Int()`). This prevents common YAML surprises and security issues, but means it behaves differently from other YAML parsers.
fix Always define a `schema` using `strictyaml` validators (e.g., `Int()`, `Float()`, `Bool()`) if you require typed data beyond strings, lists, and dicts.
gotcha StrictYAML parses only a restricted subset of the full YAML 1.2 specification. Features like duplicate keys, explicit tags, anchors/references, and flow-style YAML (embedded JSON) are intentionally disallowed or unsupported to enhance security and readability.
fix Adhere to the StrictYAML subset of YAML. Avoid features like `!!str` explicit tags, `&anchor` references, and compact JSON-like syntax within your YAML files.
gotcha StrictYAML, by design, only parses YAML from strings, not directly from file paths or file-like objects. This is a deliberate choice for explicitness and security.
fix Read the content of your YAML file into a string first, then pass that string to `strictyaml.load()`. Example: `with open('config.yaml', 'r') as f: yaml_string = f.read(); doc = load(yaml_string, schema)`.
gotcha When no schema is provided to `strictyaml.load()`, all scalar values (numbers, booleans, dates) are interpreted as strings. Automatic type inference, common in other YAML libraries, is disabled.
fix Provide a schema (`strictyaml.load(yaml_str, schema)`) with appropriate validators (`Str()`, `Int()`, `Bool()`, `Datetime()`, etc.) to enable type conversion.
python os / libc status wheel install import disk
3.10 alpine (musl) wheel - 0.07s 19.7M
3.10 alpine (musl) - - 0.08s 19.7M
3.10 slim (glibc) wheel 1.6s 0.05s 20M
3.10 slim (glibc) - - 0.06s 20M
3.11 alpine (musl) wheel - 0.12s 22.1M
3.11 alpine (musl) - - 0.14s 22.1M
3.11 slim (glibc) wheel 1.8s 0.10s 23M
3.11 slim (glibc) - - 0.10s 23M
3.12 alpine (musl) wheel - 0.09s 13.8M
3.12 alpine (musl) - - 0.10s 13.8M
3.12 slim (glibc) wheel 1.6s 0.09s 14M
3.12 slim (glibc) - - 0.10s 14M
3.13 alpine (musl) wheel - 0.09s 13.6M
3.13 alpine (musl) - - 0.10s 13.5M
3.13 slim (glibc) wheel 1.6s 0.09s 14M
3.13 slim (glibc) - - 0.10s 14M
3.9 alpine (musl) wheel - 0.08s 19.2M
3.9 alpine (musl) - - 0.09s 19.2M
3.9 slim (glibc) wheel 1.9s 0.08s 20M
3.9 slim (glibc) - - 0.07s 20M

This quickstart demonstrates how to parse a YAML string using a schema for type validation and casting, access parsed data, modify values, and handle potential YAMLError exceptions. It also shows the default behavior of parsing without a schema where all scalar values are treated as strings.

from strictyaml import load, Map, Str, Int, Seq, YAMLError

yaml_snippet = """
name: Ford Prefect
age: 42
possessions:
  - Towel
  - 'No. 2 pencil'
"""

# Define a schema for validation and type casting
schema = Map({"name": Str(), "age": Int(), "possessions": Seq(Str())})

try:
    # Load YAML with the defined schema
    document = load(yaml_snippet, schema)
    print("Parsed data:", document.data)
    print(f"Name (string): {document['name'].data}")
    print(f"Age (int): {document['age'].data}")
    print(f"First possession: {document['possessions'][0].data}")

    # Modify a value and output YAML (comments are preserved)
    document['age'] = 43
    print("\nModified YAML:\n", document.as_yaml())

except YAMLError as e:
    print(f"YAML Error: {e}")

# Example without a schema (all scalars are strings by default)
yaml_no_schema = load(yaml_snippet)
print("\nParsed without schema (age is string):", yaml_no_schema.data['age'])