Skip to main content

Opinionated Python bindings for the libyang library

Project description

Opinionated Python bindings for the libyang library

Install via pip Python versions GitHub Workflow Status

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 and ctx.destroy(). We also produce prebuilt binary wheels to make installation very simple.


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'):
blob = '''{
  "ietf-interfaces:interfaces": {
    "interface": [
        "name": "lo",
        "type": "iana-if-type:softwareLoopback",
        "ietf-ip:ipv4": {
          "address": [
              "ip": "",
              "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:


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:

    .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)
    ["ietf-ip:ipv6"]["address"][0]["prefix-length"] = 666
    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.'


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 dependencies
  • libyang-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.


Copyright © 2021-2023 Telecom Infra Project and GNPy contributors. Licensed under the 3-clause BSD license.

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

oopt-gnpy-libyang-0.0.14.tar.gz (45.2 kB view hashes)

Uploaded Source

Built Distributions

oopt_gnpy_libyang-0.0.14-cp312-cp312-win_amd64.whl (1.2 MB view hashes)

Uploaded CPython 3.12 Windows x86-64

oopt_gnpy_libyang-0.0.14-cp312-cp312-manylinux_2_35_x86_64.whl (1.1 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.35+ x86-64

oopt_gnpy_libyang-0.0.14-cp312-cp312-macosx_13_0_x86_64.whl (2.0 MB view hashes)

Uploaded CPython 3.12 macOS 13.0+ x86-64

oopt_gnpy_libyang-0.0.14-cp312-cp312-macosx_13_0_arm64.whl (1.9 MB view hashes)

Uploaded CPython 3.12 macOS 13.0+ ARM64

oopt_gnpy_libyang-0.0.14-cp311-cp311-win_amd64.whl (1.2 MB view hashes)

Uploaded CPython 3.11 Windows x86-64

oopt_gnpy_libyang-0.0.14-cp311-cp311-manylinux_2_35_x86_64.whl (1.1 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.35+ x86-64

oopt_gnpy_libyang-0.0.14-cp311-cp311-macosx_12_0_x86_64.whl (2.1 MB view hashes)

Uploaded CPython 3.11 macOS 12.0+ x86-64

oopt_gnpy_libyang-0.0.14-cp310-cp310-win_amd64.whl (1.2 MB view hashes)

Uploaded CPython 3.10 Windows x86-64

oopt_gnpy_libyang-0.0.14-cp310-cp310-manylinux_2_31_x86_64.whl (1.1 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.31+ x86-64

oopt_gnpy_libyang-0.0.14-cp310-cp310-macosx_12_0_x86_64.whl (2.1 MB view hashes)

Uploaded CPython 3.10 macOS 12.0+ x86-64

oopt_gnpy_libyang-0.0.14-cp39-cp39-manylinux_2_31_x86_64.whl (1.1 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.31+ x86-64

oopt_gnpy_libyang-0.0.14-cp38-cp38-manylinux_2_31_x86_64.whl (1.1 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.31+ x86-64

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page