CZ-NIC/yangson

XPath addition empty set index out of range

Closed this issue · 2 comments

iwanb commented

This XPath currently fails with IndexError because the nodeset is empty:

    xptest("not(t:contT/t:int8) or t:contT/t:int8 + 2 < 10", "not(test:contT/test:int8) or test:contT/test:int8 + 2.0 < 10.0", True)
tests/test_model.py:474: in xptest
    assert pex.evaluate(node) == res
yangson/xpathast.py:74: in evaluate
    return self._eval(XPathContext(node, node, 1, 1))
yangson/xpathast.py:215: in _eval
    lres, rres = self._eval_ops(xctx)
yangson/xpathast.py:188: in _eval_ops
    return (self.left._eval(xctx), self.right._eval(xctx))
yangson/xpathast.py:274: in _eval
    lres, rres = self._eval_ops(xctx)
yangson/xpathast.py:188: in _eval_ops
    return (self.left._eval(xctx), self.right._eval(xctx))
yangson/xpathast.py:295: in _eval
    lres, rres = self._eval_ops_float(xctx)
yangson/xpathast.py:191: in _eval_ops_float
    return (self.left._eval_float(xctx), self.right._eval_float(xctx))
yangson/xpathast.py:79: in _eval_float
    return float(val)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = []

    def __float__(self: "NodeSet") -> float:
>       return float(self[0].value)
E       IndexError: list index out of range

yangson/nodeset.py:54: IndexError

I expect __float__ should return NaN for an empty set.

Slightly related, the XPath evaluator currently eagerly evaluates both sides of "or" and "and" boolean expressions. It could be lazy/short-circuit like Python instead so the second part of the XPath expression is never evaluated.

I.e. instead of

        lres, rres = self._eval_ops(xctx)
        return lres or rres

do:

        return self.left._eval(xctx) or self.right._eval(xctx)

Same for the AndOperator.

Fixed in 88b56e6 and bd734ab, thanks!

iwanb commented

Great, thank you!