anytree
anytree copied to clipboard
Add hierarchy wildcard `**` to Resolver.glob()
Version 2.1.1 - glob returns only the closest children:
d = Node("parent")
child_1 = Node("child_1", parent=d, value="5")
child_2 = Node("child_2", parent=d, value="5")
grandson_1 = Node("child_1", parent=child_1, value="5")
grandson_2 = Node("child_1", parent=child_1, value="5")
r = Resolver("value")
nodes = r.glob(d, "5")
Will return only child_1 and child_2
This is the intended behaviour here. The glob()
implementation lacks of a hierarchy wildcard like **
. This might be implemented in a future release:
r.glob(d, "**/5")
Just use an iterator with a filter, which does the **/5
:
nodes = list(PreOrderIter(d, lambda n: hasattr(n, "value") and n.value == "5"))
Or with wildcard matching:
from fnmatch import fnmatchcase
nodes = list(PreOrderIter(d, lambda n: hasattr(n, "value") and fnmatchcase(n.value, "*5")))
I would change this ticket into a feature request for hierarchy wildcard **
.
HTH
Yes, I used iterator instead. in that case - what's the difference between glob and iterator? Would wild card support any descendant without specifying the amount of ** ?
The Resolver()
eases the tree interaction on a higher level. The iterator gives you more flexibility.
**
will match any descendant.
If you just want to have the first three level, you can invoke glob()
multiple times and concatenate the result:
nodes = list(glob('5')) + list(glob('*/5')) + list (glob('*/*/5'))
Anyway. An iterator with a maxlevel is more elegant:
nodes = list(PreOrderIter(d, maxlevel=3, filter_=lambda n: hasattr(n, "value") and n.value == "5"))
This would be very handy, indeed!
**
will match any descendant.
I think, it should also allowed to be empty, i.e. match the root.