Skip to content

Commit

Permalink
Merge branch 'moi90-recursive-wildcard' into 2.x.x
Browse files Browse the repository at this point in the history
  • Loading branch information
c0fec0de committed Oct 11, 2023
2 parents abdc0af + d18be95 commit 6fe3851
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 21 deletions.
55 changes: 35 additions & 20 deletions anytree/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import re

from anytree.iterators.preorderiter import PreOrderIter

from .config import ASSERTIONS

_MAXCACHE = 20
Expand Down Expand Up @@ -207,26 +209,39 @@ def __start(self, node, path, cmp_):
def __glob(self, node, parts):
if ASSERTIONS: # pragma: no branch
assert node is not None
nodes = []
if parts:
name = parts[0]
remainder = parts[1:]
# handle relative
if name == "..":
parent = node.parent
if parent is None:
raise RootResolverError(node)
nodes += self.__glob(parent, remainder)
elif name in ("", "."):
nodes += self.__glob(node, remainder)
else:
matches = self.__find(node, name, remainder)
if not matches and not Resolver.is_wildcard(name):
raise ChildResolverError(node, name, self.pathattr)
nodes += matches
else:
nodes = [node]
return nodes

if not parts:
return [node]

name = parts[0]
remainder = parts[1:]

# handle relative
if name == "..":
parent = node.parent
if parent is None:
raise RootResolverError(node)
return self.__glob(parent, remainder)

if name in ("", "."):
return self.__glob(node, remainder)

# handle recursive
if name == "**":
matches = []
for subnode in PreOrderIter(node):
try:
for match in self.__glob(subnode, remainder):
if match not in matches:
matches.append(match)
except ChildResolverError:
pass
return matches

matches = self.__find(node, name, remainder)
if not matches and not Resolver.is_wildcard(name):
raise ChildResolverError(node, name, self.pathattr)
return matches

def __find(self, node, pat, remainder):
matches = []
Expand Down
2 changes: 1 addition & 1 deletion tests/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


def eq_(one, other):
assert one == other
assert one == other, "{one} != {other}".format(one=one, other=other)


# hack own assert_raises, because py26 has a different impelmentation
Expand Down
8 changes: 8 additions & 0 deletions tests/test_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ def test_glob():
with assert_raises(at.ResolverError, "unknown root node '/z*'. root is '/top'."):
r.glob(sub1, "/z*")

# Recursive matching
assert r.glob(top, "**/sub0") == [sub0, sub0sub0, sub0sub1sub0, sub1sub0]
assert r.glob(top, "**/sub0/sub0") == [sub0sub0]
assert r.glob(top, "**/**/sub0") == [sub0, sub0sub0, sub0sub1sub0, sub1sub0]
assert r.glob(top, "sub0/**/sub0") == [sub0sub0, sub0sub1sub0]
with assert_raises(at.ResolverError, "unknown root node '/sub0'. root is '/top'."):
r.glob(top, "/sub0/**/sub0")


def test_glob_cache():
"""Wildcard Cache."""
Expand Down

0 comments on commit 6fe3851

Please sign in to comment.