Skip to content

Commit f14116c

Browse files
stewegsamuel-gauthier
authored andcommitted
data: add leafref_nodes and leafref_link_node_tree
This patch adds API, which allows user to: - determine if DNode is being referenced by some other leafref DNodes. - trigger process for creating cross-references between leafref DNodes and target DNodes. Closes: #108 Signed-off-by: Stefan Gula <[email protected]> Signed-off-by: Samuel Gauthier <[email protected]>
1 parent 47b0f09 commit f14116c

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

cffi/cdefs.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,5 +1248,14 @@ struct lyd_attr {
12481248
LY_ERR lyd_new_attr(struct lyd_node *, const char *, const char *, const char *, struct lyd_attr **);
12491249
void lyd_free_attr_single(const struct ly_ctx *ctx, struct lyd_attr *attr);
12501250

1251+
struct lyd_leafref_links_rec {
1252+
const struct lyd_node_term *node;
1253+
const struct lyd_node_term **leafref_nodes;
1254+
const struct lyd_node_term **target_nodes;
1255+
};
1256+
1257+
LY_ERR lyd_leafref_get_links(const struct lyd_node_term *e, const struct lyd_leafref_links_rec **);
1258+
LY_ERR lyd_leafref_link_node_tree(struct lyd_node *);
1259+
12511260
/* from libc, needed to free allocated strings */
12521261
void free(void *);

libyang/data.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
SRpc,
1919
Type,
2020
)
21-
from .util import DataType, IOType, LibyangError, c2str, str2c
21+
from .util import DataType, IOType, LibyangError, c2str, ly_array_iter, str2c
2222

2323

2424
LOG = logging.getLogger(__name__)
@@ -991,6 +991,28 @@ def free(self, with_siblings: bool = True) -> None:
991991
finally:
992992
self.cdata = ffi.NULL
993993

994+
def leafref_link_node_tree(self) -> None:
995+
"""
996+
Traverse through data tree including root node siblings and adds
997+
leafrefs links to the given nodes.
998+
999+
Requires leafref_linking to be set on the libyang context.
1000+
"""
1001+
lib.lyd_leafref_link_node_tree(self.cdata)
1002+
1003+
def leafref_nodes(self) -> Iterator["DNode"]:
1004+
"""
1005+
Gets the leafref links record for given node.
1006+
1007+
Requires leafref_linking to be set on the libyang context.
1008+
"""
1009+
term_node = ffi.cast("struct lyd_node_term *", self.cdata)
1010+
out = ffi.new("const struct lyd_leafref_links_rec **")
1011+
if lib.lyd_leafref_get_links(term_node, out) != lib.LY_SUCCESS:
1012+
return
1013+
for n in ly_array_iter(out[0].leafref_nodes):
1014+
yield DNode.new(self.context, n)
1015+
9941016
def __repr__(self):
9951017
cls = self.__class__
9961018
return "<%s.%s: %s>" % (cls.__module__, cls.__name__, str(self))

tests/test_data.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
DRpc,
2222
IOType,
2323
LibyangError,
24+
Module,
2425
)
2526
from libyang.data import dict_to_dnode
2627

@@ -1066,3 +1067,28 @@ def test_dnode_attrs_set_and_remove_multiple(self):
10661067

10671068
attrs.remove("ietf-netconf:operation")
10681069
self.assertEqual(len(attrs), 0)
1070+
1071+
def test_dnode_leafref_linking(self):
1072+
MAIN = """{
1073+
"yolo-leafref-extended:list1": [{
1074+
"leaf1": "val1",
1075+
"leaflist2": ["val2", "val3"]
1076+
}],
1077+
"yolo-leafref-extended:ref1": "val1"
1078+
}"""
1079+
self.ctx.destroy()
1080+
self.ctx = Context(YANG_DIR, leafref_extended=True, leafref_linking=True)
1081+
mod = self.ctx.load_module("yolo-leafref-extended")
1082+
self.assertIsInstance(mod, Module)
1083+
dnode1 = self.ctx.parse_data_mem(MAIN, "json", parse_only=True)
1084+
self.assertIsInstance(dnode1, DList)
1085+
dnode2 = next(dnode1.siblings(include_self=False))
1086+
self.assertIsInstance(dnode2, DLeaf)
1087+
dnode3 = next(dnode1.children())
1088+
self.assertIsInstance(dnode3, DLeaf)
1089+
self.assertIsNone(next(dnode3.leafref_nodes(), None))
1090+
dnode2.leafref_link_node_tree()
1091+
dnode4 = next(dnode3.leafref_nodes())
1092+
self.assertIsInstance(dnode4, DLeaf)
1093+
self.assertEqual(dnode4.cdata, dnode2.cdata)
1094+
dnode1.free()

0 commit comments

Comments
 (0)