@@ -12,10 +12,17 @@ class Resolver(object):
12
12
13
13
_match_cache = {}
14
14
15
- def __init__ (self , pathattr = 'name' ):
16
- """Resolve :any:`NodeMixin` paths using attribute `pathattr`."""
15
+ def __init__ (self , pathattr = 'name' , ignorecase = False ):
16
+ """
17
+ Resolve :any:`NodeMixin` paths using attribute `pathattr`.
18
+
19
+ Keyword Args:
20
+ name (str): Name of the node attribute to be used for resolving
21
+ ignorecase (bool): Enable case insensisitve handling.
22
+ """
17
23
super (Resolver , self ).__init__ ()
18
24
self .pathattr = pathattr
25
+ self .ignorecase = ignorecase
19
26
20
27
def get (self , node , path ):
21
28
"""
@@ -75,8 +82,19 @@ def get(self, node, path):
75
82
76
83
.. note:: Please not that :any:`get()` returned `None` in exactly that case above,
77
84
which was a bug until version 1.8.1.
85
+
86
+ Case insensitive matching:
87
+
88
+ >>> r.get(top, '/TOP')
89
+ Traceback (most recent call last):
90
+ ...
91
+ anytree.resolver.ResolverError: unknown root node '/TOP'. root is '/top'.
92
+
93
+ >>> r = Resolver('name', ignorecase=True)
94
+ >>> r.get(top, '/TOp')
95
+ Node('/top')
78
96
"""
79
- node , parts = self .__start (node , path , Resolver .__cmp )
97
+ node , parts = self .__start (node , path , self .__cmp )
80
98
for part in parts :
81
99
if part == ".." :
82
100
parent = node .parent
@@ -90,8 +108,9 @@ def get(self, node, path):
90
108
return node
91
109
92
110
def __get (self , node , name ):
111
+ namestr = str (name )
93
112
for child in node .children :
94
- if str (_getattr (child , self .pathattr )) == name :
113
+ if self . __cmp (_getattr (child , self .pathattr ), namestr ) :
95
114
return child
96
115
raise ChildResolverError (node , name , self .pathattr )
97
116
@@ -163,7 +182,7 @@ def glob(self, node, path):
163
182
...
164
183
anytree.resolver.RootResolverError: Cannot go above root node Node('/top')
165
184
"""
166
- node , parts = self .__start (node , path , Resolver .__match )
185
+ node , parts = self .__start (node , path , self .__match )
167
186
return self .__glob (node , parts )
168
187
169
188
def __start (self , node , path , cmp_ ):
@@ -172,7 +191,7 @@ def __start(self, node, path, cmp_):
172
191
# resolve root
173
192
if path .startswith (sep ):
174
193
node = node .root
175
- rootpart = str ( _getattr (node , self .pathattr ) )
194
+ rootpart = _getattr (node , self .pathattr )
176
195
parts .pop (0 )
177
196
if not parts [0 ]:
178
197
msg = "root node missing. root is '%s%s'."
@@ -209,9 +228,9 @@ def __glob(self, node, parts):
209
228
def __find (self , node , pat , remainder ):
210
229
matches = []
211
230
for child in node .children :
212
- name = str ( _getattr (child , self .pathattr ) )
231
+ name = _getattr (child , self .pathattr )
213
232
try :
214
- if Resolver .__match (name , pat ):
233
+ if self .__match (name , pat ):
215
234
if remainder :
216
235
matches += self .__glob (child , remainder )
217
236
else :
@@ -226,20 +245,25 @@ def is_wildcard(path):
226
245
"""Return `True` is a wildcard."""
227
246
return "?" in path or "*" in path
228
247
229
- @ staticmethod
230
- def __match ( name , pat ):
248
+ def __match ( self , name , pat ):
249
+ k = ( pat , self . ignorecase )
231
250
try :
232
- re_pat = Resolver ._match_cache [pat ]
251
+ re_pat = Resolver ._match_cache [k ]
233
252
except KeyError :
234
253
res = Resolver .__translate (pat )
235
254
if len (Resolver ._match_cache ) >= _MAXCACHE :
236
255
Resolver ._match_cache .clear ()
237
- Resolver ._match_cache [pat ] = re_pat = re .compile (res )
256
+ flags = 0
257
+ if self .ignorecase :
258
+ flags |= re .IGNORECASE
259
+ Resolver ._match_cache [k ] = re_pat = re .compile (res , flags = flags )
238
260
return re_pat .match (name ) is not None
239
261
240
- @staticmethod
241
- def __cmp (name , pat ):
242
- return name == pat
262
+ def __cmp (self , name , pat ):
263
+ if self .ignorecase :
264
+ return name .upper () == pat .upper ()
265
+ else :
266
+ return name == pat
243
267
244
268
@staticmethod
245
269
def __translate (pat ):
@@ -283,4 +307,4 @@ def __init__(self, node, child, pathattr):
283
307
284
308
285
309
def _getattr (node , name ):
286
- return getattr (node , name , None )
310
+ return str ( getattr (node , name , None ) )
0 commit comments