Skip to content
Snippets Groups Projects
Commit 3d3c84cf authored by Ladislav Lhotka's avatar Ladislav Lhotka
Browse files

Implement deref() for leafrefs.

parent e6d38ed2
No related branches found
No related tags found
No related merge requests found
......@@ -97,7 +97,7 @@ def instance(data_model):
}
}, {
"leafE": "ABBA",
"leafF": true
"leafF": false
}],
"testb:leafR": "C0FFEE",
"anydA": {
......@@ -272,7 +272,7 @@ def test_instance(instance):
assert inst1.path() == inst2.path() == ()
assert la1.namespace == "test"
assert la1.member("leafE").namespace == "test"
assert la1.member("leafF").value is True
assert la1.member("leafF").value is False
with pytest.raises(NonexistentInstance):
la1.member("contD")
assert str(la1.path()) == "/test:contA/listA/1"
......@@ -390,7 +390,7 @@ def test_xpath(instance):
xptest("number(false()) = 0")
xptest("sum(leafA | leafB)", 77, conta)
xptest("string(sum(//leafE))", "NaN")
xptest("sum(//leafF)", 2)
xptest("sum(//leafF)", 1)
with pytest.raises(XPathTypeError):
xptest("sum(42)")
xptest("floor(contT/decimal64)", 4)
......@@ -406,6 +406,7 @@ def test_xpath(instance):
xptest("re-match('aaax', 'a*')", False)
xptest("re-match('a\nb', '.*')", False)
xptest("re-match('a\nb', '[a-z\n]*')")
xptest("deref(.)/../t:leafF", True, lr, "testb")
def test_instance_paths(data_model, instance):
rid1 = data_model.parse_resource_id("/test:contA/testb:leafN")
......
......@@ -5,8 +5,11 @@ from pyxb.utils.xmlre import XMLToPython
from typing import Any, Callable, List, Optional, Tuple, Union
from .constants import YangsonException
from .context import Context
from .instance import InstanceNode
from .nodeset import NodeSet
from .statement import Statement
from .typealiases import *
from .xpathparser import XPathParser
# Local type aliases
Range = List[List[Union[int, decimal.Decimal]]]
......@@ -94,6 +97,9 @@ class DataType:
"""String representation of the receiver type."""
return self.__class__.__name__.lower()
def _deref(self, node: InstanceNode) -> NodeSet:
return NodeSet([])
def parse_value(self, input: str) -> ScalarValue:
"""Parse value of a data type.
......@@ -422,7 +428,11 @@ class LeafrefType(LinkType):
:param stmt: YANG ``type leafref`` statement
:param mid: id of the context module
"""
self.path = stmt.find1("path", required=True).argument
self.path = XPathParser(
stmt.find1("path", required=True).argument, mid).parse()
def _deref(self, node: InstanceNode) -> NodeSet:
return self.path.evaluate(node)
class InstanceIdentifierType(LinkType):
"""Class representing YANG "instance-identifier" type."""
......
......@@ -2,6 +2,7 @@
from datetime import datetime
from typing import List, Union
from .typealiases import *
# Local type aliases
......
......@@ -245,8 +245,13 @@ class Number(Expr):
class PathExpr(BinaryExpr):
def _eval(self, xctx: XPathContext):
res = self.left._eval(xctx)
return self.right._eval(xctx.update_cnode(res))
ns = self.left._eval(xctx)
if not isinstance(ns, NodeSet):
raise XPathTypeError(ns)
res = NodeSet([])
for n in ns:
res = res.union(self.right._eval(xctx.update_cnode(n)))
return res
class FilterExpr(Expr):
......@@ -352,6 +357,18 @@ class FuncCurrent(Expr):
def _eval(self, xctx: XPathContext) -> NodeSet:
return NodeSet([xctx.origin])
class FuncDeref(UnaryExpr):
def _eval(self, xctx: XPathContext) -> bool:
ns = self.expr._eval(xctx)
if not isinstance(ns, NodeSet):
raise XPathTypeError(ns)
ref = ns[0]
if ref.is_structured():
return NodeSet([])
tgt = ref.schema_node.type._deref(ref)
return NodeSet([n for n in tgt if str(n) == str(ref)])
class FuncFalse(Expr):
def _eval(self, xctx: XPathContext) -> bool:
......
......@@ -300,6 +300,9 @@ class XPathParser(Parser):
def _func_current(self) -> FuncCurrent:
return FuncCurrent()
def _func_deref(self) -> FuncDeref:
return FuncDeref(self.parse())
def _func_false(self) -> FuncFalse:
return FuncFalse()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment