Package: oopt-gnpy-libyang
Opinionated Python bindings for thelibyanglibraryPython bindings and packaging oflibyang.
We're focusing on parsing, validating and accessing YANG-modeled JSON data trees.
Essentially, just enough to getgnpygoing.
Want more?
Patches welcome.Compared to theCFFI libyang bindings, this wrapper takes care of low-level memory management.
This means no morenode.free()andctx.destroy().
We also produce prebuilt binarywheelsto make installation very simple.UsageLoading YANG dataimportoopt_gnpy_libyangaslyc=ly.Context('tests/yang',ly.ContextOptions.AllImplemented|ly.ContextOptions.NoYangLibrary)formin('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 dataLibyang works with forests (sets of trees), this is how to process all the data:forxindata.siblings():print(f'a sibling:{x.path}')forxxinx.children_dfs():print(f'{"term "ifxx.is_termelse"child"}:{xx.path}')ifxx.is_term:print(f'{xx.as_term()}{" (default)"ifxx.as_term().is_default_valueelse""}')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==128Or individually, one item per index:data["interface[name='lo']"]["ietf-ip:ipv6"]["address[ip='::1']"]["prefix-length"].as_term().valueEverything 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==128The data are provided as native Python types:type(data["interface[name='lo']"]["ietf-ip:ipv6"]["address"]["prefix-length"].as_term().value)==intAbsolute paths and generic XPath expressions can be used to retrieve arbitrary parts of the data forest, and to iterate over them:forifaceindata.find("/ietf-interfaces:interfaces/interface"):printiface["name"].as_term().valueRelative XPath conditions can be also used at the root level (which is represented as NULL in the C level):forifaceinsearch_at_root(data)("ietf-interfaces:interfaces/interface"):printiface["name"].as_term().valueNew values can be created; useNonefor non-terminals, orstrwhen 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 errorsIn libyang, if an operation fails, error details are available viacontext.errors():importjsonwrong=json.loads(blob)wrong["ietf-interfaces:interfaces"]["interface"][0]\["ietf-ip:ipv6"]["address"][0]["prefix-length"]=666try:data=c.parse_data(json.dumps(wrong),ly.DataFormat.JSON,ly.ParseOptions.Strict|ly.ParseOptions.Ordered,ly.ValidationOptions.Present|ly.ValidationOptions.NoState)assertFalseexceptly.Error:forerrorinc.errors():asserterror.path=="Schema location\"/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address/prefix-length\", data location\"/ietf-ip:address[ip='::1']\", line number 1."asserterror.message=='Value "666" is out of type uint8 min/max bounds.'InstallingWe're producing wheels for many popular platforms.
The installation is as simple as:$ pip install oopt-gnpy-libyangBuilding from sourceSince 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+)libyangand its dependencieslibyang-cppand its dependenciesCMake3.21+Unlike the wheels already bundle all the required libraries, when building from source,libyang,libyang-cppand 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 ourGitHub packaging recipes.LicenseCopyright © 2021-2023 Telecom Infra Project and GNPy contributors.
Licensed under the3-clause BSD license.