Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cffi/cdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ struct lys_module* ly_ctx_get_module_latest(const struct ly_ctx *, const char *)
LY_ERR ly_ctx_compile(struct ly_ctx *);

LY_ERR lys_find_xpath(const struct ly_ctx *, const struct lysc_node *, const char *, uint32_t, struct ly_set **);
LY_ERR lys_find_xpath_atoms(const struct ly_ctx *, const struct lysc_node *, const char *, uint32_t, struct ly_set **);
void ly_set_free(struct ly_set *, void(*)(void *obj));

struct ly_set {
Expand Down
32 changes: 32 additions & 0 deletions libyang/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,38 @@ def find_path(
finally:
lib.ly_set_free(node_set, ffi.NULL)

def find_xpath_atoms(
self,
path: str,
output: bool = False,
root_node: Optional["libyang.SNode"] = None,
) -> Iterator[SNode]:
if self.cdata is None:
raise RuntimeError("context already destroyed")

if root_node is not None:
ctx_node = root_node.cdata
else:
ctx_node = ffi.NULL

flags = lib.LYS_FIND_XP_OUTPUT if output else 0

node_set = ffi.new("struct ly_set **")
if (
lib.lys_find_xpath_atoms(self.cdata, ctx_node, str2c(path), flags, node_set)
!= lib.LY_SUCCESS
):
raise self.error("cannot find path")

node_set = node_set[0]
if node_set.count == 0:
raise self.error("cannot find path")
try:
for i in range(node_set.count):
yield SNode.new(self, node_set.snodes[i])
finally:
lib.ly_set_free(node_set, ffi.NULL)

def find_jsonpath(
self,
path: str,
Expand Down
18 changes: 17 additions & 1 deletion tests/test_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import os
import unittest

from libyang import Context, LibyangError, Module, SLeaf, SLeafList
from libyang import Context, LibyangError, Module, SContainer, SLeaf, SLeafList
from libyang.util import c2str


Expand Down Expand Up @@ -95,6 +95,22 @@ def test_ctx_find_path(self):
node2 = next(ctx.find_path("../number", root_node=node))
self.assertIsInstance(node2, SLeafList)

def test_ctx_find_xpath_atoms(self):
with Context(YANG_DIR) as ctx:
ctx.load_module("yolo-system")
node_iter = ctx.find_xpath_atoms("/yolo-system:conf/offline")
node = next(node_iter)
self.assertIsInstance(node, SContainer)
node = next(node_iter)
self.assertIsInstance(node, SLeaf)
node_iter = ctx.find_xpath_atoms("../number", root_node=node)
node = next(node_iter)
self.assertIsInstance(node, SLeaf)
node = next(node_iter)
self.assertIsInstance(node, SContainer)
node = next(node_iter)
self.assertIsInstance(node, SLeafList)

def test_ctx_iter_modules(self):
with Context(YANG_DIR) as ctx:
ctx.load_module("yolo-system")
Expand Down