Skip to content

Commit

Permalink
ability to include children
Browse files Browse the repository at this point in the history
  • Loading branch information
bradh352 committed Feb 13, 2025
1 parent 14ad790 commit e6c77f1
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 19 deletions.
2 changes: 1 addition & 1 deletion cffi/cdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1353,6 +1353,6 @@ void free(void *);

/* From source.c custom C code helpers for backlinks */
size_t pyly_backlinks_xpath_leafrefs(const struct ly_ctx *ctx, const char *xpath, char ***out);
size_t pyly_backlinks_find_leafref_nodes(const struct ly_ctx *ctx, const char *base_path, char ***out);
size_t pyly_backlinks_find_leafref_nodes(const struct ly_ctx *ctx, const char *base_path, int include_children, char ***out);

void pyly_cstr_array_free(char **list, size_t nlist);
21 changes: 13 additions & 8 deletions cffi/source.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ void pyly_cstr_array_free(char **list, size_t nlist)
typedef struct {
const struct ly_ctx *ctx;
const char *base_path;
int include_children;
pyly_string_list_t *res;
} pyly_dfs_data_t;

Expand Down Expand Up @@ -208,7 +209,8 @@ static LY_ERR pyly_backlinks_find_leafref_nodes_clb(struct lysc_node *node, void

/*! Search the entire loaded schema for any nodes that contain a leafref and
* record the path. If a base_path is specified, only leafrefs that point to
* the specified path will be recorded.
* the specified path will be recorded, if include_children is 1, then children
* of the specified path are also included.
*
* This function is used in replacement for the concept of backlink references
* that were part of libyang v1 but were subsequently removed. This is
Expand All @@ -221,14 +223,17 @@ static LY_ERR pyly_backlinks_find_leafref_nodes_clb(struct lysc_node *node, void
* the leafref is pointing as part of building the cache. It is expected most
* users will not need the cache and will simply pass in the base_path as needed.
*
* \param[in] ctx Initialized context with loaded schema
* \param[in] base_path Optional base node path to restrict output.
* \param[out] out Pointer passed by reference that will hold a C array
* of c strings representing the paths for any leaf
* references.
* \param[in] ctx Initialized context with loaded schema
* \param[in] base_path Optional base node path to restrict output.
* \param[in] include_children Whether or not to include children of the
* specified base path or if the path is an
* explicit reference.
* \param[out] out Pointer passed by reference that will hold a C
* array of c strings representing the paths for
* any leaf references.
* \return number of results, or 0 if none.
*/
size_t pyly_backlinks_find_leafref_nodes(const struct ly_ctx *ctx, const char *base_path, char ***out)
size_t pyly_backlinks_find_leafref_nodes(const struct ly_ctx *ctx, const char *base_path, int include_children, char ***out)
{
pyly_string_list_t res;
uint32_t module_idx = 0;
Expand All @@ -242,7 +247,7 @@ size_t pyly_backlinks_find_leafref_nodes(const struct ly_ctx *ctx, const char *b

/* Iterate across all loaded modules */
for (module_idx = 0; (module = ly_ctx_get_module_iter(ctx, &module_idx)) != NULL; ) {
pyly_dfs_data_t data = { ctx, base_path, &res };
pyly_dfs_data_t data = { ctx, base_path, include_children, &res };

lysc_module_dfs_full(module, pyly_backlinks_find_leafref_nodes_clb, &data);
/* Ignore error */
Expand Down
4 changes: 2 additions & 2 deletions libyang/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,15 +646,15 @@ def parse_data_file(
json_null=json_null,
)

def backlinks_find_leafref_nodes(self, base_path: str = None) -> list[str]:
def backlinks_find_leafref_nodes(self, base_path: str = None, include_children: bool = False) -> list[str]:
if self.cdata is None:
raise RuntimeError("context already destroyed")

out = []

carray = ffi.new("char ***")
clen = lib.pyly_backlinks_find_leafref_nodes(
self.cdata, str2c(base_path), carray
self.cdata, str2c(base_path), 1 if include_children else 0, carray
)
if clen == 0:
return out
Expand Down
47 changes: 41 additions & 6 deletions tests/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -813,23 +813,58 @@ def tearDown(self):
self.ctx = None

def test_backlinks_all_nodes(self):
expected = [
"/yolo-leafref-search-extmod:my_extref_list/my_extref",
"/yolo-leafref-search:refstr",
"/yolo-leafref-search:refnum",
"/yolo-leafref-search-extmod:my_extref_list/my_extref_union"
]
refs = self.ctx.backlinks_find_leafref_nodes()
assert len(refs) == 3

expected.sort()
refs.sort()
self.assertEqual(expected, refs)

def test_backlinks_one(self):
expected = [
"/yolo-leafref-search-extmod:my_extref_list/my_extref",
"/yolo-leafref-search:refstr",
"/yolo-leafref-search-extmod:my_extref_list/my_extref_union"
]
refs = self.ctx.backlinks_find_leafref_nodes(
base_path="/yolo-leafref-search:my_list/my_leaf_string"
)
assert len(refs) == 3
assert "/yolo-leafref-search-extmod:my_extref_list/my_extref" in refs
assert "/yolo-leafref-search:ref1" in refs
assert "/yolo-leafref-search-extmod:my_extref_list/my_extref_union" in refs

expected.sort()
refs.sort()
self.assertEqual(expected, refs)

def test_backlinks_children(self):
expected = [
"/yolo-leafref-search-extmod:my_extref_list/my_extref",
"/yolo-leafref-search:refstr",
"/yolo-leafref-search:refnum",
"/yolo-leafref-search-extmod:my_extref_list/my_extref_union"
]
refs = self.ctx.backlinks_find_leafref_nodes(
base_path="/yolo-leafref-search:my_list/"
)

expecte.sort()
refs.sort()
self.assertEqual(expected, refs)

def test_backlinks_xpath_leafrefs(self):
expected = [
"/leafref-search:my_list/leafref-search:my_leaf_string"
]
refs = self.ctx.backlinks_xpath_leafrefs(
"/yolo-leafref-search-extmod:my_extref_list/my_extref"
)
assert len(refs) > 0

expected.sort()
refs.sort()
self.assertEqual(expected, refs)


# -------------------------------------------------------------------------------------
Expand Down
12 changes: 10 additions & 2 deletions tests/yang/yolo/yolo-leafref-search.yang
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,24 @@ module yolo-leafref-search {
leaf my_leaf_string {
type string;
}
leaf-list my_leaf_list_number {
leaf-list my_leaf_number {
description
"A number.";
type types:number;
}
}

leaf ref1 {
leaf refstr {
type leafref {
path "../my_list/my_leaf_string";
}
}

leaf refnum {
type leafref {
path "../my_list/my_leaf_number";
}
}

leaf
}

0 comments on commit e6c77f1

Please sign in to comment.