From 7b804bb79e06447b755fde9f2e02479c58e55ffa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 31 Oct 2025 09:07:32 +0000 Subject: [PATCH 1/7] Initial plan From 5d60c3c90b74474227fac91bc408af0e2dd17503 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 31 Oct 2025 09:17:25 +0000 Subject: [PATCH 2/7] Update cdefs.h for libyang devel compatibility - Change ly_ctx_new options parameter from uint16_t to uint32_t - Remove LYD_ANYDATA_LYB enum value (no longer supported in devel) - Remove mem field from lyd_any_value union Co-authored-by: tbsuht <126770680+tbsuht@users.noreply.github.com> --- cffi/cdefs.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cffi/cdefs.h b/cffi/cdefs.h index 52f00b2..7fa3d07 100644 --- a/cffi/cdefs.h +++ b/cffi/cdefs.h @@ -36,7 +36,7 @@ typedef enum { LY_EPLUGIN = 128 } LY_ERR; -LY_ERR ly_ctx_new(const char *, uint16_t, struct ly_ctx **); +LY_ERR ly_ctx_new(const char *, uint32_t, struct ly_ctx **); void ly_ctx_destroy(struct ly_ctx *); int ly_ctx_set_searchdir(struct ly_ctx *, const char *); @@ -1158,8 +1158,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 { @@ -1167,7 +1166,6 @@ union lyd_any_value { const char *str; const char *xml; const char *json; - char *mem; }; struct lyd_node_any { From ba2a63cceaad0c6525835c980bf5fe2c48b422aa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 31 Oct 2025 09:23:38 +0000 Subject: [PATCH 3/7] Update version requirements for libyang 4.0 - Update source.c to require libyang >= 4.0.0 - Update README to document libyang 4.0 requirement - Document compatibility with devel branch Co-authored-by: tbsuht <126770680+tbsuht@users.noreply.github.com> --- README.rst | 7 +++++-- cffi/source.c | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 4ea8977..fc7798f 100644 --- a/README.rst +++ b/README.rst @@ -43,11 +43,14 @@ On a Debian/Ubuntu system:: Compatibility ------------- -The current version requires at least C `libyang 2.25`__. +The current version requires at least C `libyang 4.0`__ (devel branch). + +For C `libyang 3.x`__, use an earlier version of these bindings. The last version of the bindings that works with C `libyang 1.x`__ is v1.7.0__. -__ https://github.com/CESNET/libyang/commit/d2f1608b348f +__ https://github.com/CESNET/libyang/tree/devel +__ https://github.com/CESNET/libyang/tree/master __ https://github.com/CESNET/libyang/tree/libyang1 __ https://pypi.org/project/libyang/1.7.0/ diff --git a/cffi/source.c b/cffi/source.c index 34e18b0..beb7f76 100644 --- a/cffi/source.c +++ b/cffi/source.c @@ -6,6 +6,6 @@ #include #include -#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 < 40000 +#error "This version of libyang bindings only works with libyang soversion 4.0.0+" #endif From 228476d9b51c31e5da3f47043feda93cbad027d3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 31 Oct 2025 09:26:32 +0000 Subject: [PATCH 4/7] Complete: libyang devel compatibility updates Co-authored-by: tbsuht <126770680+tbsuht@users.noreply.github.com> --- _codeql_detected_source_root | 1 + 1 file changed, 1 insertion(+) create mode 120000 _codeql_detected_source_root diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root new file mode 120000 index 0000000..945c9b4 --- /dev/null +++ b/_codeql_detected_source_root @@ -0,0 +1 @@ +. \ No newline at end of file From 3cc4dde1931b07a06ad14a39dc6fe7bb4b5b5acd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 31 Oct 2025 09:46:00 +0000 Subject: [PATCH 5/7] Fix API compatibility issues with libyang 4.0.12 - Add parse_options parameter to lyd_parse_op function - Add parent parameter to lyplg_ext_compile_extension_instance - Replace plugin pointer with plugin_ref (uintptr_t) in type structs - Remove code field from lysc_pattern struct - Replace def/record with plugin_ref in lysp_ext_instance - Remove latest_revision explicit field (now bit-field in opaque part) - Update all callback signatures to match new API Co-authored-by: tbsuht <126770680+tbsuht@users.noreply.github.com> --- cffi/cdefs.h | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/cffi/cdefs.h b/cffi/cdefs.h index 7fa3d07..2c37e74 100644 --- a/cffi/cdefs.h +++ b/cffi/cdefs.h @@ -350,7 +350,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, @@ -392,7 +392,6 @@ struct lys_module { struct lys_module **deviated_by; ly_bool implemented; ly_bool to_compile; - uint8_t latest_revision; ...; }; @@ -466,12 +465,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; @@ -782,7 +780,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; }; @@ -858,7 +856,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; }; @@ -981,7 +979,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; @@ -1016,7 +1013,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; @@ -1025,7 +1022,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; @@ -1035,7 +1032,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; @@ -1057,7 +1054,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; @@ -1066,7 +1063,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; @@ -1075,7 +1072,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; @@ -1087,7 +1084,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; @@ -1096,7 +1093,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; @@ -1105,7 +1102,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; @@ -1114,7 +1111,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; @@ -1331,11 +1328,11 @@ 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 *); -typedef LY_ERR (*lyplg_ext_compile_clb)(struct lysc_ctx *, const struct lysp_ext_instance *, struct lysc_ext_instance *); +typedef LY_ERR (*lyplg_ext_compile_clb)(struct lysc_ctx *, const struct lysp_ext_instance *, struct lysc_ext_instance *, struct lysc_node *); typedef void (*lyplg_ext_parse_free_clb)(const struct ly_ctx *, struct lysp_ext_instance *); typedef void (*lyplg_ext_compile_free_clb)(const struct ly_ctx *, struct lysc_ext_instance *); struct lyplg_ext { @@ -1358,7 +1355,7 @@ struct lyplg_ext_record { #define LYPLG_EXT_API_VERSION ... LY_ERR lyplg_add_extension_plugin(struct ly_ctx *, uint32_t, const struct lyplg_ext_record *); extern "Python" LY_ERR lypy_lyplg_ext_parse_clb(struct lysp_ctx *, struct lysp_ext_instance *); -extern "Python" LY_ERR lypy_lyplg_ext_compile_clb(struct lysc_ctx *, const struct lysp_ext_instance *, struct lysc_ext_instance *); +extern "Python" LY_ERR lypy_lyplg_ext_compile_clb(struct lysc_ctx *, const struct lysp_ext_instance *, struct lysc_ext_instance *, struct lysc_node *); extern "Python" void lypy_lyplg_ext_parse_free_clb(const struct ly_ctx *, struct lysp_ext_instance *); extern "Python" void lypy_lyplg_ext_compile_free_clb(const struct ly_ctx *, struct lysc_ext_instance *); From 2008c0bf987bf0c139834b5760b750293db882f1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 31 Oct 2025 09:59:24 +0000 Subject: [PATCH 6/7] Fix remaining struct field type mismatches for libyang 4.0 - Add lysc_value struct definition with str and prefixes fields - Change lysc_node_leaf.dflt from lyd_value* to lysc_value - Change lysc_node_leaflist.dflts from lyd_value** to lysc_value* - Add parent parameter to lyplg_ext_compile_clb Python callback - Update extension.py to use plugin_ref instead of record.plugin/def.plugin - Add forward declaration for lysc_prefix struct Co-authored-by: tbsuht <126770680+tbsuht@users.noreply.github.com> --- cffi/cdefs.h | 11 +++++++++-- libyang/extension.py | 10 +++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/cffi/cdefs.h b/cffi/cdefs.h index 2c37e74..1fc66e1 100644 --- a/cffi/cdefs.h +++ b/cffi/cdefs.h @@ -607,6 +607,13 @@ struct lysp_node_container { ...; }; +struct lysc_prefix; + +struct lysc_value { + const char *str; + struct lysc_prefix *prefixes; +}; + struct lysc_node_leaf { union { struct lysc_node node; @@ -620,7 +627,7 @@ struct lysc_node_leaf { struct lysc_when **when; struct lysc_type *type; const char *units; - struct lyd_value *dflt; + struct lysc_value dflt; ...; }; @@ -650,7 +657,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; ...; diff --git a/libyang/extension.py b/libyang/extension.py index 57f7cb2..780fdeb 100644 --- a/libyang/extension.py +++ b/libyang/extension.py @@ -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[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) @@ -45,8 +45,8 @@ 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] +def libyang_c_lyplg_ext_compile_clb(cctx, pext, cext, parent): + plugin = extensions_plugins[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[pext.plugin_ref] context = Context(cdata=ctx) parsed_ext = ExtensionParsed(context, pext, None) plugin.parse_free_clb(parsed_ext) @@ -75,7 +75,7 @@ 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[getattr(cext, "def").plugin_ref] context = Context(cdata=ctx) compiled_ext = ExtensionCompiled(context, cext) plugin.compile_free_clb(compiled_ext) From 8c9e010ea22bc227c40faf48cf93d60633e1c732 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 31 Oct 2025 10:05:46 +0000 Subject: [PATCH 7/7] Fix lyplg_ext_compile_clb callback signature (3 params not 4) The callback typedef should have 3 parameters, not 4: - lyplg_ext_compile_clb has 3 params (no parent) - lyplg_ext_compile_extension_instance function has 4 params (includes parent) Fixed: - Removed parent parameter from lyplg_ext_compile_clb typedef - Removed parent from extern Python callback declaration - Removed parent parameter from Python callback implementation Co-authored-by: tbsuht <126770680+tbsuht@users.noreply.github.com> --- cffi/cdefs.h | 4 ++-- libyang/extension.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cffi/cdefs.h b/cffi/cdefs.h index 1fc66e1..8e95225 100644 --- a/cffi/cdefs.h +++ b/cffi/cdefs.h @@ -1339,7 +1339,7 @@ LY_ERR lyplg_ext_compile_extension_instance(struct lysc_ctx *, const struct lysp 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 *); -typedef LY_ERR (*lyplg_ext_compile_clb)(struct lysc_ctx *, const struct lysp_ext_instance *, struct lysc_ext_instance *, struct lysc_node *); +typedef LY_ERR (*lyplg_ext_compile_clb)(struct lysc_ctx *, const struct lysp_ext_instance *, struct lysc_ext_instance *); typedef void (*lyplg_ext_parse_free_clb)(const struct ly_ctx *, struct lysp_ext_instance *); typedef void (*lyplg_ext_compile_free_clb)(const struct ly_ctx *, struct lysc_ext_instance *); struct lyplg_ext { @@ -1362,7 +1362,7 @@ struct lyplg_ext_record { #define LYPLG_EXT_API_VERSION ... LY_ERR lyplg_add_extension_plugin(struct ly_ctx *, uint32_t, const struct lyplg_ext_record *); extern "Python" LY_ERR lypy_lyplg_ext_parse_clb(struct lysp_ctx *, struct lysp_ext_instance *); -extern "Python" LY_ERR lypy_lyplg_ext_compile_clb(struct lysc_ctx *, const struct lysp_ext_instance *, struct lysc_ext_instance *, struct lysc_node *); +extern "Python" LY_ERR lypy_lyplg_ext_compile_clb(struct lysc_ctx *, const struct lysp_ext_instance *, struct lysc_ext_instance *); extern "Python" void lypy_lyplg_ext_parse_free_clb(const struct ly_ctx *, struct lysp_ext_instance *); extern "Python" void lypy_lyplg_ext_compile_free_clb(const struct ly_ctx *, struct lysc_ext_instance *); diff --git a/libyang/extension.py b/libyang/extension.py index 780fdeb..2ff3f22 100644 --- a/libyang/extension.py +++ b/libyang/extension.py @@ -45,7 +45,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, parent): +def libyang_c_lyplg_ext_compile_clb(cctx, pext, cext): plugin = extensions_plugins[pext.plugin_ref] context = Context(cdata=lib.lyplg_ext_compile_get_ctx(cctx)) module = Module(context, cext.module)