diff --git a/libyang/schema.py b/libyang/schema.py index 6b0c803b..4f243ea8 100644 --- a/libyang/schema.py +++ b/libyang/schema.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: MIT from contextlib import suppress -from typing import IO, Any, Dict, Iterator, Optional, Tuple, Union +from typing import IO, Any, Dict, Iterator, List, Optional, Tuple, Union from _libyang import ffi, lib from .util import IOType, LibyangError, c2str, init_output, ly_array_iter, str2c @@ -1293,6 +1293,12 @@ def must_conditions(self) -> Iterator[str]: for must in ly_array_iter(pdata.musts): yield c2str(must.arg.str) + def max_elements(self) -> int: + return self.cdata_leaflist.max if self.cdata_leaflist.max != 0 else None + + def min_elements(self) -> int: + return self.cdata_leaflist.min + def __str__(self): return "%s %s" % (self.name(), self.type().name()) @@ -1384,6 +1390,23 @@ def must_conditions(self) -> Iterator[str]: for must in ly_array_iter(pdata.musts): yield c2str(must.arg.str) + def max_elements(self) -> int: + return self.cdata_list.max if self.cdata_list.max != 0 else None + + def min_elements(self) -> int: + return self.cdata_list.min + + def uniques(self) -> Iterator[List[SNode]]: + if self.cdata_list == ffi.NULL: + return + if self.cdata_list.uniques == ffi.NULL: + return + for unique in ly_array_iter(self.cdata_list.uniques): + nodes = [] + for node in ly_array_iter(unique): + nodes.append(SNode.new(self.context, node)) + yield nodes + def __str__(self): return "%s [%s]" % (self.name(), ", ".join(k.name() for k in self.keys())) diff --git a/tests/test_schema.py b/tests/test_schema.py index f493ba14..5c55b29b 100644 --- a/tests/test_schema.py +++ b/tests/test_schema.py @@ -328,6 +328,24 @@ def test_list_parent(self): self.assertIsInstance(parent, SContainer) self.assertEqual(parent.name(), "conf") + def test_list_min_max(self): + self.ctx.load_module("yolo-nodetypes") + self.list = next(self.ctx.find_path("/yolo-nodetypes:conf/list1")) + self.assertIsInstance(self.list, SList) + self.assertEqual(self.list.min_elements(), 2) + self.assertEqual(self.list.max_elements(), 10) + + def test_list_uniques(self): + self.ctx.load_module("yolo-nodetypes") + self.list = next(self.ctx.find_path("/yolo-nodetypes:conf/list1")) + self.assertIsInstance(self.list, SList) + uniques = [u for u in self.list.uniques()] + self.assertEqual(len(uniques), 1) + elements = [u.name() for u in uniques[0]] + self.assertEqual(len(elements), 2) + self.assertTrue("leaf2" in elements) + self.assertTrue("leaf3" in elements) + # ------------------------------------------------------------------------------------- class RpcTest(unittest.TestCase): @@ -474,3 +492,21 @@ def test_leaf_parent(self): def test_iter_tree(self): leaf = next(self.ctx.find_path("/yolo-system:conf")) self.assertEqual(len(list(leaf.iter_tree(full=True))), 23) + + +# ------------------------------------------------------------------------------------- +class LeafListTest(unittest.TestCase): + def setUp(self): + self.ctx = Context(YANG_DIR) + self.ctx.load_module("yolo-system") + + def tearDown(self): + self.ctx.destroy() + self.ctx = None + + def test_leaf_list_min_max(self): + self.ctx.load_module("yolo-nodetypes") + self.list = next(self.ctx.find_path("/yolo-nodetypes:conf/leaf-list1")) + self.assertIsInstance(self.list, SLeafList) + self.assertEqual(self.list.min_elements(), 3) + self.assertEqual(self.list.max_elements(), 11) diff --git a/tests/yang/yolo/yolo-nodetypes.yang b/tests/yang/yolo/yolo-nodetypes.yang new file mode 100644 index 00000000..8adc85a2 --- /dev/null +++ b/tests/yang/yolo/yolo-nodetypes.yang @@ -0,0 +1,54 @@ +module yolo-nodetypes { + yang-version 1.1; + namespace "urn:yang:yolo:nodetypes"; + prefix sys; + + description + "YOLO Nodetypes."; + + revision 2024-01-25 { + description + "Initial version."; + } + + container conf { + description + "Configuration."; + leaf percentage { + type decimal64 { + fraction-digits 2; + } + default 10.2; + } + + leaf-list ratios { + type decimal64 { + fraction-digits 2; + } + default 2.5; + default 2.6; + } + + list list1 { + key leaf1; + unique "leaf2 leaf3"; + min-elements 2; + max-elements 10; + leaf leaf1 { + type string; + } + leaf leaf2 { + type string; + } + leaf leaf3 { + type string; + } + } + + leaf-list leaf-list1 { + type string; + min-elements 3; + max-elements 11; + } + } +}