Skip to content

Commit eb7bef5

Browse files
committed
schema: check parsed object before use
With libyang/sysrepo 4 and printed contexts, the parsed object can be null. Check the parsed object before using it. If the parsed object is missing: - Module methods won't yield anything. - ExtensionParsed _module_from_parsed raises an exception. - SNode if_features won't yield anything. - Create a Type object without the parsed type. - The Container presence returns None. - For list and leaflist order, return the info from the compiled object. Fixes: 0a4b09f ("cffi: allows to usage of libyang v4") Signed-off-by: Jeremie Leska <jeremie.leska@6wind.com>
1 parent 6c0727f commit eb7bef5

File tree

1 file changed

+50
-28
lines changed

1 file changed

+50
-28
lines changed

libyang/schema.py

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,14 @@ def get_feature(self, name: str) -> "Feature":
122122
raise self.context.error("no such feature: %r" % name)
123123

124124
def revisions(self) -> Iterator["Revision"]:
125-
for revision in ly_array_iter(self.cdata.parsed.revs):
126-
yield Revision(self.context, revision, self)
125+
if self.cdata.parsed:
126+
for revision in ly_array_iter(self.cdata.parsed.revs):
127+
yield Revision(self.context, revision, self)
127128

128129
def typedefs(self) -> Iterator["Typedef"]:
129-
for typedef in ly_array_iter(self.cdata.parsed.typedefs):
130-
yield Typedef(self.context, typedef)
130+
if self.cdata.parsed:
131+
for typedef in ly_array_iter(self.cdata.parsed.typedefs):
132+
yield Typedef(self.context, typedef)
131133

132134
def get_typedef(self, name: str) -> Optional["Typedef"]:
133135
for typedef in self.typedefs():
@@ -137,8 +139,9 @@ def get_typedef(self, name: str) -> Optional["Typedef"]:
137139
return None
138140

139141
def imports(self) -> Iterator["Import"]:
140-
for i in ly_array_iter(self.cdata.parsed.imports):
141-
yield Import(self.context, i, self)
142+
if self.cdata.parsed:
143+
for i in ly_array_iter(self.cdata.parsed.imports):
144+
yield Import(self.context, i, self)
142145

143146
def get_module_from_prefix(self, prefix: str) -> Optional["Module"]:
144147
for i in self.imports():
@@ -158,32 +161,38 @@ def children(
158161
)
159162

160163
def parsed_children(self) -> Iterator["PNode"]:
161-
for c in ly_list_iter(self.cdata.parsed.data):
162-
yield PNode.new(self.context, c, self)
164+
if self.cdata.parsed:
165+
for c in ly_list_iter(self.cdata.parsed.data):
166+
yield PNode.new(self.context, c, self)
163167

164168
def groupings(self) -> Iterator["PGrouping"]:
165-
for g in ly_list_iter(self.cdata.parsed.groupings):
166-
yield PGrouping(self.context, g, self)
169+
if self.cdata.parsed:
170+
for g in ly_list_iter(self.cdata.parsed.groupings):
171+
yield PGrouping(self.context, g, self)
167172

168173
def augments(self) -> Iterator["PAugment"]:
169-
for a in ly_array_iter(self.cdata.parsed.augments):
170-
yield PAugment(self.context, a, self)
174+
if self.cdata.parsed:
175+
for a in ly_array_iter(self.cdata.parsed.augments):
176+
yield PAugment(self.context, a, self)
171177

172178
def actions(self) -> Iterator["PAction"]:
173-
for a in ly_list_iter(self.cdata.parsed.rpcs):
174-
yield PAction(self.context, a, self)
179+
if self.cdata.parsed:
180+
for a in ly_list_iter(self.cdata.parsed.rpcs):
181+
yield PAction(self.context, a, self)
175182

176183
def notifications(self) -> Iterator["PNotif"]:
177-
for n in ly_list_iter(self.cdata.parsed.notifs):
178-
yield PNotif(self.context, n, self)
184+
if self.cdata.parsed:
185+
for n in ly_list_iter(self.cdata.parsed.notifs):
186+
yield PNotif(self.context, n, self)
179187

180188
def identities(self) -> Iterator["Identity"]:
181189
for i in ly_array_iter(self.cdata.identities):
182190
yield Identity(self.context, i)
183191

184192
def parsed_identities(self) -> Iterator["PIdentity"]:
185-
for i in ly_array_iter(self.cdata.parsed.identities):
186-
yield PIdentity(self.context, i, self)
193+
if self.cdata.parsed:
194+
for i in ly_array_iter(self.cdata.parsed.identities):
195+
yield PIdentity(self.context, i, self)
187196

188197
def extensions(self) -> Iterator["ExtensionCompiled"]:
189198
compiled = ffi.cast("struct lysc_module *", self.cdata.compiled)
@@ -440,6 +449,8 @@ def _module_from_parsed(self) -> Module:
440449
prefix = c2str(self.cdata.name).split(":")[0]
441450
if self.module_parent is None:
442451
raise self.context.error("cannot get module")
452+
if not self.module_parent.cdata.parsed:
453+
raise self.context.error("cannot get module")
443454
for cdata_imp_mod in ly_array_iter(self.module_parent.cdata.parsed.imports):
444455
if ffi.string(cdata_imp_mod.prefix).decode() == prefix:
445456
return Module(self.context, cdata_imp_mod.module)
@@ -1431,10 +1442,11 @@ def get_extension(
14311442
return None
14321443

14331444
def if_features(self) -> Iterator[IfFeatureExpr]:
1434-
iff = ffi.cast("struct lysp_qname *", self.cdata_parsed.iffeatures)
1435-
module_features = self.module().features()
1436-
for if_feature in ly_array_iter(iff):
1437-
yield IfFeatureExpr(self.context, if_feature, list(module_features))
1445+
if self.cdata_parsed:
1446+
iff = ffi.cast("struct lysp_qname *", self.cdata_parsed.iffeatures)
1447+
module_features = self.module().features()
1448+
for if_feature in ly_array_iter(iff):
1449+
yield IfFeatureExpr(self.context, if_feature, list(module_features))
14381450

14391451
def parent(self) -> Optional["SNode"]:
14401452
parent_p = self.cdata.parent
@@ -1568,7 +1580,9 @@ def units(self) -> Optional[str]:
15681580
return c2str(self.cdata_leaf.units)
15691581

15701582
def type(self) -> Type:
1571-
return Type(self.context, self.cdata_leaf.type, self.cdata_leaf_parsed.type)
1583+
if self.cdata_leaf_parsed:
1584+
return Type(self.context, self.cdata_leaf.type, self.cdata_leaf_parsed.type)
1585+
return Type(self.context, self.cdata_leaf.type, None)
15721586

15731587
def is_key(self) -> bool:
15741588
if self.cdata_leaf.flags & lib.LYS_KEY:
@@ -1593,15 +1607,19 @@ def __init__(self, context: "libyang.Context", cdata):
15931607
self.cdata_default_realtypes = None
15941608

15951609
def ordered(self) -> bool:
1596-
return bool(self.cdata_parsed.flags & lib.LYS_ORDBY_USER)
1610+
if self.cdata_parsed:
1611+
return bool(self.cdata_parsed.flags & lib.LYS_ORDBY_USER)
1612+
return bool(self.cdata_leaflist.flags & lib.LYS_ORDBY_USER)
15971613

15981614
def units(self) -> Optional[str]:
15991615
return c2str(self.cdata_leaflist.units)
16001616

16011617
def type(self) -> Type:
1602-
return Type(
1603-
self.context, self.cdata_leaflist.type, self.cdata_leaflist_parsed.type
1604-
)
1618+
if self.cdata_leaflist_parsed:
1619+
return Type(
1620+
self.context, self.cdata_leaflist.type, self.cdata_leaflist_parsed.type
1621+
)
1622+
return Type(self.context, self.cdata_leaflist.type, None)
16051623

16061624
def defaults(self) -> Iterator[Union[None, bool, int, str, float]]:
16071625
if self.cdata_leaflist.dflts == ffi.NULL:
@@ -1673,6 +1691,8 @@ def __init__(self, context: "libyang.Context", cdata):
16731691
def presence(self) -> Optional[str]:
16741692
if not self.cdata_container.flags & lib.LYS_PRESENCE:
16751693
return None
1694+
if not self.cdata_container_parsed:
1695+
return None
16761696

16771697
return c2str(self.cdata_container_parsed.presence)
16781698

@@ -1735,7 +1755,9 @@ def __init__(self, context: "libyang.Context", cdata):
17351755
self.cdata_list_parsed = ffi.cast("struct lysp_node_list *", self.cdata_parsed)
17361756

17371757
def ordered(self) -> bool:
1738-
return bool(self.cdata_parsed.flags & lib.LYS_ORDBY_USER)
1758+
if self.cdata_parsed:
1759+
return bool(self.cdata_parsed.flags & lib.LYS_ORDBY_USER)
1760+
return bool(self.cdata_list.flags & lib.LYS_ORDBY_USER)
17391761

17401762
def __iter__(self) -> Iterator[SNode]:
17411763
return self.children()

0 commit comments

Comments
 (0)