mirror of
https://github.com/Telecominfraproject/oopt-gnpy-libyang.git
synced 2025-11-01 18:47:57 +00:00
190 lines
10 KiB
C++
190 lines
10 KiB
C++
#include <pybind11/functional.h>
|
|
#include <pybind11/pybind11.h>
|
|
#include <pybind11/stl.h>
|
|
#include <libyang-cpp/Context.hpp>
|
|
|
|
using namespace std::literals;
|
|
using namespace pybind11::literals;
|
|
|
|
PYBIND11_MODULE(oopt_gnpy_libyang, m) {
|
|
m.doc() = "Opinionated Python bindings for the libyang library";
|
|
|
|
pybind11::enum_<libyang::ContextOptions>(m, "ContextOptions")
|
|
.value("AllImplemented", libyang::ContextOptions::AllImplemented)
|
|
.value("RefImplemented", libyang::ContextOptions::RefImplemented)
|
|
.value("NoYangLibrary", libyang::ContextOptions::NoYangLibrary)
|
|
.value("DisableSearchDirs", libyang::ContextOptions::DisableSearchDirs)
|
|
.value("DisableSearchCwd", libyang::ContextOptions::DisableSearchCwd)
|
|
.value("PreferSearchDirs", libyang::ContextOptions::PreferSearchDirs)
|
|
.value("SetPrivParsed", libyang::ContextOptions::SetPrivParsed)
|
|
.value("ExplicitCompile", libyang::ContextOptions::ExplicitCompile)
|
|
.def("__or__", [](libyang::ContextOptions a, libyang::ContextOptions b){ return a | b; })
|
|
;
|
|
|
|
pybind11::enum_<libyang::LogLevel>(m, "LogLevel")
|
|
.value("Error", libyang::LogLevel::Error)
|
|
.value("Warning", libyang::LogLevel::Warning)
|
|
.value("Verbose", libyang::LogLevel::Verbose)
|
|
.value("Debug", libyang::LogLevel::Debug)
|
|
;
|
|
|
|
pybind11::enum_<libyang::ErrorCode>(m, "ErrorCode")
|
|
.value("Success", libyang::ErrorCode::Success)
|
|
.value("MemoryFailure", libyang::ErrorCode::MemoryFailure)
|
|
.value("SyscallFail", libyang::ErrorCode::SyscallFail)
|
|
.value("InvalidValue", libyang::ErrorCode::InvalidValue)
|
|
.value("ItemAlreadyExists", libyang::ErrorCode::ItemAlreadyExists)
|
|
.value("NotFound", libyang::ErrorCode::NotFound)
|
|
.value("InternalError", libyang::ErrorCode::InternalError)
|
|
.value("ValidationFailure", libyang::ErrorCode::ValidationFailure)
|
|
.value("OperationDenied", libyang::ErrorCode::OperationDenied)
|
|
.value("OperationIncomplete", libyang::ErrorCode::OperationIncomplete)
|
|
.value("RecompileRequired", libyang::ErrorCode::RecompileRequired)
|
|
.value("Negative", libyang::ErrorCode::Negative)
|
|
.value("Unknown", libyang::ErrorCode::Unknown)
|
|
.value("PluginError", libyang::ErrorCode::PluginError)
|
|
;
|
|
|
|
pybind11::enum_<libyang::ValidationErrorCode>(m, "ValidationErrorCode")
|
|
.value("Success", libyang::ValidationErrorCode::Success)
|
|
.value("Syntax", libyang::ValidationErrorCode::Syntax)
|
|
.value("YangSyntax", libyang::ValidationErrorCode::YangSyntax)
|
|
.value("YinSyntax", libyang::ValidationErrorCode::YinSyntax)
|
|
.value("Reference", libyang::ValidationErrorCode::Reference)
|
|
.value("Xpath", libyang::ValidationErrorCode::Xpath)
|
|
.value("Semantics", libyang::ValidationErrorCode::Semantics)
|
|
.value("XmlSyntax", libyang::ValidationErrorCode::XmlSyntax)
|
|
.value("JsonSyntax", libyang::ValidationErrorCode::JsonSyntax)
|
|
.value("Data", libyang::ValidationErrorCode::Data)
|
|
.value("Other", libyang::ValidationErrorCode::Other)
|
|
;
|
|
|
|
pybind11::enum_<libyang::DataFormat>(m, "DataFormat")
|
|
.value("Detect", libyang::DataFormat::Detect)
|
|
.value("JSON", libyang::DataFormat::JSON)
|
|
.value("XML", libyang::DataFormat::XML)
|
|
;
|
|
|
|
pybind11::enum_<libyang::ParseOptions>(m, "ParseOptions")
|
|
.value("ParseOnly", libyang::ParseOptions::ParseOnly)
|
|
.value("Strict", libyang::ParseOptions::Strict)
|
|
.value("Opaque", libyang::ParseOptions::Opaque)
|
|
.value("NoState", libyang::ParseOptions::NoState)
|
|
.value("LybModUpdate", libyang::ParseOptions::LybModUpdate)
|
|
.value("Ordered", libyang::ParseOptions::Ordered)
|
|
.def("__or__", [](libyang::ParseOptions a, libyang::ParseOptions b){ return a | b; })
|
|
;
|
|
|
|
pybind11::enum_<libyang::ValidationOptions>(m, "ValidationOptions")
|
|
.value("NoState", libyang::ValidationOptions::NoState)
|
|
.value("Present", libyang::ValidationOptions::Present)
|
|
.def("__or__", [](libyang::ValidationOptions a, libyang::ValidationOptions b){ return a | b; })
|
|
;
|
|
|
|
pybind11::enum_<libyang::PrintFlags>(m, "PrintFlags")
|
|
.value("WithDefaultsExplicit", libyang::PrintFlags::WithDefaultsExplicit)
|
|
.value("WithSiblings", libyang::PrintFlags::WithSiblings)
|
|
.value("Shrink", libyang::PrintFlags::Shrink)
|
|
.value("KeepEmptyCont", libyang::PrintFlags::KeepEmptyCont)
|
|
.value("WithDefaultsTrim", libyang::PrintFlags::WithDefaultsTrim)
|
|
.value("WithDefaultsAll", libyang::PrintFlags::WithDefaultsAll)
|
|
.value("WithDefaultsAllTag", libyang::PrintFlags::WithDefaultsAllTag)
|
|
.value("WithDefaultsImplicitTag", libyang::PrintFlags::WithDefaultsImplicitTag)
|
|
.value("WithDefaultsMask", libyang::PrintFlags::WithDefaultsMask)
|
|
.def("__or__", [](libyang::PrintFlags a, libyang::PrintFlags b){ return a | b; })
|
|
;
|
|
|
|
auto eError = pybind11::register_local_exception<libyang::Error>(m, "Error", PyExc_RuntimeError);
|
|
pybind11::register_local_exception<libyang::ErrorWithCode>(m, "ErrorWithCode", eError);
|
|
/* FIXME: cannot do .def_property("code", &libyang::ErrorWithCode::code, nullptr) */
|
|
pybind11::register_local_exception<libyang::ParsedInfoUnavailable>(m, "ParsedInfoUnavailable", eError);
|
|
|
|
pybind11::class_<libyang::Feature>(m, "Feature")
|
|
.def_property("name", &libyang::Feature::name, nullptr)
|
|
;
|
|
|
|
pybind11::class_<libyang::Module>(m, "Module")
|
|
.def_property("name", &libyang::Module::name, nullptr)
|
|
.def_property("revision", &libyang::Module::revision, nullptr)
|
|
.def_property("implemented", &libyang::Module::implemented, nullptr)
|
|
.def_property("features", &libyang::Module::features, nullptr)
|
|
.def("set_implemented", static_cast<void (libyang::Module::*)()>(&libyang::Module::setImplemented))
|
|
.def("feature_enabled", &libyang::Module::featureEnabled)
|
|
.def("set_implemented_with_features", static_cast<void (libyang::Module::*)(std::vector<std::string>)>(&libyang::Module::setImplemented), "features"_a)
|
|
.def("set_implemented_all_features", [](libyang::Module& mod) { mod.setImplemented(libyang::AllFeatures{}); })
|
|
// FIXME: identities
|
|
// FIXME: childInstantiables
|
|
;
|
|
|
|
pybind11::class_<libyang::ErrorInfo>(m, "ErrorInfo")
|
|
.def_readonly("app_tag", &libyang::ErrorInfo::appTag)
|
|
.def_readonly("level", &libyang::ErrorInfo::level)
|
|
.def_readonly("message", &libyang::ErrorInfo::message)
|
|
.def_readonly("code", &libyang::ErrorInfo::code)
|
|
.def_readonly("path", &libyang::ErrorInfo::path)
|
|
.def_readonly("validation_code", &libyang::ErrorInfo::validationCode)
|
|
;
|
|
|
|
pybind11::class_<libyang::DataNode>(m, "DataNode")
|
|
.def_property("path", &libyang::DataNode::path, nullptr)
|
|
.def_property("is_term", &libyang::DataNode::isTerm, nullptr)
|
|
.def("as_term", &libyang::DataNode::asTerm)
|
|
.def("print", &libyang::DataNode::printStr, "format"_a, "flags"_a)
|
|
.def("siblings", &libyang::DataNode::siblings)
|
|
.def("child", &libyang::DataNode::child)
|
|
.def("childrenDfs", &libyang::DataNode::childrenDfs)
|
|
.def("immediateChildren", &libyang::DataNode::immediateChildren)
|
|
.def("__getitem__",
|
|
[](const libyang::DataNode& node, const std::string& key) {
|
|
auto set = node.findXPath(key);
|
|
if (set.empty()) {
|
|
throw pybind11::key_error{"No such data node below '" + node.path() + "' for '" + key + "'"};
|
|
} else if (set.size() > 1) {
|
|
throw pybind11::key_error{"Too many nodes below '" + node.path() + "' for '" + key + "'"};
|
|
} else {
|
|
return *set.begin();
|
|
}
|
|
})
|
|
;
|
|
|
|
pybind11::class_<libyang::DataNodeTerm, libyang::DataNode>(m, "DataNodeTerm")
|
|
.def_property("is_default_value", &libyang::DataNodeTerm::isDefaultValue, nullptr)
|
|
.def_property("value", &libyang::DataNodeTerm::value, nullptr)
|
|
.def("__str__", &libyang::DataNodeTerm::valueStr)
|
|
;
|
|
|
|
using Collection_DataNode_Siblings = libyang::Collection<libyang::DataNode, libyang::IterationType::Sibling>;
|
|
pybind11::class_<Collection_DataNode_Siblings>(m, "_Collection_DataNode_Siblings")
|
|
.def("__iter__",
|
|
[](const Collection_DataNode_Siblings &s) { return pybind11::make_iterator(s.begin(), s.end()); },
|
|
pybind11::keep_alive<0, 1>())
|
|
;
|
|
|
|
using Collection_DataNode_Dfs = libyang::Collection<libyang::DataNode, libyang::IterationType::Dfs>;
|
|
pybind11::class_<Collection_DataNode_Dfs>(m, "_Collection_DataNode_Dfs")
|
|
.def("__iter__",
|
|
[](const Collection_DataNode_Dfs &s) { return pybind11::make_iterator(s.begin(), s.end()); },
|
|
pybind11::keep_alive<0, 1>())
|
|
;
|
|
|
|
pybind11::class_<libyang::Context>(m, "Context")
|
|
.def(pybind11::init<const std::optional<std::string>&, const std::optional<libyang::ContextOptions>>(), "searchPath"_a=std::nullopt, "options"_a=std::nullopt)
|
|
.def("load_module", &libyang::Context::loadModule, "name"_a, "revision"_a=std::nullopt, "features"_a=std::vector<std::string>{})
|
|
.def("modules", &libyang::Context::modules)
|
|
.def("get_module", &libyang::Context::getModule, "name"_a, "revision"_a=std::nullopt)
|
|
.def("get_module_implemented", &libyang::Context::getModuleImplemented, "name"_a)
|
|
.def("errors", &libyang::Context::getErrors)
|
|
.def("clean_all_errors", &libyang::Context::cleanAllErrors)
|
|
.def("parse_data_str", &libyang::Context::parseDataMem, "data"_a, "format"_a, "parse_options"_a=std::nullopt, "validation_options"_a=std::nullopt)
|
|
|
|
// is this actually needed? looks like parseDataMem() does that just fine
|
|
/* .def("validate_data_str", */
|
|
/* [](const libyang::Context& ctx, const std::string& data, const libyang::DataFormat format, const libyang::ParseOptions parseOptions, const libyang::ValidationOptions validationOptions) { */
|
|
/* auto x = ctx.parseDataMem(data, format, parseOptions, validationOptions); */
|
|
/* libyang::validateAll(x, validationOptions); */
|
|
/* return x; */
|
|
/* }, */
|
|
/* "data"_a, "format"_a=libyang::DataFormat::Auto, "parse_options"_a=std::nullopt, "validation_options"_a=std::nullopt) */
|
|
;
|
|
}
|