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(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.children_dfs():
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
Absolute paths and generic XPath expressions can be used to retrieve arbitrary parts of the data forest, and to iterate over them:
for iface in data.find("/ietf-interfaces:interfaces/interface"):
print iface["name"].as_term().value
Relative XPath conditions can be also used at the root level (which is represented as NULL in the C level):
for iface in search_at_root(data)("ietf-interfaces:interfaces/interface"):
print iface["name"].as_term().value
New values can be created; use None
for non-terminals, or str
when a value is needed:
node = ctx.create("/ietf-interfaces:interfaces/interface[name='666']")
another = ctx.create("/ietf-interfaces:interfaces/interface[name='666']/ietf-ip:ipv6/enabled", "true")
data["interface[name='lo']"]["ietf-ip:ipv6"]["address"]["prefix-length"] = "64"
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(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-2023 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.12-cp312-cp312-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a9d3a1e4c875d04cff511b156b4af50bcab3d072a11da1f18dcf15c9cfa93b25 |
|
MD5 | be176bf3266af3321e44d30ad2faf87c |
|
BLAKE2b-256 | dbdfd48e0753c6fa1ed138525a3a3a9eae182a8d27ac50116ac4ff9093e49ed4 |
Hashes for oopt_gnpy_libyang-0.0.12-cp312-cp312-manylinux_2_35_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5bda7074df5fc5c5316bda0285fac5f27fdbb42944e9bb9dc8988e0f6961e3d7 |
|
MD5 | ebb0cb3055c645c64cf61cdd989bb681 |
|
BLAKE2b-256 | 1169204085640dc9a590861c31f1def982a0eb31b4fada71d3f4819979202c89 |
Hashes for oopt_gnpy_libyang-0.0.12-cp312-cp312-macosx_13_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 03a5337c1a34c3b4de155838cbf975396cb78b662f8e3036480fe9f6eaa621ec |
|
MD5 | d9c0621f50e2402b5508a7631c9deb63 |
|
BLAKE2b-256 | a6b55a757294f5ed2a7a07e00bc2b1f0afaed3eb95b7ddea61cbf784a1998b82 |
Hashes for oopt_gnpy_libyang-0.0.12-cp312-cp312-macosx_13_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3e4f0da397528b2dd75ca1f061abaf82b9afe96de8c6a719ddd37a538106bcae |
|
MD5 | 01b5c6f27454f5cec6fa017fddeae27b |
|
BLAKE2b-256 | 22f04ab6da31e7ccd4bd4509ef85422d2f28233b27a632730ae16942f4948d26 |
Hashes for oopt_gnpy_libyang-0.0.12-cp311-cp311-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | dd27ff8430d334bc7328081d1f25d0ce0fee73c669f6290932465f11620b4328 |
|
MD5 | cc9093960eb33ca410b6d677bed03419 |
|
BLAKE2b-256 | 3303b3db7c43579c353310fd92687f5218400e9cb4d2663d82051741b29089fa |
Hashes for oopt_gnpy_libyang-0.0.12-cp311-cp311-manylinux_2_35_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | fb3963acfe794d68621c07bbf7505406dcfdc9086a7ae7bdef8c5947de1ff40f |
|
MD5 | 799b7af814c6c3386fea0c2dc4d6fdd6 |
|
BLAKE2b-256 | e938ad291e36e224adfcf474c4f3861aec98d9e7d2092eef53997913ca235452 |
Hashes for oopt_gnpy_libyang-0.0.12-cp311-cp311-macosx_12_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f53540a5d713ac6fcf188ee0d5b423229a00f068c43ac65c78e6b92893f56e48 |
|
MD5 | 1d97b9a0ed13ec9ad6b6225d87662ae9 |
|
BLAKE2b-256 | 4450d7e4e97db5c762e46ae147de461306b94fdb9d4526e8ae6c31dfd8dd4102 |
Hashes for oopt_gnpy_libyang-0.0.12-cp310-cp310-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 18e18036754408368a6a14e9b2511218ff463ad827cd86c80713097745dfcb3d |
|
MD5 | e012f41721cc5f39557ccd7889767d81 |
|
BLAKE2b-256 | ca06b9a3e9469483e29d6fca3618aec62cca59bafcc7d404d5009d0d3d7c978b |
Hashes for oopt_gnpy_libyang-0.0.12-cp310-cp310-manylinux_2_31_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b9aa2affd42604c57fe5e393109f63b5c0efd7e5c33c05dd43dddd908fcb658f |
|
MD5 | 50d99ccb41e603aa4e007a9d5cdae8dc |
|
BLAKE2b-256 | c32fcd1cc0d19cbf7647bf1697b92265265c0adaa0e608f73939a70d58c3a0e0 |
Hashes for oopt_gnpy_libyang-0.0.12-cp310-cp310-macosx_12_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a5347ef25c16dd87e8cc2cfc833e24bfc0caf4f9e8d6fc8a21962def5afed224 |
|
MD5 | 209450a276c8f723f3303ea27f4e839b |
|
BLAKE2b-256 | cbcc86a24b2ee0238aaf2eda7c67f41d9319d64d6a76a4515dfe383c41a4988c |
Hashes for oopt_gnpy_libyang-0.0.12-cp39-cp39-manylinux_2_31_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 69b830575c4fbaaa8de69d2beedba4081e8a5af0a30fee5ac7f773494b72ace0 |
|
MD5 | d20fa4546c45fa820a30cae6dd1b326c |
|
BLAKE2b-256 | f9442a40200793d33c8f8342298de908665d2c1151b91b098aac7dea99d027d0 |
Hashes for oopt_gnpy_libyang-0.0.12-cp38-cp38-manylinux_2_31_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b550f57f23c708166290bec6d3f79987ef9077bd8f3196f73b18251e631e0fa3 |
|
MD5 | 4f872f478116e02ba8349f49cf42f5f3 |
|
BLAKE2b-256 | b8b912ac8434611ba8170804d01ed008445dc5bdff0d214b0bbba0800514f52a |