mirror of
https://github.com/Telecominfraproject/oopt-gnpy-libyang.git
synced 2025-11-02 02:58:01 +00:00
Port to libyang v3
...along with a bunch of incompatible API/ABI changes. I had to make a few tweaks in the build process as well, and these couldn't be made (and tested!) with separate commits. The test suite was failing on OS X 13, so I decided to upgrade, because "why not".
This commit is contained in:
53
.github/workflows/ci.yaml
vendored
53
.github/workflows/ci.yaml
vendored
@@ -78,19 +78,19 @@ jobs:
|
||||
wheel: win_amd64
|
||||
python-version: "3.12"
|
||||
|
||||
- name: "macOS 13 x86_64 Python 3.12"
|
||||
os: macos-13
|
||||
- name: "macOS 15 x86_64 x86_64 Python 3.13"
|
||||
os: macos-15-large
|
||||
build_type: Release
|
||||
generators: Ninja
|
||||
wheel: macosx_13_0_x86_64
|
||||
python-version: "3.12"
|
||||
wheel: macosx_15_0_x86_64
|
||||
python-version: "3.13"
|
||||
|
||||
- name: "macOS 13 arm64 Python 3.12"
|
||||
os: macos-13-xlarge
|
||||
- name: "macOS 15 arm64 Python 3.13"
|
||||
os: macos-15-xlarge
|
||||
build_type: Release
|
||||
generators: Ninja
|
||||
wheel: macosx_13_0_arm64
|
||||
python-version: "3.12"
|
||||
wheel: macosx_15_0_arm64
|
||||
python-version: "3.13"
|
||||
|
||||
steps:
|
||||
- name: Unix line endings in git
|
||||
@@ -177,19 +177,18 @@ jobs:
|
||||
echo CC=gcc-10 >> $GITHUB_ENV
|
||||
echo CXX=g++-10 >> $GITHUB_ENV
|
||||
|
||||
# FIXME: this cannot be GCC 13 because of https://github.com/actions/runner-images/issues/9997
|
||||
- name: GCC 12 on Mac OS 13
|
||||
- name: GCC 14 on Mac OS 15
|
||||
if: startsWith(matrix.os, 'macos-13')
|
||||
shell: bash
|
||||
run: |
|
||||
echo CC=gcc-12 >> $GITHUB_ENV
|
||||
echo CXX=g++-12 >> $GITHUB_ENV
|
||||
echo CC=gcc-14 >> $GITHUB_ENV
|
||||
echo CXX=g++-14 >> $GITHUB_ENV
|
||||
|
||||
- name: Mac OS 13 deployment target
|
||||
if: startsWith(matrix.os, 'macos-13')
|
||||
- name: Mac OS 15 deployment target
|
||||
if: startsWith(matrix.os, 'macos-15')
|
||||
shell: bash
|
||||
run: |
|
||||
echo MACOSX_DEPLOYMENT_TARGET=13.0 >> $GITHUB_ENV
|
||||
echo MACOSX_DEPLOYMENT_TARGET=15.0 >> $GITHUB_ENV
|
||||
|
||||
- name: Mac OS ARCHFLAGS x86_64
|
||||
if: startsWith(matrix.os, 'macos') && endsWith(matrix.wheel, '_x86_64')
|
||||
@@ -234,14 +233,6 @@ jobs:
|
||||
echo REPAIR_LIBRARY_PATH=${{ github.workspace }}/../target/lib >> $GITHUB_ENV
|
||||
echo PKG_CONFIG_PATH=${{ github.workspace }}/../target/lib/pkgconfig >> $GITHUB_ENV
|
||||
|
||||
# FIXME: linker is FUBAR on this platform and/or version of XCode
|
||||
# https://forums.developer.apple.com/forums/thread/737707
|
||||
# https://github.com/actions/runner-images/issues/9273
|
||||
# https://github.com/Homebrew/homebrew-core/issues/145991
|
||||
- name: Unbreak XCode linker
|
||||
if: startswith(matrix.os, 'macos-13')
|
||||
run: sudo xcode-select -switch /Applications/Xcode_14.3.1.app
|
||||
|
||||
# FIXME: CMake 4.0 is backwards-incompatible, https://github.com/actions/runner-images/issues/11926
|
||||
- name: pin CMake to the latest 3.x series
|
||||
uses: jwlawson/actions-setup-cmake@09fd9b0fb3b239b4b68d9256cd65adf8d6b91da0
|
||||
@@ -501,15 +492,15 @@ jobs:
|
||||
wheel: win_amd64
|
||||
python-version: "3.12"
|
||||
|
||||
- name: "macOS 13 x86_64 Python 3.12"
|
||||
os: macos-13
|
||||
wheel: macosx_13_0_x86_64
|
||||
python-version: "3.12"
|
||||
- name: "macOS 15 x86_64 Python 3.13"
|
||||
os: macos-15-large
|
||||
wheel: macosx_15_0_x86_64
|
||||
python-version: "3.13"
|
||||
|
||||
- name: "macOS 13 arm64 Python 3.12"
|
||||
os: macos-13-xlarge
|
||||
wheel: macosx_13_0_arm64
|
||||
python-version: "3.12"
|
||||
- name: "macOS 13 arm64 Python 3.13"
|
||||
os: macos-15-xlarge
|
||||
wheel: macosx_15_0_arm64
|
||||
python-version: "3.13"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -17,7 +17,7 @@ if(NOT MSVC)
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(LIBYANG-CPP REQUIRED IMPORTED_TARGET libyang-cpp>=1.0.0 libyang)
|
||||
pkg_check_modules(LIBYANG-CPP REQUIRED IMPORTED_TARGET libyang-cpp>=4 libyang)
|
||||
|
||||
set(PYBIND11_FINDPYTHON ON)
|
||||
find_package(Python 3.8 REQUIRED COMPONENTS Interpreter Development.Module)
|
||||
|
||||
@@ -68,7 +68,7 @@ for x in data.siblings():
|
||||
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 ""}')
|
||||
print(f' {xx.as_term()} {" (default)" if xx.as_term().has_default_value else ""}')
|
||||
```
|
||||
Data can be accessed via their known paths, of course. Either as a full, multi-level XPath:
|
||||
|
||||
@@ -119,7 +119,9 @@ try:
|
||||
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.schema_path is None
|
||||
assert error.data_path == "/ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/address[ip='::1']/prefix-length"
|
||||
assert error.line > 0
|
||||
assert error.message == 'Value "666" is out of type uint8 min/max bounds.'
|
||||
```
|
||||
|
||||
|
||||
2
libyang
2
libyang
Submodule libyang updated: fbcee29952...ce38b35612
Submodule libyang-cpp updated: 5884eeaa79...dab8c9aac9
@@ -167,7 +167,9 @@ PYBIND11_MODULE(oopt_gnpy_libyang, m) {
|
||||
.def_readonly("level", &ErrorInfo::level)
|
||||
.def_readonly("message", &ErrorInfo::message)
|
||||
.def_readonly("code", &ErrorInfo::code)
|
||||
.def_readonly("path", &ErrorInfo::path)
|
||||
.def_readonly("data_path", &ErrorInfo::dataPath)
|
||||
.def_readonly("schema_path", &ErrorInfo::schemaPath)
|
||||
.def_readonly("line", &ErrorInfo::line)
|
||||
.def_readonly("validation_code", &ErrorInfo::validationCode)
|
||||
.def("__repr__", [](const ErrorInfo& e) {
|
||||
std::ostringstream ss;
|
||||
@@ -176,7 +178,9 @@ PYBIND11_MODULE(oopt_gnpy_libyang, m) {
|
||||
ss << ", code = " << e.code;
|
||||
ss << ", validation_code = " << e.validationCode;
|
||||
ss << ", message = " << repr_optional_string(e.message);
|
||||
ss << ", path = " << repr_optional_string(e.path);
|
||||
ss << ", data_path = " << repr_optional_string(e.dataPath);
|
||||
ss << ", schema_path = " << repr_optional_string(e.schemaPath);
|
||||
ss << ", line = " << e.line;
|
||||
ss << ", app_tag = " << repr_optional_string(e.appTag);
|
||||
ss << ")";
|
||||
return ss.str();
|
||||
@@ -219,7 +223,8 @@ PYBIND11_MODULE(oopt_gnpy_libyang, m) {
|
||||
;
|
||||
|
||||
py::class_<DataNodeTerm, DataNode>(m, "DataNodeTerm")
|
||||
.def_property("is_default_value", &DataNodeTerm::isDefaultValue, nullptr)
|
||||
.def_property("has_default_value", &DataNodeTerm::hasDefaultValue, nullptr)
|
||||
.def_property("is_implicit_default", &DataNodeTerm::isImplicitDefault, nullptr)
|
||||
.def_property("value", &DataNodeTerm::value, nullptr)
|
||||
.def("__str__", &DataNodeTerm::valueStr)
|
||||
;
|
||||
|
||||
@@ -27,10 +27,13 @@ def test_features(context_no_libyang):
|
||||
m = context_no_libyang.load_module('ietf-interfaces')
|
||||
with pytest.raises(ly.Error, match="Couldn't set module 'ietf-interfaces' to implemented: LY_EINVAL"):
|
||||
m.set_implemented_with_features(['arbotrary-names'])
|
||||
errors = [(e.level, e.code, e.message, e.path, e.validation_code, e.app_tag) for e in context_no_libyang.errors()]
|
||||
errors = [
|
||||
(e.level, e.code, e.message, e.data_path, e.schema_path, e.line, e.validation_code, e.app_tag)
|
||||
for e in context_no_libyang.errors()
|
||||
]
|
||||
assert errors == [
|
||||
(ly.LogLevel.Error, ly.ErrorCode.InvalidValue, 'Feature "arbotrary-names" not found in module "ietf-interfaces".',
|
||||
None, ly.ValidationErrorCode.Success, None)
|
||||
None, None, 0, ly.ValidationErrorCode.Success, None)
|
||||
]
|
||||
m.set_implemented_with_features(['arbitrary-names'])
|
||||
for feature in m.features:
|
||||
@@ -54,5 +57,5 @@ def test_explicit_loading(context_no_libyang):
|
||||
|
||||
def test_version():
|
||||
assert len(ly.libyang_version_info()) == 3
|
||||
assert ly.libyang_version_info()[0] == 2
|
||||
assert ly.libyang_version()[0:2] == '2.'
|
||||
assert ly.libyang_version_info()[0] == 3
|
||||
assert ly.libyang_version()[0:2] == '3.'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import json
|
||||
import pytest
|
||||
import oopt_gnpy_libyang as ly
|
||||
|
||||
@@ -192,6 +193,20 @@ def test_ietf_interfaces(context_with_modules):
|
||||
assert "/ietf-interfaces:interfaces/interface[name='42']" in separate_node
|
||||
context_with_modules.create("/ietf-interfaces:interfaces/interface[name='666']")
|
||||
|
||||
wrong = json.loads(blob)
|
||||
wrong["ietf-interfaces:interfaces"]["interface"][0]["ietf-ip:ipv6"]["address"][0]["prefix-length"] = 666
|
||||
try:
|
||||
data = context_with_modules.parse_data(json.dumps(wrong, indent=2),
|
||||
ly.DataFormat.JSON, ly.ParseOptions.Strict | ly.ParseOptions.Ordered,
|
||||
ly.ValidationOptions.Present | ly.ValidationOptions.NoState)
|
||||
assert False
|
||||
except ly.Error:
|
||||
for error in context_with_modules.errors():
|
||||
assert error.schema_path is None
|
||||
assert error.data_path == "/ietf-interfaces:interfaces/interface[name='lo']/ietf-ip:ipv6/address[ip='::1']/prefix-length"
|
||||
assert error.line == 20
|
||||
assert error.message == 'Value "666" is out of type uint8 min/max bounds.'
|
||||
|
||||
def test_types(context_no_libyang):
|
||||
context_no_libyang.parse_module('''
|
||||
module dummy {
|
||||
|
||||
Reference in New Issue
Block a user