mrkeyoor.com_
Tue 22 Sept 18:50 UTC
PyPIUtilsupdated 20 Sept 2026

strictyaml review

StrictYAML 1.7.3 imported in 0.20 seconds after our 0.2-second install and occupied 2 MB across 3 packages. It reads a deliberately limited YAML dialect, then validates and converts values with Python schemas such as `Map`, `Seq`, `Int`, and `Enum`. Without a schema, every scalar remains text. Normal loading refuses duplicate keys, flow collections, tags, anchors, and aliases. Returned nodes retain comments and line locations for diagnostics and edits. Release 1.7.3 fixed wheel and source-distribution packaging; it did not introduce a new parser model.

Verdict

StrictYAML 1.7.3 installed in 0.2 seconds, used 2 MB, imported in 0.20 seconds, and had 0 audit findings in our sandbox. Pick it for Python-owned configuration where rejecting advanced YAML is the policy; use a general parser for interoperable YAML.

We installed it

Lab card: what happened when we installed strictyamlScreenshot of strictyaml documentation
Install✓ · 0.2s3 packages on disk · 2 MB
Importimport strictyaml in 0.20s · pure Python · requires Python >=3.7.0
Known vulns0(pip-audit)

Answers from our run

Does strictyaml install cleanly?

Yes. In a fresh container with an empty cache, pip install strictyaml finished in 0.2s, leaving 3 packages and 2 MB on disk. pip-audit reported no known vulnerabilities.

What does strictyaml need to run?

Python >=3.7.0, and nothing compiled: it is pure Python. In our run import strictyaml succeeded in 0.20s.

strictyaml or PyYAML: which should you use?

PyYAML: Choose PyYAML for broad producer compatibility and the familiar safe_load dictionary workflow. StrictYAML 1.7.3 installed in 0.2 seconds, used 2 MB, imported in 0.20 seconds, and had 0 audit findings in our sandbox.

When should you not use strictyaml?

Files come from general YAML tools that emit anchors, aliases, tags, or {flow: mappings}. Standard load() refuses those valid YAML features on purpose.

API stability4/5The 1.x public surface still revolves around `load`, `dirty_load`, `as_document`, YAML nodes, and composable scalar or collection validators. Restrictions on implicit typing, tags, anchors, and duplicate keys are documented design decisions rather than accidental gaps. `MapCombined` and optional defaults are labeled experimental in the docs, however, and the absent top-level typing marker makes static API drift harder to catch automatically.
Docs5/5The documentation gives executable examples for fixed maps, arbitrary keys, optional defaults, unique sequences, scalar conversion, revalidation, construction, line lookup, and comment-preserving edits. Separate pages explain each rejected YAML feature and the string-only input API. It also admits two awkward facts directly: speed is not a priority, and round trips may move newlines or comments even when the parsed data stays the same.
Maintenance2/5PyPI published 1.7.3 on 2023-03-10, and GitHub shows the last repository push on 2025-05-23. The repository remains open; GitHub reports 105 open issues and pull requests. The current release mostly repaired wheel and source-distribution packaging, and no newer parser release has followed. A small configuration parser can stay stable for years, yet security and compatibility fixes may take time to reach PyPI.
Ecosystem3/5The recorded package data is roughly 7.2 million weekly downloads, and GitHub reports 1,622 stars. Its validators cover common Python configuration shapes, with ordinary dictionaries and lists available through `.data`. Interchange remains intentionally narrow: many valid YAML documents fail, schemas cannot be shared outside Python, and the package lacks a top-level typing marker. PyYAML, ruamel.yaml, and Pydantic connect to broader tooling.

Use it if

  • A Python-owned configuration file needs closed schemas that reject missing and unexpected keys with source locations.
  • Values such as `yes`, `no`, and `0123` must stay strings until an explicit validator converts them.
  • An editor must update validated values while retaining comments and readable block-style YAML.
  • Rejecting anchors, tags, duplicate keys, and flow collections is acceptable for every producer of the file.
Skip it if

Setup reality

We installed StrictYAML 1.7.3 in a fresh Python 3.12 Bookworm sandbox in 0.2 seconds. The environment ended with 3 packages using 2 MB on disk. The library is pure Python, requires Python 3.7.0 or newer, and has 1 direct dependency under the MIT license. import strictyaml succeeded in 0.20 seconds, while pip-audit reported 0 known vulnerabilities. The installed package does not advertise typing through a top-level py.typed marker.

Schema choice controls conversion. With no schema, 8080, yes, and dates remain strings. A plain Map demands every listed key and rejects extra ones; Optional relaxes selected keys, and MapPattern checks arbitrary names. Defaults supplied by Optional appear in .data but can be omitted from as_yaml() when they equal the declared default. That difference matters in snapshot tests and generated configuration reviews.

load() accepts decoded text, so open paths yourself and choose the encoding. Keep the YAML node when comments, start_line, or round-trip editing matter; extracting .data gives ordinary Python values without source context. Assigning through a validated node runs the schema again and can raise YAMLSerializationError. The docs also warn that parsed data survives a round trip, while exact newlines or comment placement may shift because of underlying ruamel behavior.

Normal parsing rejects flow style, anchors, aliases, tags, duplicate keys, and inconsistent mapping indentation. dirty_load(..., allow_flow_style=True) accepts flow collections for migration, but it also disables the related indentation-consistency check. Version 1.7.3 fixed package construction for wheels and source archives rather than these parsing rules. The missing top-level typing marker means mypy and pyright users may need local stubs or reduced checking at this boundary.

Patterns

Read every scalar as text load-text-scalars

from strictyaml import load

doc = load('port: 8080\nenabled: yes\n')
assert doc.data == {'port': '8080', 'enabled': 'yes'}

Without a schema, both `8080` and `yes` stay strings; StrictYAML performs no implicit scalar typing.

Convert a closed configuration map validate-fixed-map

from strictyaml import Bool, Int, Map, Str, load

schema = Map({
    'host': Str(),
    'port': Int(),
    'debug': Bool(),
})
config = load(yaml_text, schema).data

A plain `Map` rejects an unknown key and also rejects any missing required key before returning data.

Fill an omitted boolean default supply-optional-default

from strictyaml import Bool, Int, Map, Optional, load

schema = Map({
    'port': Int(),
    Optional('debug', default=False): Bool(),
})
doc = load('port: 8080\n', schema)
assert doc.data['debug'] is False

The default appears in `.data`, while `as_yaml()` omits it when the value still equals `False`.

Check every service entry validate-record-sequence

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

schema = Seq(Map({'name': Str(), 'port': Int()}))
services = load('- name: api\n  port: 8080\n', schema).data

`Seq` applies one validator to every item; use `FixedSeq` when position 1 and position 2 need different validators.

Require unique names reject-duplicate-sequence-items

from strictyaml import Str, UniqueSeq, load

schema = UniqueSeq(Str())
names = load('- api\n- worker\n', schema).data

`UniqueSeq` raises `YAMLValidationError` on a repeated value during parsing and rejects duplicates during serialization too.

Check user-named port entries validate-dynamic-keys

from strictyaml import Int, MapPattern, Regex, load

schema = MapPattern(Regex(r'^[a-z][a-z0-9-]+$'), Int())
ports = load('api: 8080\nadmin: 8081\n', schema).data

`MapPattern` runs one validator against each key and another against each value, with optional minimum and maximum key counts.

Keep required fields beside extensions combine-known-and-extra-keys

from strictyaml import Any, MapCombined, Str, load

schema = MapCombined(
    {'name': Str()},
    Str(),
    Any(),
)
doc = load('name: api\nowner: platform\n', schema)

The documentation labels `MapCombined` experimental, so its API may change in a minor 1.x release.

Update a validated value in place edit-preserving-comments

from strictyaml import Int, Map, Str, load

schema = Map({'name': Str(), 'port': Int()})
doc = load('# listener\nname: api\nport: 8080\n', schema)
doc['port'] = 8081
print(doc.as_yaml())

Editing the YAML node preserves its comment, while rebuilding from `.data` has no original comment location to reuse.

Put a filename in parse errors label-validation-errors

from pathlib import Path
from strictyaml import YAMLError, load

path = Path('service.yaml')
try:
    doc = load(path.read_text(encoding='utf-8'), schema, label=str(path))
except YAMLError as error:
    print(error)

`label='service.yaml'` replaces the default `<unicode string>` label in line and column diagnostics.

Locate a parsed value inspect-source-lines

doc = load(yaml_text, schema)
port_node = doc['port']
print(port_node.start_line, port_node.end_line)
print(port_node.lines())

Line numbers and source text belong to YAML nodes; calling `.data` returns plain Python values without those methods.

Apply a schema after reading related keys revalidate-subtree

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

overall = Map({'ports': Any(), 'services': Seq(Str())})
doc = load(yaml_text, overall)
port_schema = Map({name: Int() for name in doc.data['services']})
doc['ports'].revalidate(port_schema)

`revalidate()` can change subtree values from strings to integers and rejects any service key absent from the derived schema.

Accept flow collections during migration migrate-flow-style

from strictyaml import Any, Map, dirty_load

schema = Map({'settings': Any()})
doc = dirty_load(
    'settings: {port: 8080, debug: no}\n',
    schema,
    allow_flow_style=True,
)

`allow_flow_style=True` admits brace and bracket collections and also skips the related map-indentation consistency check.

Alternatives

PackageRegistryPick it when
PyYAMLPyPIChoose PyYAML for broad producer compatibility and the familiar `safe_load` dictionary workflow.
ruamel.yamlPyPIChoose ruamel.yaml when YAML 1.2 features and detailed round-trip control matter more than a restricted dialect.
pydanticPyPIChoose Pydantic when one typed model must validate values loaded from YAML, JSON, environment variables, or Python objects.
yamalePyPIChoose Yamale when the validation schema should live in a separate YAML file instead of executable Python code.

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.