mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 01:13:00 +02:00
Upgrade python-libyang to support libyang4
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# md5, sha256 from https://pypi.org/pypi/libyang/json
|
||||
md5 46332891cac852441b523f7e71a507f7 libyang-3.0.1.tar.gz
|
||||
sha256 57f8b234131fb073518313351288194e535d74cc8fdff7f0ff7e31c0ab33e663 libyang-3.0.1.tar.gz
|
||||
sha256 97da2c908a8a3607ac834f2acec224ea53a4b9e9770c13e5598513641decf637 libyang-3.3.0.tar.gz
|
||||
# Locally computed sha256 checksums
|
||||
sha256 c8d554f918d32b1467f35829e1cfb753764dd683c6edcecc877a4d7e9f05b2a7 LICENSE
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#
|
||||
################################################################################
|
||||
|
||||
PYTHON_LIBYANG_VERSION = 3.0.1
|
||||
PYTHON_LIBYANG_VERSION = 3.3.0
|
||||
PYTHON_LIBYANG_SOURCE = libyang-$(PYTHON_LIBYANG_VERSION).tar.gz
|
||||
PYTHON_LIBYANG_SITE = https://files.pythonhosted.org/packages/91/2e/ff13ee16c874d232d5d3fdff83f629cbc9ac47f9aaf2b59256b6a1bdbc16
|
||||
PYTHON_LIBYANG_SITE = https://files.pythonhosted.org/packages/34/d8/ebe9de6d29eaf62a684b34d30118294e48a05d7fbd1bb0af002b7627140d
|
||||
PYTHON_LIBYANG_SETUP_TYPE = setuptools
|
||||
PYTHON_LIBYANG_LICENSE = MIT
|
||||
PYTHON_LIBYANG_LICENSE_FILES = LICENSE
|
||||
|
||||
@@ -0,0 +1,876 @@
|
||||
From 8c246567c03471e20cd9574f9c95a179712c3e3f Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Gula <steweg@gmail.com>
|
||||
Date: Sun, 2 Nov 2025 21:26:55 +0100
|
||||
Subject: [PATCH] cffi: allows to usage of libyang v4.2.2
|
||||
|
||||
This patch adjust cffi definitions and also all associated functions
|
||||
based on libyang v4.2.2.
|
||||
|
||||
Signed-off-by: Stefan Gula <steweg@gmail.com>
|
||||
---
|
||||
cffi/cdefs.h | 61 ++++++++++++++++++++++-----------------
|
||||
cffi/source.c | 4 +--
|
||||
libyang/context.py | 25 ++++++++++------
|
||||
libyang/data.py | 7 ++---
|
||||
libyang/extension.py | 24 +++++++++++-----
|
||||
libyang/schema.py | 66 +++++++++++++++++++++++++++++++++---------
|
||||
tests/test_context.py | 6 +++-
|
||||
tests/test_data.py | 67 ++++++++++++++++++++++++-------------------
|
||||
tests/test_diff.py | 4 ++-
|
||||
tests/test_schema.py | 4 +--
|
||||
10 files changed, 172 insertions(+), 96 deletions(-)
|
||||
|
||||
diff --git a/cffi/cdefs.h b/cffi/cdefs.h
|
||||
index 8b6d426..82ec974 100644
|
||||
--- a/cffi/cdefs.h
|
||||
+++ b/cffi/cdefs.h
|
||||
@@ -17,6 +17,7 @@ struct ly_ctx;
|
||||
#define LY_CTX_LEAFREF_EXTENDED ...
|
||||
#define LY_CTX_LEAFREF_LINKING ...
|
||||
#define LY_CTX_BUILTIN_PLUGINS_ONLY ...
|
||||
+#define LY_CTX_COMPILE_OBSOLETE ...
|
||||
|
||||
|
||||
typedef enum {
|
||||
@@ -304,20 +305,19 @@ enum lyd_type {
|
||||
LYD_TYPE_REPLY_RESTCONF
|
||||
};
|
||||
|
||||
-#define LYD_PRINT_KEEPEMPTYCONT ...
|
||||
#define LYD_PRINT_SHRINK ...
|
||||
+#define LYD_PRINT_EMPTY_CONT ...
|
||||
#define LYD_PRINT_WD_ALL ...
|
||||
#define LYD_PRINT_WD_ALL_TAG ...
|
||||
#define LYD_PRINT_WD_EXPLICIT ...
|
||||
#define LYD_PRINT_WD_IMPL_TAG ...
|
||||
#define LYD_PRINT_WD_MASK ...
|
||||
-#define LYD_PRINT_WITHSIBLINGS ...
|
||||
+#define LYD_PRINT_SIBLINGS ...
|
||||
#define LYD_PRINT_WD_TRIM ...
|
||||
LY_ERR lyd_print_mem(char **, const struct lyd_node *, LYD_FORMAT, uint32_t);
|
||||
LY_ERR lyd_print_tree(struct ly_out *, const struct lyd_node *, LYD_FORMAT, uint32_t);
|
||||
LY_ERR lyd_print_all(struct ly_out *, const struct lyd_node *, LYD_FORMAT, uint32_t);
|
||||
|
||||
-#define LYD_PARSE_LYB_MOD_UPDATE ...
|
||||
#define LYD_PARSE_NO_STATE ...
|
||||
#define LYD_PARSE_STORE_ONLY ...
|
||||
#define LYD_PARSE_JSON_NULL ...
|
||||
@@ -351,7 +351,7 @@ LY_ERR ly_out_new_file(FILE *, struct ly_out **);
|
||||
LY_ERR ly_out_new_fd(int, struct ly_out **);
|
||||
|
||||
LY_ERR lyd_parse_data(const struct ly_ctx *, struct lyd_node *, struct ly_in *, LYD_FORMAT, uint32_t, uint32_t, struct lyd_node **);
|
||||
-LY_ERR lyd_parse_op(const struct ly_ctx *, struct lyd_node *, struct ly_in *, LYD_FORMAT, enum lyd_type, struct lyd_node **, struct lyd_node **);
|
||||
+LY_ERR lyd_parse_op(const struct ly_ctx *, struct lyd_node *, struct ly_in *, LYD_FORMAT, enum lyd_type, uint32_t, struct lyd_node **, struct lyd_node **);
|
||||
|
||||
typedef enum {
|
||||
LYS_OUT_UNKNOWN,
|
||||
@@ -369,6 +369,7 @@ LY_ERR lys_print_module(struct ly_out *, const struct lys_module *, LYS_OUTFORMA
|
||||
|
||||
struct lysc_module {
|
||||
struct lys_module *mod;
|
||||
+ const char **features;
|
||||
struct lysc_node *data;
|
||||
struct lysc_node_action *rpcs;
|
||||
struct lysc_node_notif *notifs;
|
||||
@@ -388,13 +389,15 @@ struct lys_module {
|
||||
const char *ref;
|
||||
struct lysp_module *parsed;
|
||||
struct lysc_module *compiled;
|
||||
+ struct lysc_ext *extensions;
|
||||
struct lysc_ident *identities;
|
||||
+ struct lysc_submodule *submodules;
|
||||
struct lys_module **augmented_by;
|
||||
struct lys_module **deviated_by;
|
||||
ly_bool implemented;
|
||||
ly_bool to_compile;
|
||||
- uint8_t latest_revision;
|
||||
- ...;
|
||||
+ uint8_t version : 2;
|
||||
+ uint8_t latest_revision : 4;
|
||||
};
|
||||
|
||||
struct lysp_module {
|
||||
@@ -467,12 +470,11 @@ struct lysp_ext_instance {
|
||||
const char *argument;
|
||||
LY_VALUE_FORMAT format;
|
||||
void *prefix_data;
|
||||
- struct lysp_ext *def;
|
||||
+ uintptr_t plugin_ref;
|
||||
void *parent;
|
||||
enum ly_stmt parent_stmt;
|
||||
uint64_t parent_stmt_index;
|
||||
uint16_t flags;
|
||||
- const struct lyplg_ext_record *record;
|
||||
struct lysp_ext_substmt *substmts;
|
||||
void *parsed;
|
||||
struct lysp_stmt *child;
|
||||
@@ -610,6 +612,11 @@ struct lysp_node_container {
|
||||
...;
|
||||
};
|
||||
|
||||
+struct lysc_value {
|
||||
+ const char *str;
|
||||
+ struct lysc_prefix *prefixes;
|
||||
+};
|
||||
+
|
||||
struct lysc_node_leaf {
|
||||
union {
|
||||
struct lysc_node node;
|
||||
@@ -623,7 +630,7 @@ struct lysc_node_leaf {
|
||||
struct lysc_when **when;
|
||||
struct lysc_type *type;
|
||||
const char *units;
|
||||
- struct lyd_value *dflt;
|
||||
+ struct lysc_value dflt;
|
||||
...;
|
||||
};
|
||||
|
||||
@@ -653,7 +660,7 @@ struct lysc_node_leaflist {
|
||||
struct lysc_when **when;
|
||||
struct lysc_type *type;
|
||||
const char *units;
|
||||
- struct lyd_value **dflts;
|
||||
+ struct lysc_value *dflts;
|
||||
uint32_t min;
|
||||
uint32_t max;
|
||||
...;
|
||||
@@ -783,7 +790,7 @@ struct lysp_node_augment {
|
||||
struct lysc_type {
|
||||
const char *name;
|
||||
struct lysc_ext_instance *exts;
|
||||
- struct lyplg_type *plugin;
|
||||
+ uintptr_t plugin_ref;
|
||||
LY_DATA_TYPE basetype;
|
||||
uint32_t refcount;
|
||||
};
|
||||
@@ -859,7 +866,7 @@ struct lysc_ext {
|
||||
const char *name;
|
||||
const char *argname;
|
||||
struct lysc_ext_instance *exts;
|
||||
- struct lyplg_ext *plugin;
|
||||
+ uintptr_t plugin_ref;
|
||||
struct lys_module *module;
|
||||
uint16_t flags;
|
||||
};
|
||||
@@ -982,7 +989,6 @@ typedef struct pcre2_real_code pcre2_code;
|
||||
|
||||
struct lysc_pattern {
|
||||
const char *expr;
|
||||
- pcre2_code *code;
|
||||
const char *dsc;
|
||||
const char *ref;
|
||||
const char *emsg;
|
||||
@@ -1017,7 +1023,7 @@ struct lysc_ident {
|
||||
struct lysc_type_num {
|
||||
const char *name;
|
||||
struct lysc_ext_instance *exts;
|
||||
- struct lyplg_type *plugin;
|
||||
+ uintptr_t plugin_ref;
|
||||
LY_DATA_TYPE basetype;
|
||||
uint32_t refcount;
|
||||
struct lysc_range *range;
|
||||
@@ -1026,7 +1032,7 @@ struct lysc_type_num {
|
||||
struct lysc_type_dec {
|
||||
const char *name;
|
||||
struct lysc_ext_instance *exts;
|
||||
- struct lyplg_type *plugin;
|
||||
+ uintptr_t plugin_ref;
|
||||
LY_DATA_TYPE basetype;
|
||||
uint32_t refcount;
|
||||
uint8_t fraction_digits;
|
||||
@@ -1036,7 +1042,7 @@ struct lysc_type_dec {
|
||||
struct lysc_type_str {
|
||||
const char *name;
|
||||
struct lysc_ext_instance *exts;
|
||||
- struct lyplg_type *plugin;
|
||||
+ uintptr_t plugin_ref;
|
||||
LY_DATA_TYPE basetype;
|
||||
uint32_t refcount;
|
||||
struct lysc_range *length;
|
||||
@@ -1058,7 +1064,7 @@ struct lysc_type_bitenum_item {
|
||||
struct lysc_type_enum {
|
||||
const char *name;
|
||||
struct lysc_ext_instance *exts;
|
||||
- struct lyplg_type *plugin;
|
||||
+ uintptr_t plugin_ref;
|
||||
LY_DATA_TYPE basetype;
|
||||
uint32_t refcount;
|
||||
struct lysc_type_bitenum_item *enums;
|
||||
@@ -1067,7 +1073,7 @@ struct lysc_type_enum {
|
||||
struct lysc_type_bits {
|
||||
const char *name;
|
||||
struct lysc_ext_instance *exts;
|
||||
- struct lyplg_type *plugin;
|
||||
+ uintptr_t plugin_ref;
|
||||
LY_DATA_TYPE basetype;
|
||||
uint32_t refcount;
|
||||
struct lysc_type_bitenum_item *bits;
|
||||
@@ -1076,7 +1082,7 @@ struct lysc_type_bits {
|
||||
struct lysc_type_leafref {
|
||||
const char *name;
|
||||
struct lysc_ext_instance *exts;
|
||||
- struct lyplg_type *plugin;
|
||||
+ uintptr_t plugin_ref;
|
||||
LY_DATA_TYPE basetype;
|
||||
uint32_t refcount;
|
||||
struct lyxp_expr *path;
|
||||
@@ -1088,7 +1094,7 @@ struct lysc_type_leafref {
|
||||
struct lysc_type_identityref {
|
||||
const char *name;
|
||||
struct lysc_ext_instance *exts;
|
||||
- struct lyplg_type *plugin;
|
||||
+ uintptr_t plugin_ref;
|
||||
LY_DATA_TYPE basetype;
|
||||
uint32_t refcount;
|
||||
struct lysc_ident **bases;
|
||||
@@ -1097,7 +1103,7 @@ struct lysc_type_identityref {
|
||||
struct lysc_type_instanceid {
|
||||
const char *name;
|
||||
struct lysc_ext_instance *exts;
|
||||
- struct lyplg_type *plugin;
|
||||
+ uintptr_t plugin_ref;
|
||||
LY_DATA_TYPE basetype;
|
||||
uint32_t refcount;
|
||||
uint8_t require_instance;
|
||||
@@ -1106,7 +1112,7 @@ struct lysc_type_instanceid {
|
||||
struct lysc_type_union {
|
||||
const char *name;
|
||||
struct lysc_ext_instance *exts;
|
||||
- struct lyplg_type *plugin;
|
||||
+ uintptr_t plugin_ref;
|
||||
LY_DATA_TYPE basetype;
|
||||
uint32_t refcount;
|
||||
struct lysc_type **types;
|
||||
@@ -1115,7 +1121,7 @@ struct lysc_type_union {
|
||||
struct lysc_type_bin {
|
||||
const char *name;
|
||||
struct lysc_ext_instance *exts;
|
||||
- struct lyplg_type *plugin;
|
||||
+ uintptr_t plugin_ref;
|
||||
LY_DATA_TYPE basetype;
|
||||
uint32_t refcount;
|
||||
struct lysc_range *length;
|
||||
@@ -1159,8 +1165,7 @@ typedef enum {
|
||||
LYD_ANYDATA_DATATREE,
|
||||
LYD_ANYDATA_STRING,
|
||||
LYD_ANYDATA_XML,
|
||||
- LYD_ANYDATA_JSON,
|
||||
- LYD_ANYDATA_LYB
|
||||
+ LYD_ANYDATA_JSON
|
||||
} LYD_ANYDATA_VALUETYPE;
|
||||
|
||||
union lyd_any_value {
|
||||
@@ -1168,7 +1173,6 @@ union lyd_any_value {
|
||||
const char *str;
|
||||
const char *xml;
|
||||
const char *json;
|
||||
- char *mem;
|
||||
};
|
||||
|
||||
struct lyd_node_any {
|
||||
@@ -1320,6 +1324,8 @@ struct lyd_attr {
|
||||
LY_ERR lyd_new_attr(struct lyd_node *, const char *, const char *, const char *, struct lyd_attr **);
|
||||
void lyd_free_attr_single(const struct ly_ctx *ctx, struct lyd_attr *attr);
|
||||
|
||||
+LY_ERR lyd_value_validate_dflt(const struct lysc_node *, const char *, struct lysc_prefix *, const struct lyd_node *, const struct lysc_type **, const char **);
|
||||
+
|
||||
struct lyd_leafref_links_rec {
|
||||
const struct lyd_node_term *node;
|
||||
const struct lyd_node_term **leafref_nodes;
|
||||
@@ -1328,13 +1334,14 @@ struct lyd_leafref_links_rec {
|
||||
|
||||
LY_ERR lyd_leafref_get_links(const struct lyd_node_term *, const struct lyd_leafref_links_rec **);
|
||||
LY_ERR lyd_leafref_link_node_tree(struct lyd_node *);
|
||||
+struct lyplg_ext *lysc_get_ext_plugin(uintptr_t);
|
||||
const char *lyplg_ext_stmt2str(enum ly_stmt stmt);
|
||||
const struct lysp_module *lyplg_ext_parse_get_cur_pmod(const struct lysp_ctx *);
|
||||
struct ly_ctx *lyplg_ext_compile_get_ctx(const struct lysc_ctx *);
|
||||
void lyplg_ext_parse_log(const struct lysp_ctx *, const struct lysp_ext_instance *, LY_LOG_LEVEL, LY_ERR, const char *, ...);
|
||||
void lyplg_ext_compile_log(const struct lysc_ctx *, const struct lysc_ext_instance *, LY_LOG_LEVEL, LY_ERR, const char *, ...);
|
||||
LY_ERR lyplg_ext_parse_extension_instance(struct lysp_ctx *, struct lysp_ext_instance *);
|
||||
-LY_ERR lyplg_ext_compile_extension_instance(struct lysc_ctx *, const struct lysp_ext_instance *, struct lysc_ext_instance *);
|
||||
+LY_ERR lyplg_ext_compile_extension_instance(struct lysc_ctx *, const struct lysp_ext_instance *, struct lysc_ext_instance *, struct lysc_node *);
|
||||
void lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext_substmt *substmts);
|
||||
void lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext_substmt *substmts);
|
||||
typedef LY_ERR (*lyplg_ext_parse_clb)(struct lysp_ctx *, struct lysp_ext_instance *);
|
||||
diff --git a/cffi/source.c b/cffi/source.c
|
||||
index 34e18b0..3c76e98 100644
|
||||
--- a/cffi/source.c
|
||||
+++ b/cffi/source.c
|
||||
@@ -6,6 +6,6 @@
|
||||
#include <libyang/libyang.h>
|
||||
#include <libyang/version.h>
|
||||
|
||||
-#if LY_VERSION_MAJOR * 10000 + LY_VERSION_MINOR * 100 + LY_VERSION_MICRO < 30801
|
||||
-#error "This version of libyang bindings only works with libyang soversion 3.8.1+"
|
||||
+#if LY_VERSION_MAJOR * 10000 + LY_VERSION_MINOR * 100 + LY_VERSION_MICRO < 40202
|
||||
+#error "This version of libyang bindings only works with libyang soversion 4.2.2+"
|
||||
#endif
|
||||
diff --git a/libyang/context.py b/libyang/context.py
|
||||
index 4489680..21db162 100644
|
||||
--- a/libyang/context.py
|
||||
+++ b/libyang/context.py
|
||||
@@ -205,6 +205,7 @@ def __init__(
|
||||
builtin_plugins_only: bool = False,
|
||||
all_implemented: bool = False,
|
||||
enable_imp_features: bool = False,
|
||||
+ compile_obsolete: bool = False,
|
||||
yanglib_path: Optional[str] = None,
|
||||
yanglib_fmt: str = "json",
|
||||
cdata=None, # C type: "struct ly_ctx *"
|
||||
@@ -231,6 +232,8 @@ def __init__(
|
||||
options |= lib.LY_CTX_ALL_IMPLEMENTED
|
||||
if enable_imp_features:
|
||||
options |= lib.LY_CTX_ENABLE_IMP_FEATURES
|
||||
+ if compile_obsolete:
|
||||
+ options |= lib.LY_CTX_COMPILE_OBSOLETE
|
||||
# force priv parsed
|
||||
options |= lib.LY_CTX_SET_PRIV_PARSED
|
||||
|
||||
@@ -259,6 +262,7 @@ def __init__(
|
||||
fmt = lib.LYD_JSON
|
||||
else:
|
||||
fmt = lib.LYD_XML
|
||||
+ print("steweg", search_path, yanglib_path, yanglib_fmt, options)
|
||||
ret = lib.ly_ctx_new_ylpath(
|
||||
str2c(search_path), str2c(yanglib_path), fmt, options, ctx
|
||||
)
|
||||
@@ -542,6 +546,8 @@ def parse_op(
|
||||
in_data: Union[IO, str],
|
||||
dtype: DataType,
|
||||
parent: DNode = None,
|
||||
+ opaq: bool = False,
|
||||
+ strict: bool = False,
|
||||
) -> DNode:
|
||||
fmt = data_format(fmt)
|
||||
data = ffi.new("struct ly_in **")
|
||||
@@ -551,13 +557,14 @@ def parse_op(
|
||||
if ret != lib.LY_SUCCESS:
|
||||
raise self.error("failed to read input data")
|
||||
|
||||
+ flags = parser_flags(opaq=opaq, strict=strict)
|
||||
tree = ffi.new("struct lyd_node **", ffi.NULL)
|
||||
op = ffi.new("struct lyd_node **", ffi.NULL)
|
||||
par = ffi.new("struct lyd_node **", ffi.NULL)
|
||||
if parent is not None:
|
||||
par[0] = parent.cdata
|
||||
|
||||
- ret = lib.lyd_parse_op(self.cdata, par[0], data[0], fmt, dtype, tree, op)
|
||||
+ ret = lib.lyd_parse_op(self.cdata, par[0], data[0], fmt, dtype, flags, tree, op)
|
||||
lib.ly_in_free(data[0], 0)
|
||||
if ret != lib.LY_SUCCESS:
|
||||
raise self.error("failed to parse input data")
|
||||
@@ -570,9 +577,17 @@ def parse_op_mem(
|
||||
data: str,
|
||||
dtype: DataType = DataType.DATA_YANG,
|
||||
parent: DNode = None,
|
||||
+ opaq: bool = False,
|
||||
+ strict: bool = False,
|
||||
):
|
||||
return self.parse_op(
|
||||
- fmt, in_type=IOType.MEMORY, in_data=data, dtype=dtype, parent=parent
|
||||
+ fmt,
|
||||
+ in_type=IOType.MEMORY,
|
||||
+ in_data=data,
|
||||
+ dtype=dtype,
|
||||
+ parent=parent,
|
||||
+ opaq=opaq,
|
||||
+ strict=strict,
|
||||
)
|
||||
|
||||
def parse_data(
|
||||
@@ -581,7 +596,6 @@ def parse_data(
|
||||
in_type: IOType,
|
||||
in_data: Union[str, bytes, IO],
|
||||
parent: DNode = None,
|
||||
- lyb_mod_update: bool = False,
|
||||
no_state: bool = False,
|
||||
parse_only: bool = False,
|
||||
opaq: bool = False,
|
||||
@@ -596,7 +610,6 @@ def parse_data(
|
||||
if self.cdata is None:
|
||||
raise RuntimeError("context already destroyed")
|
||||
parser_flgs = parser_flags(
|
||||
- lyb_mod_update=lyb_mod_update,
|
||||
no_state=no_state,
|
||||
parse_only=parse_only,
|
||||
opaq=opaq,
|
||||
@@ -640,7 +653,6 @@ def parse_data_mem(
|
||||
data: Union[str, bytes],
|
||||
fmt: str,
|
||||
parent: DNode = None,
|
||||
- lyb_mod_update: bool = False,
|
||||
no_state: bool = False,
|
||||
parse_only: bool = False,
|
||||
opaq: bool = False,
|
||||
@@ -657,7 +669,6 @@ def parse_data_mem(
|
||||
in_type=IOType.MEMORY,
|
||||
in_data=data,
|
||||
parent=parent,
|
||||
- lyb_mod_update=lyb_mod_update,
|
||||
no_state=no_state,
|
||||
parse_only=parse_only,
|
||||
opaq=opaq,
|
||||
@@ -675,7 +686,6 @@ def parse_data_file(
|
||||
fileobj: IO,
|
||||
fmt: str,
|
||||
parent: DNode = None,
|
||||
- lyb_mod_update: bool = False,
|
||||
no_state: bool = False,
|
||||
parse_only: bool = False,
|
||||
opaq: bool = False,
|
||||
@@ -692,7 +702,6 @@ def parse_data_file(
|
||||
in_type=IOType.FD,
|
||||
in_data=fileobj,
|
||||
parent=parent,
|
||||
- lyb_mod_update=lyb_mod_update,
|
||||
no_state=no_state,
|
||||
parse_only=parse_only,
|
||||
opaq=opaq,
|
||||
diff --git a/libyang/data.py b/libyang/data.py
|
||||
index 7a5887b..230c51a 100644
|
||||
--- a/libyang/data.py
|
||||
+++ b/libyang/data.py
|
||||
@@ -53,11 +53,11 @@ def printer_flags(
|
||||
) -> int:
|
||||
flags = 0
|
||||
if with_siblings:
|
||||
- flags |= lib.LYD_PRINT_WITHSIBLINGS
|
||||
+ flags |= lib.LYD_PRINT_SIBLINGS
|
||||
if not pretty:
|
||||
flags |= lib.LYD_PRINT_SHRINK
|
||||
if keep_empty_containers:
|
||||
- flags |= lib.LYD_PRINT_KEEPEMPTYCONT
|
||||
+ flags |= lib.LYD_PRINT_EMPTY_CONT
|
||||
if trim_default_values:
|
||||
flags |= lib.LYD_PRINT_WD_TRIM
|
||||
if include_implicit_defaults:
|
||||
@@ -109,7 +109,6 @@ def newval_flags(
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
def parser_flags(
|
||||
- lyb_mod_update: bool = False,
|
||||
no_state: bool = False,
|
||||
parse_only: bool = False,
|
||||
opaq: bool = False,
|
||||
@@ -120,8 +119,6 @@ def parser_flags(
|
||||
json_string_datatypes: bool = False,
|
||||
) -> int:
|
||||
flags = 0
|
||||
- if lyb_mod_update:
|
||||
- flags |= lib.LYD_PARSE_LYB_MOD_UPDATE
|
||||
if no_state:
|
||||
flags |= lib.LYD_PARSE_NO_STATE
|
||||
if parse_only:
|
||||
diff --git a/libyang/extension.py b/libyang/extension.py
|
||||
index 57f7cb2..f7e4ba9 100644
|
||||
--- a/libyang/extension.py
|
||||
+++ b/libyang/extension.py
|
||||
@@ -8,7 +8,7 @@
|
||||
from _libyang import ffi, lib
|
||||
from .context import Context
|
||||
from .log import get_libyang_level
|
||||
-from .schema import ExtensionCompiled, ExtensionParsed, Module
|
||||
+from .schema import ExtensionCompiled, ExtensionParsed, Module, SNode
|
||||
from .util import LibyangError, c2str, str2c
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ def __init__(self, message: str, ret: int, log_level: int) -> None:
|
||||
|
||||
@ffi.def_extern(name="lypy_lyplg_ext_parse_clb")
|
||||
def libyang_c_lyplg_ext_parse_clb(pctx, pext):
|
||||
- plugin = extensions_plugins[pext.record.plugin]
|
||||
+ plugin = extensions_plugins[lib.lysc_get_ext_plugin(pext.plugin_ref)]
|
||||
module_cdata = lib.lyplg_ext_parse_get_cur_pmod(pctx).mod
|
||||
context = Context(cdata=module_cdata.ctx)
|
||||
module = Module(context, module_cdata)
|
||||
@@ -46,7 +46,7 @@ def libyang_c_lyplg_ext_parse_clb(pctx, pext):
|
||||
|
||||
@ffi.def_extern(name="lypy_lyplg_ext_compile_clb")
|
||||
def libyang_c_lyplg_ext_compile_clb(cctx, pext, cext):
|
||||
- plugin = extensions_plugins[pext.record.plugin]
|
||||
+ plugin = extensions_plugins[lib.lysc_get_ext_plugin(pext.plugin_ref)]
|
||||
context = Context(cdata=lib.lyplg_ext_compile_get_ctx(cctx))
|
||||
module = Module(context, cext.module)
|
||||
parsed_ext = ExtensionParsed(context, pext, module)
|
||||
@@ -67,7 +67,7 @@ def libyang_c_lyplg_ext_compile_clb(cctx, pext, cext):
|
||||
|
||||
@ffi.def_extern(name="lypy_lyplg_ext_parse_free_clb")
|
||||
def libyang_c_lyplg_ext_parse_free_clb(ctx, pext):
|
||||
- plugin = extensions_plugins[pext.record.plugin]
|
||||
+ plugin = extensions_plugins[lib.lysc_get_ext_plugin(pext.plugin_ref)]
|
||||
context = Context(cdata=ctx)
|
||||
parsed_ext = ExtensionParsed(context, pext, None)
|
||||
plugin.parse_free_clb(parsed_ext)
|
||||
@@ -75,7 +75,9 @@ def libyang_c_lyplg_ext_parse_free_clb(ctx, pext):
|
||||
|
||||
@ffi.def_extern(name="lypy_lyplg_ext_compile_free_clb")
|
||||
def libyang_c_lyplg_ext_compile_free_clb(ctx, cext):
|
||||
- plugin = extensions_plugins[getattr(cext, "def").plugin]
|
||||
+ plugin = extensions_plugins[
|
||||
+ lib.lysc_get_ext_plugin(getattr(cext, "def").plugin_ref)
|
||||
+ ]
|
||||
context = Context(cdata=ctx)
|
||||
compiled_ext = ExtensionCompiled(context, cext)
|
||||
plugin.compile_free_clb(compiled_ext)
|
||||
@@ -200,9 +202,17 @@ def set_compile_ctx(self, cctx) -> None:
|
||||
def parse_substmts(self, ext: ExtensionParsed) -> int:
|
||||
return lib.lyplg_ext_parse_extension_instance(self._pctx, ext.cdata)
|
||||
|
||||
- def compile_substmts(self, pext: ExtensionParsed, cext: ExtensionCompiled) -> int:
|
||||
+ def compile_substmts(
|
||||
+ self,
|
||||
+ pext: ExtensionParsed,
|
||||
+ cext: ExtensionCompiled,
|
||||
+ parent: Optional[SNode] = None,
|
||||
+ ) -> int:
|
||||
return lib.lyplg_ext_compile_extension_instance(
|
||||
- self._cctx, pext.cdata, cext.cdata
|
||||
+ self._cctx,
|
||||
+ pext.cdata,
|
||||
+ cext.cdata,
|
||||
+ ffi.NULL if parent is None else parent.cdata,
|
||||
)
|
||||
|
||||
def free_parse_substmts(self, ext: ExtensionParsed) -> None:
|
||||
diff --git a/libyang/schema.py b/libyang/schema.py
|
||||
index 23c1b1b..f104a87 100644
|
||||
--- a/libyang/schema.py
|
||||
+++ b/libyang/schema.py
|
||||
@@ -1522,21 +1522,35 @@ def new(context: "libyang.Context", cdata) -> "SNode":
|
||||
# -------------------------------------------------------------------------------------
|
||||
@SNode.register(SNode.LEAF)
|
||||
class SLeaf(SNode):
|
||||
- __slots__ = ("cdata_leaf", "cdata_leaf_parsed")
|
||||
+ __slots__ = ("cdata_leaf", "cdata_leaf_parsed", "cdata_default_realtype")
|
||||
|
||||
def __init__(self, context: "libyang.Context", cdata):
|
||||
super().__init__(context, cdata)
|
||||
self.cdata_leaf = ffi.cast("struct lysc_node_leaf *", cdata)
|
||||
self.cdata_leaf_parsed = ffi.cast("struct lysp_node_leaf *", self.cdata_parsed)
|
||||
+ self.cdata_default_realtype = None
|
||||
|
||||
def default(self) -> Union[None, bool, int, str, float]:
|
||||
- if not self.cdata_leaf.dflt:
|
||||
+ if not self.cdata_leaf.dflt.str:
|
||||
return None
|
||||
- val = lib.lyd_value_get_canonical(self.context.cdata, self.cdata_leaf.dflt)
|
||||
- if not val:
|
||||
- return None
|
||||
- val = c2str(val)
|
||||
- val_type = Type(self.context, self.cdata_leaf.dflt.realtype, None)
|
||||
+
|
||||
+ if self.cdata_default_realtype is None:
|
||||
+ # calculate real type of default value just once
|
||||
+ val_type_cdata = ffi.new("struct lysc_type **", ffi.NULL)
|
||||
+ ret = lib.lyd_value_validate_dflt(
|
||||
+ self.cdata,
|
||||
+ self.cdata_leaf.dflt.str,
|
||||
+ self.cdata_leaf.dflt.prefixes,
|
||||
+ ffi.NULL,
|
||||
+ val_type_cdata,
|
||||
+ ffi.NULL,
|
||||
+ )
|
||||
+ if ret != lib.LY_SUCCESS:
|
||||
+ raise self.context.error("Unable to get real type of default value")
|
||||
+ self.cdata_default_realtype = Type(self.context, val_type_cdata[0], None)
|
||||
+
|
||||
+ val = c2str(self.cdata_leaf.dflt.str)
|
||||
+ val_type = self.cdata_default_realtype
|
||||
if val_type.base() == Type.BOOL:
|
||||
return val == "true"
|
||||
if val_type.base() in Type.NUM_TYPES:
|
||||
@@ -1563,7 +1577,7 @@ def __str__(self):
|
||||
# -------------------------------------------------------------------------------------
|
||||
@SNode.register(SNode.LEAFLIST)
|
||||
class SLeafList(SNode):
|
||||
- __slots__ = ("cdata_leaflist", "cdata_leaflist_parsed")
|
||||
+ __slots__ = ("cdata_leaflist", "cdata_leaflist_parsed", "cdata_default_realtypes")
|
||||
|
||||
def __init__(self, context: "libyang.Context", cdata):
|
||||
super().__init__(context, cdata)
|
||||
@@ -1571,6 +1585,7 @@ def __init__(self, context: "libyang.Context", cdata):
|
||||
self.cdata_leaflist_parsed = ffi.cast(
|
||||
"struct lysp_node_leaflist *", self.cdata_parsed
|
||||
)
|
||||
+ self.cdata_default_realtypes = None
|
||||
|
||||
def ordered(self) -> bool:
|
||||
return bool(self.cdata_parsed.flags & lib.LYS_ORDBY_USER)
|
||||
@@ -1586,12 +1601,37 @@ def type(self) -> Type:
|
||||
def defaults(self) -> Iterator[Union[None, bool, int, str, float]]:
|
||||
if self.cdata_leaflist.dflts == ffi.NULL:
|
||||
return
|
||||
- for dflt in ly_array_iter(self.cdata_leaflist.dflts):
|
||||
- val = lib.lyd_value_get_canonical(self.context.cdata, dflt)
|
||||
- if not val:
|
||||
+
|
||||
+ if self.cdata_default_realtypes is None:
|
||||
+ # calculate real types of default values just once
|
||||
+ val_type_cdata = ffi.new("struct lysc_type **", ffi.NULL)
|
||||
+ self.cdata_default_realtypes = []
|
||||
+ for dflt in ly_array_iter(self.cdata_leaflist.dflts):
|
||||
+ if not dflt.str:
|
||||
+ self.cdata_default_realtypes.append(None)
|
||||
+ continue
|
||||
+ val_type_cdata[0] = ffi.NULL
|
||||
+ ret = lib.lyd_value_validate_dflt(
|
||||
+ self.cdata,
|
||||
+ dflt.str,
|
||||
+ dflt.prefixes,
|
||||
+ ffi.NULL,
|
||||
+ val_type_cdata,
|
||||
+ ffi.NULL,
|
||||
+ )
|
||||
+ if ret != lib.LY_SUCCESS:
|
||||
+ raise self.context.error("Unable to get real type of default value")
|
||||
+ self.cdata_default_realtypes.append(
|
||||
+ Type(self.context, val_type_cdata[0], None)
|
||||
+ )
|
||||
+
|
||||
+ for dflt, val_type in zip(
|
||||
+ ly_array_iter(self.cdata_leaflist.dflts), self.cdata_default_realtypes
|
||||
+ ):
|
||||
+ if not dflt.str:
|
||||
yield None
|
||||
- val = c2str(val)
|
||||
- val_type = Type(self.context, dflt.realtype, None)
|
||||
+ continue
|
||||
+ val = c2str(dflt.str)
|
||||
if val_type.base() == Type.BOOL:
|
||||
yield val == "true"
|
||||
elif val_type.base() in Type.NUM_TYPES:
|
||||
diff --git a/tests/test_context.py b/tests/test_context.py
|
||||
index 61c0ae8..8ffd045 100644
|
||||
--- a/tests/test_context.py
|
||||
+++ b/tests/test_context.py
|
||||
@@ -20,7 +20,11 @@ def test_ctx_no_dir(self):
|
||||
self.assertIsNot(ctx, None)
|
||||
|
||||
def test_ctx_yanglib(self):
|
||||
- ctx = Context(YANG_DIR, yanglib_path=YANG_DIR + "/yang-library.json")
|
||||
+ ctx = Context(
|
||||
+ YANG_DIR,
|
||||
+ yanglib_path=YANG_DIR + "/yang-library.json",
|
||||
+ compile_obsolete=True,
|
||||
+ )
|
||||
ctx.load_module("yolo-system")
|
||||
dnode = ctx.get_yanglib_data()
|
||||
j = dnode.print_mem("json", with_siblings=True)
|
||||
diff --git a/tests/test_data.py b/tests/test_data.py
|
||||
index 430873a..8f56dc1 100644
|
||||
--- a/tests/test_data.py
|
||||
+++ b/tests/test_data.py
|
||||
@@ -33,7 +33,7 @@
|
||||
# -------------------------------------------------------------------------------------
|
||||
class DataTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
- self.ctx = Context(YANG_DIR)
|
||||
+ self.ctx = Context(YANG_DIR, compile_obsolete=True)
|
||||
modules = [
|
||||
self.ctx.load_module("ietf-netconf"),
|
||||
self.ctx.load_module("yolo-system"),
|
||||
@@ -51,18 +51,18 @@ def tearDown(self):
|
||||
"yolo-system:conf": {
|
||||
"hostname": "foo",
|
||||
"url": [
|
||||
- {
|
||||
- "proto": "https",
|
||||
- "host": "github.com",
|
||||
- "path": "/CESNET/libyang-python",
|
||||
- "enabled": false
|
||||
- },
|
||||
{
|
||||
"proto": "http",
|
||||
"host": "foobar.com",
|
||||
"port": 8080,
|
||||
"path": "/index.html",
|
||||
"enabled": true
|
||||
+ },
|
||||
+ {
|
||||
+ "proto": "https",
|
||||
+ "host": "github.com",
|
||||
+ "path": "/CESNET/libyang-python",
|
||||
+ "enabled": false
|
||||
}
|
||||
],
|
||||
"number": [
|
||||
@@ -76,7 +76,9 @@ def tearDown(self):
|
||||
"""
|
||||
|
||||
def test_data_parse_config_json(self):
|
||||
- dnode = self.ctx.parse_data_mem(self.JSON_CONFIG, "json", no_state=True)
|
||||
+ dnode = self.ctx.parse_data_mem(
|
||||
+ self.JSON_CONFIG, "json", no_state=True, ordered=True
|
||||
+ )
|
||||
self.assertIsInstance(dnode, DContainer)
|
||||
try:
|
||||
j = dnode.print_mem("json", with_siblings=True)
|
||||
@@ -91,18 +93,18 @@ def test_data_parse_config_json(self):
|
||||
"yolo-system:conf": {
|
||||
"hostname": "foo",
|
||||
"url": [
|
||||
- {
|
||||
- "proto": "https",
|
||||
- "host": "github.com",
|
||||
- "path": "/CESNET/libyang-python",
|
||||
- "enabled": false
|
||||
- },
|
||||
{
|
||||
"proto": "http",
|
||||
"host": "foobar.com",
|
||||
"port": 8080,
|
||||
"path": "/index.html",
|
||||
"enabled": true
|
||||
+ },
|
||||
+ {
|
||||
+ "proto": "https",
|
||||
+ "host": "github.com",
|
||||
+ "path": "/CESNET/libyang-python",
|
||||
+ "enabled": false
|
||||
}
|
||||
],
|
||||
"number": [
|
||||
@@ -128,12 +130,6 @@ def test_data_parse_config_json_without_yang_lib(self):
|
||||
"yolo-system:conf": {
|
||||
"hostname": "foo",
|
||||
"url": [
|
||||
- {
|
||||
- "proto": "https",
|
||||
- "host": "github.com",
|
||||
- "path": "/CESNET/libyang-python",
|
||||
- "enabled": false
|
||||
- },
|
||||
{
|
||||
"proto": "http",
|
||||
"host": "barfoo.com",
|
||||
@@ -145,6 +141,12 @@ def test_data_parse_config_json_without_yang_lib(self):
|
||||
"port": 8080,
|
||||
"path": "/index.html",
|
||||
"enabled": true
|
||||
+ },
|
||||
+ {
|
||||
+ "proto": "https",
|
||||
+ "host": "github.com",
|
||||
+ "path": "/CESNET/libyang-python",
|
||||
+ "enabled": false
|
||||
}
|
||||
],
|
||||
"number": [
|
||||
@@ -254,7 +256,9 @@ def test_data_parse_state_json(self):
|
||||
"""
|
||||
|
||||
def test_data_parse_config_xml(self):
|
||||
- dnode = self.ctx.parse_data_mem(self.XML_CONFIG, "xml", validate_present=True)
|
||||
+ dnode = self.ctx.parse_data_mem(
|
||||
+ self.XML_CONFIG, "xml", validate_present=True, ordered=True
|
||||
+ )
|
||||
self.assertIsInstance(dnode, DContainer)
|
||||
try:
|
||||
xml = dnode.print_mem("xml", with_siblings=True, trim_default_values=True)
|
||||
@@ -509,6 +513,7 @@ def test_data_from_dict_module_free_func(self):
|
||||
}
|
||||
|
||||
def test_data_from_dict_module_with_prefix(self):
|
||||
+ self.maxDiff = None
|
||||
module = self.ctx.get_module("yolo-system")
|
||||
dnode = module.parse_data_dict(
|
||||
self.DICT_CONFIG_WITH_PREFIX, strict=True, validate_present=True
|
||||
@@ -853,17 +858,17 @@ def test_data_diff(self):
|
||||
TREE = [
|
||||
"/yolo-system:conf",
|
||||
"/yolo-system:conf/hostname",
|
||||
- "/yolo-system:conf/url[proto='https'][host='github.com']",
|
||||
- "/yolo-system:conf/url[proto='https'][host='github.com']/proto",
|
||||
- "/yolo-system:conf/url[proto='https'][host='github.com']/host",
|
||||
- "/yolo-system:conf/url[proto='https'][host='github.com']/path",
|
||||
- "/yolo-system:conf/url[proto='https'][host='github.com']/enabled",
|
||||
"/yolo-system:conf/url[proto='http'][host='foobar.com']",
|
||||
"/yolo-system:conf/url[proto='http'][host='foobar.com']/proto",
|
||||
"/yolo-system:conf/url[proto='http'][host='foobar.com']/host",
|
||||
"/yolo-system:conf/url[proto='http'][host='foobar.com']/port",
|
||||
"/yolo-system:conf/url[proto='http'][host='foobar.com']/path",
|
||||
"/yolo-system:conf/url[proto='http'][host='foobar.com']/enabled",
|
||||
+ "/yolo-system:conf/url[proto='https'][host='github.com']",
|
||||
+ "/yolo-system:conf/url[proto='https'][host='github.com']/proto",
|
||||
+ "/yolo-system:conf/url[proto='https'][host='github.com']/host",
|
||||
+ "/yolo-system:conf/url[proto='https'][host='github.com']/path",
|
||||
+ "/yolo-system:conf/url[proto='https'][host='github.com']/enabled",
|
||||
"/yolo-system:conf/number[.='1000']",
|
||||
"/yolo-system:conf/number[.='2000']",
|
||||
"/yolo-system:conf/number[.='3000']",
|
||||
@@ -906,7 +911,7 @@ def test_find_all(self):
|
||||
}
|
||||
]
|
||||
}
|
||||
- self.assertEqual(urls[0].print_dict(absolute=False), expected_url)
|
||||
+ self.assertEqual(urls[1].print_dict(absolute=False), expected_url)
|
||||
finally:
|
||||
dnode.free()
|
||||
|
||||
@@ -1090,7 +1095,9 @@ def test_dnode_leafref_linking(self):
|
||||
"yolo-leafref-extended:ref1": "val1"
|
||||
}"""
|
||||
self.ctx.destroy()
|
||||
- self.ctx = Context(YANG_DIR, leafref_extended=True, leafref_linking=True)
|
||||
+ self.ctx = Context(
|
||||
+ YANG_DIR, leafref_extended=True, leafref_linking=True, compile_obsolete=True
|
||||
+ )
|
||||
mod = self.ctx.load_module("yolo-leafref-extended")
|
||||
self.assertIsInstance(mod, Module)
|
||||
dnode1 = self.ctx.parse_data_mem(MAIN, "json", parse_only=True)
|
||||
@@ -1121,7 +1128,7 @@ def test_dnode_builtin_plugins_only(self):
|
||||
MAIN = {"yolo-nodetypes:ip-address": "test"}
|
||||
self.tearDown()
|
||||
gc.collect()
|
||||
- self.ctx = Context(YANG_DIR, builtin_plugins_only=True)
|
||||
+ self.ctx = Context(YANG_DIR, builtin_plugins_only=True, compile_obsolete=True)
|
||||
module = self.ctx.load_module("yolo-nodetypes")
|
||||
dnode = dict_to_dnode(MAIN, module, None, validate=False, store_only=True)
|
||||
self.assertIsInstance(dnode, DLeaf)
|
||||
@@ -1140,7 +1147,7 @@ def test_merge_builtin_plugins_only(self):
|
||||
MAIN = {"yolo-nodetypes:ip-address": "test"}
|
||||
self.tearDown()
|
||||
gc.collect()
|
||||
- self.ctx = Context(YANG_DIR, builtin_plugins_only=True)
|
||||
+ self.ctx = Context(YANG_DIR, builtin_plugins_only=True, compile_obsolete=True)
|
||||
module = self.ctx.load_module("yolo-nodetypes")
|
||||
dnode = module.parse_data_dict(MAIN, validate=False, store_only=True)
|
||||
self.assertIsInstance(dnode, DLeaf)
|
||||
diff --git a/tests/test_diff.py b/tests/test_diff.py
|
||||
index d4b7e87..2263e34 100644
|
||||
--- a/tests/test_diff.py
|
||||
+++ b/tests/test_diff.py
|
||||
@@ -97,7 +97,9 @@ class DiffTest(unittest.TestCase):
|
||||
)
|
||||
|
||||
def test_diff(self):
|
||||
- with Context(OLD_YANG_DIR) as ctx_old, Context(NEW_YANG_DIR) as ctx_new:
|
||||
+ with Context(OLD_YANG_DIR, compile_obsolete=True) as ctx_old, Context(
|
||||
+ NEW_YANG_DIR, compile_obsolete=True
|
||||
+ ) as ctx_new:
|
||||
mod = ctx_old.load_module("yolo-system")
|
||||
mod.feature_enable_all()
|
||||
mod = ctx_new.load_module("yolo-system")
|
||||
diff --git a/tests/test_schema.py b/tests/test_schema.py
|
||||
index b1862ab..a1ca412 100644
|
||||
--- a/tests/test_schema.py
|
||||
+++ b/tests/test_schema.py
|
||||
@@ -272,7 +272,7 @@ def test_iffeature_dump(self):
|
||||
# -------------------------------------------------------------------------------------
|
||||
class ContainerTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
- self.ctx = Context(YANG_DIR)
|
||||
+ self.ctx = Context(YANG_DIR, compile_obsolete=True)
|
||||
mod = self.ctx.load_module("yolo-system")
|
||||
mod.feature_enable_all()
|
||||
self.container = next(self.ctx.find_path("/yolo-system:conf"))
|
||||
@@ -549,7 +549,7 @@ def test_rpc_parsed(self):
|
||||
# -------------------------------------------------------------------------------------
|
||||
class LeafTypeTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
- self.ctx = Context(YANG_DIR)
|
||||
+ self.ctx = Context(YANG_DIR, compile_obsolete=True)
|
||||
self.ctx.load_module("yolo-system")
|
||||
|
||||
def tearDown(self):
|
||||
Reference in New Issue
Block a user