self.assertEquals(0, len(find_all(t, "//NameNode[not(@name)]")))
self.assertEquals(2, len(find_all(t, "//NameNode[not(@honking)]")))
+ def test_node_path_and(self):
+ t = self._build_tree()
+ self.assertEquals(1, len(find_all(t, "//DefNode[.//ReturnStatNode and .//NameNode]")))
+ self.assertEquals(0, len(find_all(t, "//NameNode[@honking and @name]")))
+ self.assertEquals(0, len(find_all(t, "//NameNode[@name and @honking]")))
+ self.assertEquals(2, len(find_all(t, "//DefNode[.//NameNode[@name] and @name]")))
+
def test_node_path_attribute_string_predicate(self):
t = self._build_tree()
self.assertEquals(1, len(find_all(t, "//NameNode[@name = 'decorator']")))
def parse_path_value(next):
token = next()
value = token[0]
- if value[:1] == "'" or value[:1] == '"':
- value = value[1:-1]
- else:
+ if value:
+ if value[:1] == "'" or value[:1] == '"':
+ return value[1:-1]
try:
- value = int(value)
+ return int(value)
except ValueError:
- raise ValueError("Invalid attribute predicate: '%s'" % value)
- return value
+ pass
+ else:
+ name = token[1].lower()
+ if name == 'true':
+ return True
+ elif name == 'false':
+ return False
+ raise ValueError("Invalid attribute predicate: '%s'" % value)
def handle_predicate(next, token):
token = next()
if token[0] == "/":
token = next()
+ if not token[0] and token[1] == 'and':
+ return logical_and(selector, handle_predicate(next, token))
+
def select(result):
for node in result:
subresult = iter((node,))
yield node
return select
+def logical_and(lhs_selects, rhs_select):
+ def select(result):
+ for node in result:
+ subresult = iter((node,))
+ for select in lhs_selects:
+ subresult = select(subresult)
+ predicate_result = _get_first_or_none(subresult)
+ subresult = iter((node,))
+ if predicate_result is not None:
+ for result_node in rhs_select(subresult):
+ yield node
+ return select
+
+
operations = {
"@": handle_attribute,
"": handle_name,