Skip to content

Commit b3f74f3

Browse files
committed
schema: get more info from enums/bits
Return python objects instead of tuples of (name, description). This is an API breakage (although, minor). Signed-off-by: Robin Jarry <robin@jarry.cc>
1 parent 6391942 commit b3f74f3

File tree

7 files changed

+114
-26
lines changed

7 files changed

+114
-26
lines changed

cffi/cdefs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ struct lys_type_info_binary {
151151
struct lys_type_bit {
152152
const char *name;
153153
const char *dsc;
154+
uint16_t flags;
154155
uint32_t pos;
155156
...;
156157
};
@@ -168,6 +169,7 @@ struct lys_type_info_dec64 {
168169
struct lys_type_enum {
169170
const char *name;
170171
const char *dsc;
172+
uint16_t flags;
171173
...;
172174
};
173175

libyang/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
BaseTypeRemoved,
1111
BitAdded,
1212
BitRemoved,
13+
BitStatusAdded,
14+
BitStatusRemoved,
1315
ConfigFalseAdded,
1416
ConfigFalseRemoved,
1517
DefaultAdded,
@@ -18,6 +20,8 @@
1820
DescriptionRemoved,
1921
EnumAdded,
2022
EnumRemoved,
23+
EnumStatusAdded,
24+
EnumStatusRemoved,
2125
ExtensionAdded,
2226
ExtensionRemoved,
2327
KeyAdded,

libyang/diff.py

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,14 @@ class BitAdded(SNodeAttributeChanged):
142142
pass
143143

144144

145+
class BitStatusRemoved(SNodeAttributeChanged):
146+
pass
147+
148+
149+
class BitStatusAdded(SNodeAttributeChanged):
150+
pass
151+
152+
145153
class ConfigFalseRemoved(SNodeAttributeChanged):
146154
pass
147155

@@ -174,6 +182,14 @@ class EnumAdded(SNodeAttributeChanged):
174182
pass
175183

176184

185+
class EnumStatusRemoved(SNodeAttributeChanged):
186+
pass
187+
188+
189+
class EnumStatusAdded(SNodeAttributeChanged):
190+
pass
191+
192+
177193
class ExtensionRemoved(SNodeAttributeChanged):
178194
pass
179195

@@ -365,19 +381,31 @@ def snode_changes(old: SNode, new: SNode) -> Iterator[SNodeDiff]:
365381
for r in new_ranges - old_ranges:
366382
yield RangeAdded(old, new, r)
367383

368-
old_enums = set(e for e, _ in old.type().all_enums())
369-
new_enums = set(e for e, _ in new.type().all_enums())
370-
for e in old_enums - new_enums:
371-
yield EnumRemoved(old, new, e)
372-
for e in new_enums - old_enums:
373-
yield EnumAdded(old, new, e)
374-
375-
old_bits = set(b for b, _ in old.type().all_bits())
376-
new_bits = set(b for b, _ in new.type().all_bits())
377-
for b in old_bits - new_bits:
378-
yield BitRemoved(old, new, b)
379-
for b in new_bits - old_bits:
380-
yield BitAdded(old, new, b)
384+
old_enums = {e.name(): e for e in old.type().all_enums()}
385+
new_enums = {e.name(): e for e in new.type().all_enums()}
386+
for e in old_enums.keys() - new_enums.keys():
387+
yield EnumRemoved(old, new, old_enums[e])
388+
for e in new_enums.keys() - old_enums.keys():
389+
yield EnumAdded(old, new, new_enums[e])
390+
for e in new_enums.keys() & old_enums.keys():
391+
o = old_enums[e]
392+
n = new_enums[e]
393+
if o.status() != n.status():
394+
yield EnumStatusRemoved(old, new, (o.name(), o.status()))
395+
yield EnumStatusAdded(old, new, (n.name(), n.status()))
396+
397+
old_bits = {b.name(): b for b in old.type().all_bits()}
398+
new_bits = {b.name(): b for b in new.type().all_bits()}
399+
for b in old_bits.keys() - new_bits.keys():
400+
yield BitRemoved(old, new, old_bits[b])
401+
for b in new_bits.keys() - old_bits.keys():
402+
yield BitAdded(old, new, new_bits[b])
403+
for b in new_bits.keys() & old_bits.keys():
404+
o = old_bits[b]
405+
n = new_bits[b]
406+
if o.status() != n.status():
407+
yield BitStatusRemoved(old, new, (o.name(), o.status()))
408+
yield BitStatusAdded(old, new, (n.name(), n.status()))
381409

382410
if isinstance(old, SLeaf) and isinstance(new, SLeaf):
383411
if old.default() != new.default():

libyang/schema.py

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,52 @@ def __str__(self):
281281
return self.name()
282282

283283

284+
# -------------------------------------------------------------------------------------
285+
class _EnumBit:
286+
287+
__slots__ = ("context", "cdata")
288+
289+
def __init__(self, context: "libyang.Context", cdata):
290+
self.context = context
291+
self.cdata = cdata # C type "struct lys_type_bit" or "struct lys_type_enum"
292+
293+
def name(self) -> str:
294+
return c2str(self.cdata.name)
295+
296+
def description(self) -> str:
297+
return c2str(self.cdata.dsc)
298+
299+
def deprecated(self) -> bool:
300+
return bool(self.cdata.flags & lib.LYS_STATUS_DEPRC)
301+
302+
def obsolete(self) -> bool:
303+
return bool(self.cdata.flags & lib.LYS_STATUS_OBSLT)
304+
305+
def status(self) -> str:
306+
if self.cdata.flags & lib.LYS_STATUS_OBSLT:
307+
return "obsolete"
308+
if self.cdata.flags & lib.LYS_STATUS_DEPRC:
309+
return "deprecated"
310+
return "current"
311+
312+
def __repr__(self):
313+
cls = self.__class__
314+
return "<%s.%s: %s>" % (cls.__module__, cls.__name__, self)
315+
316+
def __str__(self):
317+
return self.name()
318+
319+
320+
# -------------------------------------------------------------------------------------
321+
class Enum(_EnumBit):
322+
pass
323+
324+
325+
# -------------------------------------------------------------------------------------
326+
class Bit(_EnumBit):
327+
pass
328+
329+
284330
# -------------------------------------------------------------------------------------
285331
class Type:
286332

@@ -393,31 +439,29 @@ def union_types(self) -> Iterator["Type"]:
393439
for i in range(t.info.uni.count):
394440
yield Type(self.context, t.info.uni.types[i])
395441

396-
def enums(self) -> Iterator[Tuple[str, Optional[str]]]:
442+
def enums(self) -> Iterator[Enum]:
397443
if self.cdata.base != self.ENUM:
398444
return
399445
t = self.cdata
400446
while t.info.enums.count == 0:
401447
t = ffi.addressof(t.der.type)
402448
for i in range(t.info.enums.count):
403-
e = t.info.enums.enm[i]
404-
yield c2str(e.name), c2str(e.dsc)
449+
yield Enum(self.context, t.info.enums.enm[i])
405450

406-
def all_enums(self) -> Iterator[Tuple[str, Optional[str]]]:
451+
def all_enums(self) -> Iterator[Enum]:
407452
for b in self.get_bases():
408453
yield from b.enums()
409454

410-
def bits(self) -> Iterator[Tuple[str, Optional[str]]]:
455+
def bits(self) -> Iterator[Bit]:
411456
if self.cdata.base != self.BITS:
412457
return
413458
t = self.cdata
414459
while t.info.bits.count == 0:
415460
t = ffi.addressof(t.der.type)
416461
for i in range(t.info.bits.count):
417-
b = t.info.bits.bit[i]
418-
yield c2str(b.name), c2str(b.dsc)
462+
yield Bit(self.context, t.info.bits.bit[i])
419463

420-
def all_bits(self) -> Iterator[Tuple[str, Optional[str]]]:
464+
def all_bits(self) -> Iterator[Bit]:
421465
for b in self.get_bases():
422466
yield from b.bits()
423467

tests/test_diff.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
BaseTypeAdded,
99
BaseTypeRemoved,
1010
Context,
11+
EnumRemoved,
12+
EnumStatusAdded,
13+
EnumStatusRemoved,
1114
NodeTypeAdded,
1215
NodeTypeRemoved,
1316
SNodeAdded,
@@ -68,6 +71,12 @@ class DiffTest(unittest.TestCase):
6871
(SNodeAdded, "/yolo-system:alarm-triggered"),
6972
(SNodeAdded, "/yolo-system:alarm-triggered/yolo-system:severity"),
7073
(SNodeAdded, "/yolo-system:alarm-triggered/yolo-system:description"),
74+
(EnumRemoved, "/yolo-system:conf/yolo-system:url/yolo-system:proto"),
75+
(EnumRemoved, "/yolo-system:state/yolo-system:url/yolo-system:proto"),
76+
(EnumStatusAdded, "/yolo-system:conf/yolo-system:url/yolo-system:proto"),
77+
(EnumStatusAdded, "/yolo-system:state/yolo-system:url/yolo-system:proto"),
78+
(EnumStatusRemoved, "/yolo-system:conf/yolo-system:url/yolo-system:proto"),
79+
(EnumStatusRemoved, "/yolo-system:state/yolo-system:url/yolo-system:proto"),
7180
)
7281
)
7382

tests/test_schema.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,8 @@ def test_leaf_type_enum(self):
346346
self.assertIsInstance(t, Type)
347347
self.assertEqual(t.name(), "protocol")
348348
self.assertEqual(t.base(), Type.ENUM)
349-
enums = [e for e, _ in t.enums()]
350-
self.assertEqual(enums, ["http", "https", "ftp", "sftp", "tftp"])
349+
enums = [e.name() for e in t.enums()]
350+
self.assertEqual(enums, ["http", "https", "ftp", "sftp"])
351351

352352
def test_leaf_type_bits(self):
353353
leaf = next(
@@ -358,7 +358,7 @@ def test_leaf_type_bits(self):
358358
self.assertIsInstance(t, Type)
359359
self.assertEqual(t.name(), "permissions")
360360
self.assertEqual(t.base(), Type.BITS)
361-
bits = [b for b, _ in t.bits()]
361+
bits = [b.name() for b in t.bits()]
362362
self.assertEqual(bits, ["read", "write", "execute"])
363363
self.assertIs(t.derived_type().module(), None)
364364

tests/yang/wtf/wtf-types.yang

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@ module wtf-types {
3737
type enumeration {
3838
enum http;
3939
enum https;
40-
enum ftp;
40+
enum ftp {
41+
status deprecated;
42+
}
4143
enum sftp;
42-
enum tftp;
4344
}
4445
}
4546

0 commit comments

Comments
 (0)