Opinionated Python bindings for the libyang library
Project description
Opinionated Python bindings for the libyang
library
Python bindings and packaging of libyang
.
We're focusing on parsing, validating and accessing YANG-modeled JSON data trees.
Essentially, just enough to get gnpy
going.
Want more?
Patches welcome.
Compared to the CFFI libyang bindings, this wrapper takes care of low-level memory management.
This means no more node.free()
and ctx.destroy()
.
We also produce prebuilt binary wheels to make installation very simple.
Usage
Loading YANG data
import oopt_gnpy_libyang as ly
c = ly.Context('tests/yang', ly.ContextOptions.AllImplemented | ly.ContextOptions.NoYangLibrary)
for m in ('iana-if-type', 'ietf-interfaces', 'ietf-ip'):
c.load_module(m)
blob = '''{
"ietf-interfaces:interfaces": {
"interface": [
{
"name": "lo",
"type": "iana-if-type:softwareLoopback",
"ietf-ip:ipv4": {
"address": [
{
"ip": "127.0.0.1",
"prefix-length": 8
}
]
},
"ietf-ip:ipv6": {
"address": [
{
"ip": "::1",
"prefix-length": 128
}
]
}
},
{
"name": "eth0",
"type": "iana-if-type:ethernetCsmacd"
}
]
}
}'''
data = c.parse_data_str(blob,
ly.DataFormat.JSON, ly.ParseOptions.Strict | ly.ParseOptions.Ordered,
ly.ValidationOptions.Present | ly.ValidationOptions.NoState)
Working with data
Libyang works with forests (sets of trees), this is how to process all the data:
for x in data.siblings():
print(f'a sibling: {x.path}')
for xx in x.childrenDfs():
print(f' {"term " if xx.is_term else "child"}: {xx.path}')
if xx.is_term:
print(f' {xx.as_term()} {" (default)" if xx.as_term().is_default_value else ""}')
Data can be accessed via their known paths, of course. Either as a full, multi-level XPath:
data["interface[name='lo']/ietf-ip:ipv6/address[ip='::1']/prefix-length"].as_term().value == 128
Or individually, one item per index:
data["interface[name='lo']"]["ietf-ip:ipv6"]["address[ip='::1']"]["prefix-length"].as_term().value
Everything is an XPath, so it's possible to take a shortcut and skip specifying keys for single-element lists:
data["interface[name='lo']"]["ietf-ip:ipv6"]["address"]["prefix-length"].as_term().value == 128
The data are provided as native Python types:
type(data["interface[name='lo']"]["ietf-ip:ipv6"]["address"]["prefix-length"]
.as_term().value) == int
Validation errors
In libyang, if an operation fails, error details are available via context.errors()
:
import json
wrong = json.loads(blob)
wrong["ietf-interfaces:interfaces"]["interface"][0]\
["ietf-ip:ipv6"]["address"][0]["prefix-length"] = 666
try:
data = c.parse_data_str(json.dumps(wrong),
ly.DataFormat.JSON, ly.ParseOptions.Strict | ly.ParseOptions.Ordered,
ly.ValidationOptions.Present | ly.ValidationOptions.NoState)
assert False
except ly.Error:
for error in c.errors():
assert error.path == "Schema location \"/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address/prefix-length\", data location \"/ietf-ip:address[ip='::1']\", line number 1."
assert error.message == 'Value "666" is out of type uint8 min/max bounds.'
Installing
We're producing wheels for many popular platforms. The installation is as simple as:
$ pip install oopt-gnpy-libyang
Building from source
Since this library is a Python wrapper around a C++ wrapper around a C library, source-based builds are more complex. They require:
- a C++20 compiler (e.g., GCC 10+, clang 10+, MSVC 17.2+)
libyang
and its dependencieslibyang-cpp
and its dependencies- CMake 3.21+
Unlike the wheels already bundle all the required libraries, when building from source, libyang
, libyang-cpp
and all their dependencies will have to be installed first.
Also, in a from-source build these won't be bundled into the resulting package.
For an inspiration, consult our GitHub packaging recipes.
License
Copyright © 2021-2022 Telecom Infra Project and GNPy contributors. Licensed under the 3-clause BSD 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 Distributions
Hashes for oopt_gnpy_libyang-0.0.5-cp311-cp311-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 91a110e754407c51d7a884f4f61d3e6b8fb63002b877339cd684b30322584cd0 |
|
MD5 | 888f9bd3975fe95b1f5b4696ce93518d |
|
BLAKE2b-256 | 07690eb288ef154c7e23f3096b688407953711ea8e8d0b1c0a48b5aa2b3c8350 |
Hashes for oopt_gnpy_libyang-0.0.5-cp311-cp311-manylinux_2_35_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 785ff2b0b84d584540843c0ca29dce4232b7067803a452ebecfcf1e2f6df8b19 |
|
MD5 | c344c2d1e68d7a6aa2ed6415288c53ac |
|
BLAKE2b-256 | d76772a032e576702ec7072d6494d924ac9fc169d6c10903fd8a255b3d1b5992 |
Hashes for oopt_gnpy_libyang-0.0.5-cp311-cp311-macosx_12_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5678229e623f2aec7a1f768f80b9968f66d5351699e685aa0c8712919478e167 |
|
MD5 | 156284f7c550a7c2ad3f0df86ca6862c |
|
BLAKE2b-256 | dfbc2a4095f4f05978147b869de22ac397c6a27bdd58c917014f6d236ebafe96 |
Hashes for oopt_gnpy_libyang-0.0.5-cp310-cp310-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d9849ac15a5d21f9a254185a6b0e3b942be24e26b9c4158e26b2092b5cac9e36 |
|
MD5 | 433583cad9c9d53fdd8fc3db024d0f52 |
|
BLAKE2b-256 | 4a48f4f427f798ee024cae30f64c0c7a81fa517c63a0a12980418bbe409303aa |
Hashes for oopt_gnpy_libyang-0.0.5-cp310-cp310-manylinux_2_31_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 166b010e6142c9ab14d3403ad70f294c85a6e221864709bcf687726b513d3cab |
|
MD5 | ab3fbf29d8f18dc93ad524966993e289 |
|
BLAKE2b-256 | 0915b2921407bfede51431f8c0f21964d17983e3bd63d617a7bceda137ec3b39 |
Hashes for oopt_gnpy_libyang-0.0.5-cp310-cp310-macosx_12_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a4abe6abb1562d02d8f8a92cd329c71973fd6fa094b19f1686dafd8f1d8345fc |
|
MD5 | e6afecb4724cedb5c782a489441401ec |
|
BLAKE2b-256 | 6b3f4ee41ebb520104eec92d8e4a112e4b086d1e3a1bf8eda8e65147150e2a79 |
Hashes for oopt_gnpy_libyang-0.0.5-cp39-cp39-manylinux_2_31_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 36959a72053e330924737d3a1435df49742bdb69d2ff618b3fe30967cea08373 |
|
MD5 | 94b8ed7767ba50683f6fb1d77b3c1fa7 |
|
BLAKE2b-256 | 3255a2e7f4129fe83e482a3373844b257caee47c1f0bf8d6ff26d03d1f7ffffa |
Hashes for oopt_gnpy_libyang-0.0.5-cp38-cp38-manylinux_2_31_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 384c48308ed61c5c8491c738d9021760568b6a41c18871919289a9a2a10ab63d |
|
MD5 | 3812f3b94396c549f231aa6afbc451c0 |
|
BLAKE2b-256 | 726f39767a0a8c661d9e67ac516472986367116c9999401562313acc3701cdd4 |