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.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(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.8-cp311-cp311-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | decc43f27fef0a715257a1882ba8b14159e7aeb69187a2d2dd2f0b77009a5e4e |
|
MD5 | a09a5cd04191b1579fe4c0b490a3210f |
|
BLAKE2b-256 | 3f37b8f4c2e55417ebded1afd90031b3245678bcfd41736b441b47c48775c39e |
Hashes for oopt_gnpy_libyang-0.0.8-cp311-cp311-manylinux_2_35_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 99f310fac6531b82a7f39d549578311df15e5abd3892bd24d1bee5e892f07090 |
|
MD5 | 01b3652d0be0583294ad10223fbd8024 |
|
BLAKE2b-256 | 6675b85af5cec421724d1fffab5832717f8b6cb48141f98cc731303bb4898663 |
Hashes for oopt_gnpy_libyang-0.0.8-cp311-cp311-macosx_12_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4186c9d634cdca4504f3dfeebe9569a8267850fb4c4bbe32d99515770b6af8d5 |
|
MD5 | d8253a6bee09a107a8406b9c2b108c1b |
|
BLAKE2b-256 | 87714a2e12e7889f599db367a15984b146e74c899070cd3ebc349e194ea972d2 |
Hashes for oopt_gnpy_libyang-0.0.8-cp310-cp310-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a05cb03911914b9e7fec4079ac4a54ea6ad7d56c90d9f60768c1718e804e2bbe |
|
MD5 | ba21367dd69d42767555a8e5e31b22aa |
|
BLAKE2b-256 | df7f98c9f8fba3b26f783d830755d1fa5d05737110b9c1b1da98cdbeec540f7d |
Hashes for oopt_gnpy_libyang-0.0.8-cp310-cp310-manylinux_2_31_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 92447389bf63ba1b268c65f09f5a6ba21d7777440058c4a5c7a03d7c14c4df75 |
|
MD5 | 4b8f54a35b8b053a3a32360c6aea8bf3 |
|
BLAKE2b-256 | fab0fbe0d43210e6cb3fad9dc1d6bb077f0aec2e7c3ab9f236bb54d9f73b9c97 |
Hashes for oopt_gnpy_libyang-0.0.8-cp310-cp310-macosx_12_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4feb608e0631a6ff0ecaef6be5ef5087ba352d292c64e81db26f646121d07b91 |
|
MD5 | eccabe316365f959e570ebd74d313bd8 |
|
BLAKE2b-256 | 9f0c229f54ee99fc932eb1faaf9dfa13e730c30b91c04b6a490c00b084bb0ffc |
Hashes for oopt_gnpy_libyang-0.0.8-cp39-cp39-manylinux_2_31_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b1c0f2b4498433ee66f9971bffc0aadfd88f524c61fe413ac56fe4408c0bae68 |
|
MD5 | c1f6b416713530b528a5b476db91a387 |
|
BLAKE2b-256 | fb23fa48d4c1779e4fce8298c134a262012f38237d5d6d9b6bc2da1c340597c4 |
Hashes for oopt_gnpy_libyang-0.0.8-cp38-cp38-manylinux_2_31_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 702ffc5c8dfa17c1daa5c81321cc1b1efa115653b6186bc2c1d67ae3433baa18 |
|
MD5 | 92f156a11982e3cbb8fba5f35eb7ac82 |
|
BLAKE2b-256 | d2e3def90b89d8d8fb75f3ff53d38381c19aeef076daea88300254d2e4878a5e |