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.13-cp312-cp312-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | c9166957a2123589d7f297cfe5480dd8035cd8471cd6d709138a18f7c37d4a18 |
|
MD5 | 376fcfa308664cbbff6bffb926c7b660 |
|
BLAKE2b-256 | efc3029e33adc307642aa1ae81e0c83da6ac77b1daf3cc4e0bb99ce9ab2a26df |
Hashes for oopt_gnpy_libyang-0.0.13-cp312-cp312-manylinux_2_35_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 40c1bc323660d647051d9f07b49de35042cff778fc764ccb6d64f89306c3c068 |
|
MD5 | 62d8ba6ed0bc83dcdb5c9c205ef16f6d |
|
BLAKE2b-256 | 9514bbbaab8535bcf4963086b59ab381e884e8f496438379e8b381c55fdadc6f |
Hashes for oopt_gnpy_libyang-0.0.13-cp312-cp312-macosx_13_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a76d919906c0541ca12039a5c31ed7f4eae704b8f07f1c13606b7ee69c354325 |
|
MD5 | c89e428dc4cac647e5dd7b8364c1a13f |
|
BLAKE2b-256 | 742b0e540dd204a21e408569c836367f7a0bd310896fb5f63e04922a544ee550 |
Hashes for oopt_gnpy_libyang-0.0.13-cp312-cp312-macosx_13_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2af5e428458cc8d80781c9f9220bc8c42745400c6af74c89f6211f91ff625dec |
|
MD5 | dac03d6b1ea3549fc989784fe560ccb2 |
|
BLAKE2b-256 | 355f1a0fa3f5d581a4b085bd3704918b62066a4da04f067139f0a8d11ff62ff7 |
Hashes for oopt_gnpy_libyang-0.0.13-cp311-cp311-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1d28ed526772696f3fb98bef030c538141e99c17a19a03f7bf42f9e92f4f7126 |
|
MD5 | 35287e068637334245235c6c657e34dd |
|
BLAKE2b-256 | 276be3b6a024ea9fba766973b105d87ba0484c05e749998337da924d85b1ae1a |
Hashes for oopt_gnpy_libyang-0.0.13-cp311-cp311-manylinux_2_35_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 30adc6b5072a16d12d62cb0a876df5852944473252c6ba25f68069e77cb5f158 |
|
MD5 | 2e9a0a2fea2fa77439dcd9f5b253f59d |
|
BLAKE2b-256 | 455ab663ce04fa93370f1b55bf1741faa9e0e0b5c771a4beb4b5f0c31285324d |
Hashes for oopt_gnpy_libyang-0.0.13-cp311-cp311-macosx_12_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 361401603adbd874a95e64f5c2e68348f653538dab9ba6eae7ed0aadae1ffe95 |
|
MD5 | ad871c6344f98645adebb5f2be3bf3f5 |
|
BLAKE2b-256 | 54b3d2bac7e765e60bc2b32ce6d1296f7e52be6626429668ab77ea0ea020cad8 |
Hashes for oopt_gnpy_libyang-0.0.13-cp310-cp310-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d49ab9e8698103d74fb88e98510f3eef4d8e4987fccac492e117ee809b33f306 |
|
MD5 | 0b6225de3a1fdb42e2e345c3d9de2ede |
|
BLAKE2b-256 | 1972d31ec0e423cc0ab91f49bdf520e30864a041c48e46c20bae09173381f861 |
Hashes for oopt_gnpy_libyang-0.0.13-cp310-cp310-manylinux_2_31_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f52ab906c5fd52c7a6b989fbd6317d64e34e9fb8432d8be4aa1678456b7609c1 |
|
MD5 | 7206093918be707c18c9825d461226c9 |
|
BLAKE2b-256 | d4e616f2849653d266342526a31afdc3122bf43acb7ab176025f54f4118afc0d |
Hashes for oopt_gnpy_libyang-0.0.13-cp310-cp310-macosx_12_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | ff80e44017df6aa2d8146d0eee9dbaa342ff5babfa730a47763cb662c2388cea |
|
MD5 | 9860508eaf8ace6086071551dce8b971 |
|
BLAKE2b-256 | 28e3a82381ee83f1212f4b9db9503aa8a20b579b05e9a7800895c500e7904961 |
Hashes for oopt_gnpy_libyang-0.0.13-cp39-cp39-manylinux_2_31_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 33777d08f2a356f94189d766fc1b6abca05f3b4639c3296b98ac122888bcc2d5 |
|
MD5 | d9e624ca6b3fe0e38a836719b227956b |
|
BLAKE2b-256 | 3039438d3169f9024b7365d6c5a6da60308471c0ff7355e9b10093027eaa3114 |
Hashes for oopt_gnpy_libyang-0.0.13-cp38-cp38-manylinux_2_31_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 49c3024d314c1f6467da72b35d65e289c0341c6e6d401dccf9832e028e2391d5 |
|
MD5 | 98023cb34b5327b80b38d3bcd387f76b |
|
BLAKE2b-256 | 3b6d2400e78b3454ba50eec777f2298967d1083e6e189486cd4c0c4f3f7d6347 |