Skip to content

Commit aaca4df

Browse files
samuel-gauthierrjarry
authored andcommitted
schema: add typedef support
Parse the typedef section in a Typedef class, add typedefs / get_typedef methods to the Module class, and add a method to get the Typedef object associated to a Type. Signed-off-by: Samuel Gauthier <samuel.gauthier@6wind.com> Acked-by: Robin Jarry <robin@jarry.cc>
1 parent fd7a990 commit aaca4df

File tree

5 files changed

+88
-0
lines changed

5 files changed

+88
-0
lines changed

cffi/cdefs.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,17 @@ LY_ERR lyd_dup_siblings(const struct lyd_node *, struct lyd_node_inner *, uint32
978978
LY_ERR lyd_dup_single(const struct lyd_node *, struct lyd_node_inner *, uint32_t, struct lyd_node **);
979979
void lyd_free_meta_single(struct lyd_meta *);
980980

981+
struct lysp_tpdf {
982+
const char *name;
983+
const char *units;
984+
struct lysp_qname dflt;
985+
const char *dsc;
986+
const char *ref;
987+
struct lysp_ext_instance *exts;
988+
struct lysp_type type;
989+
uint16_t flags;
990+
};
991+
981992
struct lysc_when {
982993
struct lyxp_expr *cond;
983994
struct lysc_node *context;

libyang/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
SRpc,
8484
SRpcInOut,
8585
Type,
86+
Typedef,
8687
)
8788
from .util import DataType, IOType, LibyangError
8889
from .xpath import (

libyang/schema.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,17 @@ def revisions(self) -> Iterator["Revision"]:
112112
for revision in ly_array_iter(self.cdata.parsed.revs):
113113
yield Revision(self.context, revision, self)
114114

115+
def typedefs(self) -> Iterator["Typedef"]:
116+
for typedef in ly_array_iter(self.cdata.parsed.typedefs):
117+
yield Typedef(self.context, typedef)
118+
119+
def get_typedef(self, name: str) -> Optional["Typedef"]:
120+
for typedef in self.typedefs():
121+
if typedef.name() != name:
122+
continue
123+
return typedef
124+
return None
125+
115126
def imports(self) -> Iterator["Import"]:
116127
for i in ly_array_iter(self.cdata.parsed.imports):
117128
yield Import(self.context, i, self)
@@ -533,6 +544,14 @@ def leafref_path(self) -> Optional["str"]:
533544
lr = ffi.cast("struct lysc_type_leafref *", self.cdata)
534545
return c2str(lib.lyxp_get_expr(lr.path))
535546

547+
def typedef(self) -> "Typedef":
548+
if ":" in self.name():
549+
module_prefix, type_name = self.name().split(":")
550+
import_module = self.module().get_module_from_prefix(module_prefix)
551+
if import_module:
552+
return import_module.get_typedef(type_name)
553+
return None
554+
536555
def union_types(self) -> Iterator["Type"]:
537556
if self.cdata.basetype != self.UNION:
538557
return
@@ -662,6 +681,59 @@ def __str__(self):
662681
return self.name()
663682

664683

684+
# -------------------------------------------------------------------------------------
685+
class Typedef:
686+
__slots__ = ("context", "cdata", "__dict__")
687+
688+
def __init__(self, context: "libyang.Context", cdata):
689+
self.context = context
690+
self.cdata = cdata # C type: "struct lysp_tpdf *"
691+
692+
def name(self) -> str:
693+
return c2str(self.cdata.name)
694+
695+
def description(self) -> Optional[str]:
696+
return c2str(self.cdata.dsc)
697+
698+
def units(self) -> Optional[str]:
699+
return c2str(self.cdata.units)
700+
701+
def reference(self) -> Optional[str]:
702+
return c2str(self.cdata.ref)
703+
704+
def extensions(self) -> Iterator[ExtensionCompiled]:
705+
ext = ffi.cast("struct lysc_ext_instance *", self.cdata.exts)
706+
if ext == ffi.NULL:
707+
return
708+
for extension in ly_array_iter(ext):
709+
yield ExtensionCompiled(self.context, extension)
710+
711+
def get_extension(
712+
self, name: str, prefix: Optional[str] = None, arg_value: Optional[str] = None
713+
) -> Optional[ExtensionCompiled]:
714+
for ext in self.extensions():
715+
if ext.name() != name:
716+
continue
717+
if prefix is not None and ext.module().name() != prefix:
718+
continue
719+
if arg_value is not None and ext.argument() != arg_value:
720+
continue
721+
return ext
722+
return None
723+
724+
def deprecated(self) -> bool:
725+
return bool(self.cdata.flags & lib.LYS_STATUS_DEPRC)
726+
727+
def obsolete(self) -> bool:
728+
return bool(self.cdata.flags & lib.LYS_STATUS_OBSLT)
729+
730+
def module(self) -> Module:
731+
return Module(self.context, self.cdata.module)
732+
733+
def __str__(self):
734+
return self.name()
735+
736+
665737
# -------------------------------------------------------------------------------------
666738
class Feature:
667739
__slots__ = ("context", "cdata", "__dict__")

tests/test_schema.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,8 @@ def test_leaf_type_derived(self):
380380
self.assertIsNot(mod, None)
381381
self.assertEqual(mod.name(), "yolo-system")
382382
self.assertEqual(mod.get_module_from_prefix("types").name(), "wtf-types")
383+
self.assertEqual(t.typedef().name(), "host")
384+
self.assertEqual(t.typedef().description(), "my host type.")
383385

384386
def test_leaf_type_status(self):
385387
leaf = next(self.ctx.find_path("/yolo-system:conf/yolo-system:hostname"))

tests/yang/wtf/wtf-types.yang

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ module wtf-types {
1212
type str {
1313
pattern "[a-z]+";
1414
}
15+
description
16+
"my host type.";
1517
}
1618

1719
extension signed;

0 commit comments

Comments
 (0)