diff --git a/tests/test_model.py b/tests/test_model.py index 87e6bd6eaee882d8074aab0d420afc08903b870d..8c39408c983df8b99c4fc73c7c4c949b5109d309 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -174,8 +174,7 @@ def test_schema(data_model): assert lla.type.default == 11 assert lo.default_value() == True assert lp.default_value() == 42 - assert (lsta.default_value() == - super(SequenceNode, lsta).from_raw({"contD": {"contE": {"leafP": 42}}})) + assert lsta.default_value() == ObjectValue() assert la.type.parse_value("99") == 99 with pytest.raises(YangTypeError): ld.type.parse_value("99") @@ -296,9 +295,9 @@ def test_instance(instance): axtest(la1.ancestors_or_self(("listA", "test")), ["/test:contA/listA/1" ]) axtest(la1.preceding_siblings(), ["/test:contA/listA/0"]) axtest(la1.following_siblings(), []) - assert len(conta.children()) == 8 + assert len(conta.children()) == 9 axtest(la1.children(("leafF", "test")), ["/test:contA/listA/1/leafF"]) - assert len(instance.descendants(with_self=True)) == 25 + assert len(instance.descendants(with_self=True)) == 29 axtest(conta.descendants(("listA", "test")), ["/test:contA/listA/0", "/test:contA/listA/1"]) axtest(tbln.ancestors_or_self(("leafN", "testb")), ["/test:contA/testb:leafN"]) @@ -350,7 +349,7 @@ def test_xpath(instance): xptest("local-name()", "leafR", lr) xptest("name()", "testb:leafR", lr) xptest("name(../t:listA)", "listA", lr, "testb") - xptest("count(descendant-or-self::*)", 30) + xptest("count(descendant-or-self::*)", 29) xptest("count(descendant::leafE)", 2) xptest("count(preceding-sibling::*)", 0, lr, "testb") xptest("count(following-sibling::*)", 0, lr, "testb") diff --git a/yangson/instance.py b/yangson/instance.py index 535b5463fd023a78a04356e49a8392957a9ea9a8..0cd99d71a357da69e3174d5540fa07b3fc0cf8bc 100644 --- a/yangson/instance.py +++ b/yangson/instance.py @@ -207,12 +207,11 @@ class InstanceNode: sn = self.schema_node if isinstance(sn, TerminalNode): return [] if qname: - iname = (qname[0] if self.namespace == qname[1] - else qname[1] + ":" + qname[0]) - if iname in self.value: - return self.member(iname).xpath_nodes() cn = sn.get_data_child(*qname) if cn is None: return [] + iname = cn.iname() + if iname in self.value: + return self.member(iname).xpath_nodes() res = cn._default_nodes(self) if not res: return res while True: @@ -224,8 +223,20 @@ class InstanceNode: continue return [] res = [] - for n in self.value: - res += self.member(n).xpath_nodes() + for cn in sn.children.values(): + if isinstance(cn, ChoiceNode): + cin = cn.child_inst_names().intersection(self.value) + if cin: + for i in cin: + res.extend(self.member(i).xpath_nodes()) + else: + res.extend(cn._default_nodes(inst)) + else: + iname = cn.iname() + if iname in self.value: + res.extend(self.member(iname).xpath_nodes()) + else: + res.extend(cn._default_nodes(self)) return res def descendants(self, qname: Union[QualName, bool] = None, @@ -849,6 +860,6 @@ class InstanceIdParser(InstancePathParser): sel[knod.iname()] = val return EntryKeys(sel) -from .schema import (CaseNode, DataNode, InternalNode, +from .schema import (CaseNode, ChoiceNode, DataNode, InternalNode, LeafNode, LeafListNode, ListNode, NonexistentSchemaNode, SequenceNode, TerminalNode) diff --git a/yangson/schema.py b/yangson/schema.py index 7cbb2c2e78ea2fdaccb898c2145319e30b692fe8..fffe87f7f695eb068e6eeb2cb339ddab860b4316 100644 --- a/yangson/schema.py +++ b/yangson/schema.py @@ -442,12 +442,13 @@ class TerminalNode(SchemaNode): return None def _default_nodes(self, inst: "InstanceNode") -> List["InstanceNode"]: - if self.default is None: return [] + dflt = self.default_value() + if dflt is None: return [] iname = self.iname() ni = inst.put_member(iname, (None,)) res = ni.member(iname) if self.when is None or self.when.evaluate(res): - res.value = self.default + res.value = dflt return res.xpath_nodes() return [] @@ -597,6 +598,13 @@ class ChoiceNode(InternalNode): if self.mandatory: self.parent._add_mandatory_child(self) + def _default_nodes(self, inst: "InstanceNode") -> List["InstanceNode"]: + res = [] + if self.default_case is None: return res + for cn in self.children[self.default_case].children.values(): + res.extend(cn._default_nodes(inst)) + return res + def default_value(self) -> Optional[ObjectValue]: """Return the receiver's default content.""" if self.default_case in [c.qual_name for c in self.default_children]: