Skip to content

Commit 5681ef0

Browse files
stewegsamuel-gauthier
authored andcommitted
schema: support LYS_GETNEXT_WITH{CASE,CHOICE}
Add support for LYS_GETNEXT_WITH{CASE,CHOICE} for Module, Container, Choice and Case. To do so, introduce a new iter_children_options function that translates booleans to lys_getnext options. The Rpc children function is updated to use the iter_children_options mecanism. The lib.LYS_CHOICE and lib.LYS_CASE are added by to the default types in iter_children, as it does not change the behavior. Fixes: #91 Signed-off-by: Stefan Gula <steweg@gmail.com> Signed-off-by: Samuel Gauthier <samuel.gauthier@6wind.com>
1 parent a6c7164 commit 5681ef0

File tree

3 files changed

+80
-14
lines changed

3 files changed

+80
-14
lines changed

cffi/cdefs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,7 @@ struct lysc_ext {
691691
#define LYS_GETNEXT_WITHCASE ...
692692
#define LYS_GETNEXT_INTONPCONT ...
693693
#define LYS_GETNEXT_OUTPUT ...
694+
#define LYS_GETNEXT_WITHSCHEMAMOUNT ...
694695

695696
const struct lysc_node* lys_find_child(const struct lysc_node *, const struct lys_module *, const char *, size_t, uint16_t, uint32_t);
696697
const struct lysc_node* lysc_node_child(const struct lysc_node *);

libyang/schema.py

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,12 @@ def get_module_from_prefix(self, prefix: str) -> Optional["Module"]:
137137
def __iter__(self) -> Iterator["SNode"]:
138138
return self.children()
139139

140-
def children(self, types: Optional[Tuple[int, ...]] = None) -> Iterator["SNode"]:
141-
return iter_children(self.context, self.cdata, types=types)
140+
def children(
141+
self, types: Optional[Tuple[int, ...]] = None, with_choice: bool = False
142+
) -> Iterator["SNode"]:
143+
return iter_children(
144+
self.context, self.cdata, types=types, with_choice=with_choice
145+
)
142146

143147
def __str__(self) -> str:
144148
return self.name()
@@ -1401,8 +1405,12 @@ def presence(self) -> Optional[str]:
14011405
def __iter__(self) -> Iterator[SNode]:
14021406
return self.children()
14031407

1404-
def children(self, types: Optional[Tuple[int, ...]] = None) -> Iterator[SNode]:
1405-
return iter_children(self.context, self.cdata, types=types)
1408+
def children(
1409+
self, types: Optional[Tuple[int, ...]] = None, with_choice: bool = False
1410+
) -> Iterator[SNode]:
1411+
return iter_children(
1412+
self.context, self.cdata, types=types, with_choice=with_choice
1413+
)
14061414

14071415

14081416
# -------------------------------------------------------------------------------------
@@ -1411,8 +1419,10 @@ class SChoice(SNode):
14111419
def __iter__(self) -> Iterator[SNode]:
14121420
return self.children()
14131421

1414-
def children(self, types: Optional[Tuple[int, ...]] = None) -> Iterator[SNode]:
1415-
return iter_children(self.context, self.cdata, types=types)
1422+
def children(
1423+
self, types: Optional[Tuple[int, ...]] = None, with_case: bool = False
1424+
) -> Iterator[SNode]:
1425+
return iter_children(self.context, self.cdata, types=types, with_case=with_case)
14161426

14171427

14181428
# -------------------------------------------------------------------------------------
@@ -1421,8 +1431,12 @@ class SCase(SNode):
14211431
def __iter__(self) -> Iterator[SNode]:
14221432
return self.children()
14231433

1424-
def children(self, types: Optional[Tuple[int, ...]] = None) -> Iterator[SNode]:
1425-
return iter_children(self.context, self.cdata, types=types)
1434+
def children(
1435+
self, types: Optional[Tuple[int, ...]] = None, with_choice: bool = False
1436+
) -> Iterator[SNode]:
1437+
return iter_children(
1438+
self.context, self.cdata, types=types, with_choice=with_choice
1439+
)
14261440

14271441

14281442
# -------------------------------------------------------------------------------------
@@ -1442,9 +1456,18 @@ def __iter__(self) -> Iterator[SNode]:
14421456
return self.children()
14431457

14441458
def children(
1445-
self, skip_keys: bool = False, types: Optional[Tuple[int, ...]] = None
1459+
self,
1460+
skip_keys: bool = False,
1461+
types: Optional[Tuple[int, ...]] = None,
1462+
with_choice: bool = False,
14461463
) -> Iterator[SNode]:
1447-
return iter_children(self.context, self.cdata, skip_keys=skip_keys, types=types)
1464+
return iter_children(
1465+
self.context,
1466+
self.cdata,
1467+
skip_keys=skip_keys,
1468+
types=types,
1469+
with_choice=with_choice,
1470+
)
14481471

14491472
def keys(self) -> Iterator[SNode]:
14501473
node = lib.lysc_node_child(self.cdata)
@@ -1512,9 +1535,7 @@ def children(self, types: Optional[Tuple[int, ...]] = None) -> Iterator[SNode]:
15121535
yield from iter_children(self.context, self.cdata, types=types)
15131536
# With libyang2, you can get only input or output
15141537
# To keep behavior, we iter 2 times witt output options
1515-
yield from iter_children(
1516-
self.context, self.cdata, types=types, options=lib.LYS_GETNEXT_OUTPUT
1517-
)
1538+
yield from iter_children(self.context, self.cdata, types=types, output=True)
15181539

15191540

15201541
# -------------------------------------------------------------------------------------
@@ -1539,13 +1560,43 @@ class SAnydata(SNode):
15391560
pass
15401561

15411562

1563+
# -------------------------------------------------------------------------------------
1564+
def iter_children_options(
1565+
with_choice: bool = False,
1566+
no_choice: bool = False,
1567+
with_case: bool = False,
1568+
into_non_presence_container: bool = False,
1569+
output: bool = False,
1570+
with_schema_mount: bool = False,
1571+
) -> int:
1572+
options = 0
1573+
if with_choice:
1574+
options |= lib.LYS_GETNEXT_WITHCHOICE
1575+
if no_choice:
1576+
options |= lib.LYS_GETNEXT_NOCHOICE
1577+
if with_case:
1578+
options |= lib.LYS_GETNEXT_WITHCASE
1579+
if into_non_presence_container:
1580+
options |= lib.LYS_GETNEXT_INTONPCONT
1581+
if output:
1582+
options |= lib.LYS_GETNEXT_OUTPUT
1583+
if with_schema_mount:
1584+
options |= lib.LYS_GETNEXT_WITHSCHEMAMOUNT
1585+
return options
1586+
1587+
15421588
# -------------------------------------------------------------------------------------
15431589
def iter_children(
15441590
context: "libyang.Context",
15451591
parent, # C type: Union["struct lys_module *", "struct lys_node *"]
15461592
skip_keys: bool = False,
15471593
types: Optional[Tuple[int, ...]] = None,
1548-
options: int = 0,
1594+
with_choice: bool = False,
1595+
no_choice: bool = False,
1596+
with_case: bool = False,
1597+
into_non_presence_container: bool = False,
1598+
output: bool = False,
1599+
with_schema_mount: bool = False,
15491600
) -> Iterator[SNode]:
15501601
if types is None:
15511602
types = (
@@ -1556,6 +1607,8 @@ def iter_children(
15561607
lib.LYS_LEAF,
15571608
lib.LYS_LEAFLIST,
15581609
lib.LYS_NOTIF,
1610+
lib.LYS_CHOICE,
1611+
lib.LYS_CASE,
15591612
)
15601613

15611614
def _skip(node) -> bool:
@@ -1576,6 +1629,14 @@ def _skip(node) -> bool:
15761629
else:
15771630
module = ffi.NULL
15781631

1632+
options = iter_children_options(
1633+
with_choice=with_choice,
1634+
no_choice=no_choice,
1635+
with_case=with_case,
1636+
into_non_presence_container=into_non_presence_container,
1637+
output=output,
1638+
with_schema_mount=with_schema_mount,
1639+
)
15791640
child = lib.lys_getnext(ffi.NULL, parent, module, options)
15801641
while child:
15811642
if not _skip(child):

tests/test_schema.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ def test_cont_iter(self):
271271
def test_cont_children_leafs(self):
272272
leafs = list(self.container.children(types=(SNode.LEAF,)))
273273
self.assertEqual(len(leafs), 9)
274+
without_choice = [c.name() for c in self.container.children(with_choice=False)]
275+
with_choice = [c.name() for c in self.container.children(with_choice=True)]
276+
self.assertTrue("pill" not in without_choice)
277+
self.assertTrue("pill" in with_choice)
274278

275279
def test_cont_parent(self):
276280
self.assertIsNone(self.container.parent())

0 commit comments

Comments
 (0)