A Python library implementing a subset of YANG features focused on constraint validation
Project description
xYang
YANG models, validated JSON, and JSON Schema—without dragging in a full management stack.
xYang is a pure-Python library and CLI for parsing YANG 1.1-shaped modules, validating instance data against the full set of RFC 7950 built-in types (each checked with the right rules—ranges, length/pattern, base64 binary, bits, union disambiguation, leafref / identityref / instance-identifier resolution, and the rest), plus must, when, if-feature, and structure. It exports a standards-friendly JSON Schema (2020-12) layer augmented with x-yang metadata for round-trip where supported. It is built for real modules (reference design: examples/meta-model.yang), including deep XPath: deref() tied to schema paths, union typing, and current() in list and leaf-list contexts.
- Zero required runtime dependencies — drop into apps, agents, and pipelines with minimal footprint.
- Honest scope — not every RFC 7950 statement is modeled; what is implemented is described precisely in FEATURES.md (including
import/include,if-feature,anydata/anyxml, and JSONif-featuresround-trip). Constructs such asrpc,notification, anddeviationare recognized and skipped with a log warning so mixed modules still parse. - MIT licensed — use it in products and internal tools alike.
Repository: github.com/exergy-connect/xYang · Issues: github.com/exergy-connect/xYang/issues
Features (overview)
The list below is the short version; FEATURES.md is the authoritative, line-by-line feature matrix and documents the YANG.json hybrid format.
- Module structure:
module/submodule,yang-version,namespace,prefix, metadata,revision,import,include,feature - Types: All RFC 7950 built-in types (Section 4.2.4) are supported and validated on instance data—
string,binary, numeric types,decimal64,boolean,empty,enumeration,bits,union,leafref,identityref, andinstance-identifier—with applicable substatements (length,range,pattern,fraction-digits,require-instance, etc.).typedefand imports compose these. Statement-level scope (e.g. skippedrpc/notification) and JSON Schema details: FEATURES.md. - Data nodes:
container,list+key,leaf,leaf-list,choice/case,anydata/anyxml,grouping/uses/refine,augment(merge when uses expansion is enabled) - Constraints:
must,when,if-feature,mandatory,default,min-elements/max-elements,pattern,length,range,fraction-digits - References:
leafref(+require-instance),instance-identifier,identityref,identity/base, XPathderived-from()/derived-from-or-self() - Interop:
xyangCLI (parse,validate,convert) and JSON Schema export withx-yangannotations for generator/parser round-trip where supported
Installation
From PyPI (when published):
pip install xyang
From a checkout (editable, for development):
pip install -e .
There are no required runtime dependencies. For xyang validate with .yaml / .yml instance files, install PyYAML (pip install PyYAML or pip install -e ".[dev]").
Requirements: Python ≥ 3.9 (see pyproject.toml).
Usage
Command-line (xyang)
xyang -h # help
xyang parse <file.yang> # print module info
xyang validate <file.yang> [data.json] # or .yaml/.yml (needs PyYAML); omit file → JSON from stdin
xyang convert <file.yang> [-o path] # YANG → .yang.json (output path ends with .yang.json)
Without installing the package, from the repo root: PYTHONPATH=src python3 -m xyang -h
Parsing a YANG module
from xyang import parse_yang_file, parse_yang_string
# Parse from file
module = parse_yang_file("examples/meta-model.yang")
# Parse from string
yang_content = """
module example {
yang-version 1.1;
namespace "urn:example";
prefix "ex";
container data {
leaf name {
type string;
}
}
}
"""
module = parse_yang_string(yang_content)
print(f"Module: {module.name}")
print(f"Namespace: {module.namespace}")
print(f"Prefix: {module.prefix}")
Validating data
from xyang import parse_yang_file, YangValidator
module = parse_yang_file("examples/meta-model.yang")
validator = YangValidator(module)
# Consolidated JSON document: one tree matching your module’s data layout.
# XPath comparisons use schema-aware coercion (e.g. string "true" vs boolean leaves).
data = {
"data-model": {
"name": "example",
"entities": [
{
"name": "server",
"fields": [
{"name": "id", "type": "string"}
]
}
]
}
}
is_valid, errors, warnings = validator.validate(data)
if not is_valid:
for error in errors:
print(f"Error: {error}")
Working with types
from xyang import TypeConstraint, TypeSystem
type_system = TypeSystem()
constraint = TypeConstraint(
pattern=r'[a-z_][a-z0-9_]*',
length="1..64"
)
type_system.register_typedef("entity-name", "string", constraint)
is_valid, error = type_system.validate("server_name", "entity-name")
print(f"Valid: {is_valid}")
Converting YANG → JSON Schema (.yang.json)
Valid JSON Schema for structure and types; YANG-only rules (must, when, leafref paths, if-features, …) ride in x-yang. Details: FEATURES.md — YANG.json hybrid format.
from xyang.parser import YangParser
from xyang.json import schema_to_yang_json
parser = YangParser(expand_uses=False)
module = parser.parse_file("examples/meta-model.yang")
schema_to_yang_json(module, output_path="meta-model.yang.json")
CLI: xyang convert examples/meta-model.yang -o meta-model.yang.json
Project layout
xYang/
├── src/xyang/
│ ├── __init__.py # Package exports
│ ├── __main__.py # CLI (parse, validate, convert)
│ ├── parser/ # YANG parser (incl. unsupported-statement skip)
│ ├── json/ # JSON Schema generator + parser
│ ├── validator/ # Document validation
│ ├── xpath/ # XPath for must/when
│ ├── ast.py # AST nodes
│ ├── types.py # Type system
│ ├── module.py # Module model
│ └── errors.py
├── examples/ # meta-model.yang, samples, generated .yang.json
├── tests/
├── benchmarks/
├── FEATURES.md # Full feature list & format spec
├── pyproject.toml
└── README.md
XPath (schema-aware)
Coverage matches what meta-model.yang needs, evaluated with schema context (not a generic XPath 1.0 engine):
- Paths:
../field,../../field, absolute paths such as/data-model/entities - Functions:
string(),number(),concat(),string-length(),translate(),count(),deref(),current(),not(),true(),false(),boolean(),derived-from(),derived-from-or-self(), … - Comparisons & logic:
=,!=,<=,>=,<,>,and,or - Literal sequences (xYang extension): RHS
('a', 'b')for membership-style equality - Predicates & indexing: e.g.
[name = current()],[1] - String concat:
+between strings in expressions
deref() on leafref values follows the leafref’s schema path to resolve the target node; it supports nesting, caching, and cycle detection for the patterns used in production modules here.
When & must (examples)
When — if the condition is false, the node is out of the effective schema; data there is reported as invalid:
container item_type {
when "../type = 'array'";
leaf primitive { type string; }
}
Must — XPath must evaluate true or validation fails (with error-message when provided):
leaf minDate {
type date;
must "not(../maxDate) or . <= ../maxDate" {
error-message "minDate must be less than or equal to maxDate";
}
}
Scope & limitations
- Single JSON instance — validation is against one consolidated document, not NETCONF/XML fragments or incremental edits.
- XPath subset — unsupported expressions fail at XPath parse time (
UnsupportedXPathError). Extend the evaluator to add features. deref()— fully handled for meta-model-style patterns; it remains schema-coupled by design, not a standalone generic resolver.- RFC surface — see FEATURES.md for what is partial, skipped, or out of scope; the parser warns when it skips unsupported top-level-like statements.
Design choices
No mandatory third-party stack — core package dependencies are empty in pyproject.toml; optional PyYAML only for YAML instances on the CLI. That keeps xYang easy to embed and audit.
Development
pip install -e ".[dev]"
pytest
black src/xyang/
License
MIT License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xyang-0.1.0.tar.gz.
File metadata
- Download URL: xyang-0.1.0.tar.gz
- Upload date:
- Size: 129.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3e53ba8e995f3cebb341e4bb900573d276a7626c3b32b9951716c15e59b08dc5
|
|
| MD5 |
2eb4d1e3967648513730db811e36696d
|
|
| BLAKE2b-256 |
c65563d0a0257da8d9f328807d3151603acd221e4ff8f1d35e34e2a7d3ef34e3
|
Provenance
The following attestation bundles were made for xyang-0.1.0.tar.gz:
Publisher:
publish-pypi.yml on exergy-connect/xYang
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xyang-0.1.0.tar.gz -
Subject digest:
3e53ba8e995f3cebb341e4bb900573d276a7626c3b32b9951716c15e59b08dc5 - Sigstore transparency entry: 1258531192
- Sigstore integration time:
-
Permalink:
exergy-connect/xYang@9cf11e130d8417c7cb0dce7009e7677ba74cf6cc -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/exergy-connect
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@9cf11e130d8417c7cb0dce7009e7677ba74cf6cc -
Trigger Event:
release
-
Statement type:
File details
Details for the file xyang-0.1.0-py3-none-any.whl.
File metadata
- Download URL: xyang-0.1.0-py3-none-any.whl
- Upload date:
- Size: 92.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c9d203fece6283fd38932de21d8e3ad629eae50a35eec3f95ab5926525cb1923
|
|
| MD5 |
23af68e2c58ec3da2f133382f6bfc757
|
|
| BLAKE2b-256 |
650c85d4bfb49071ea428c1b6c5108ca8490fcba6dcd46e128d1ac9245797cbd
|
Provenance
The following attestation bundles were made for xyang-0.1.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on exergy-connect/xYang
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xyang-0.1.0-py3-none-any.whl -
Subject digest:
c9d203fece6283fd38932de21d8e3ad629eae50a35eec3f95ab5926525cb1923 - Sigstore transparency entry: 1258531208
- Sigstore integration time:
-
Permalink:
exergy-connect/xYang@9cf11e130d8417c7cb0dce7009e7677ba74cf6cc -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/exergy-connect
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@9cf11e130d8417c7cb0dce7009e7677ba74cf6cc -
Trigger Event:
release
-
Statement type: