Skip to content

Commit fa4d42a

Browse files
committed
Resolver: Implement recursive wildcard **
Fixes c0fec0de#4
1 parent d63289b commit fa4d42a

File tree

2 files changed

+38
-20
lines changed

2 files changed

+38
-20
lines changed

anytree/resolver.py

+35-20
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
import re
77

8+
from anytree.iterators.preorderiter import PreOrderIter
9+
810
_MAXCACHE = 20
911

1012

@@ -204,26 +206,39 @@ def __start(self, node, path, cmp_):
204206

205207
def __glob(self, node, parts):
206208
assert node is not None
207-
nodes = []
208-
if parts:
209-
name = parts[0]
210-
remainder = parts[1:]
211-
# handle relative
212-
if name == "..":
213-
parent = node.parent
214-
if parent is None:
215-
raise RootResolverError(node)
216-
nodes += self.__glob(parent, remainder)
217-
elif name in ("", "."):
218-
nodes += self.__glob(node, remainder)
219-
else:
220-
matches = self.__find(node, name, remainder)
221-
if not matches and not Resolver.is_wildcard(name):
222-
raise ChildResolverError(node, name, self.pathattr)
223-
nodes += matches
224-
else:
225-
nodes = [node]
226-
return nodes
209+
210+
if not parts:
211+
return [node]
212+
213+
name = parts[0]
214+
remainder = parts[1:]
215+
216+
# handle relative
217+
if name == "..":
218+
parent = node.parent
219+
if parent is None:
220+
raise RootResolverError(node)
221+
return self.__glob(parent, remainder)
222+
223+
if name in ("", "."):
224+
return self.__glob(node, remainder)
225+
226+
# handle recursive
227+
if name == "**":
228+
matches = []
229+
for n in PreOrderIter(node):
230+
try:
231+
matches += self.__glob(n, remainder)
232+
except ChildResolverError:
233+
pass
234+
return matches
235+
236+
print(node, name, remainder)
237+
238+
matches = self.__find(node, name, remainder)
239+
if not matches and not Resolver.is_wildcard(name):
240+
raise ChildResolverError(node, name, self.pathattr)
241+
return matches
227242

228243
def __find(self, node, pat, remainder):
229244
matches = []

tests/test_resolver.py

+3
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ def test_glob():
8080
with assert_raises(at.ResolverError, "unknown root node '/z*'. root is '/top'."):
8181
r.glob(sub1, "/z*")
8282

83+
# Recursive matching
84+
eq_(r.glob(top, "**/sub0"), [sub0, sub0sub0, sub0sub1sub0, sub1sub0])
85+
8386

8487
def test_glob_cache():
8588
"""Wildcard Cache."""

0 commit comments

Comments
 (0)