22
22
from time import time , sleep
23
23
from types import ListType
24
24
from shutil import copyfile
25
- from os .path import join , splitext , exists , relpath , dirname , basename , split , abspath , isfile , isdir
25
+ from os .path import join , splitext , exists , relpath , dirname , basename , split , abspath , isfile , isdir , normcase
26
+ from itertools import chain
26
27
from inspect import getmro
27
28
from copy import deepcopy
28
29
from tools .config import Config
42
43
CPU_COUNT_MIN = 1
43
44
CPU_COEF = 1
44
45
46
+ class LazyDict (dict ):
47
+ def __init__ (self ):
48
+ self .eager = {}
49
+ self .lazy = {}
50
+
51
+ def add_lazy (self , key , thunk ):
52
+ if key in self .eager :
53
+ del self .eager [key ]
54
+ self .lazy [key ] = thunk
55
+
56
+ def __getitem__ (self , key ):
57
+ if (key not in self .eager
58
+ and key in self .lazy ):
59
+ self .eager [key ] = self .lazy [key ]()
60
+ del self .lazy [key ]
61
+ return self .eager [key ]
62
+
63
+ def __setitem__ (self , key , value ):
64
+ self .eager [key ] = value
65
+
66
+ def __delitem__ (self , key ):
67
+ if key in self .eager :
68
+ del self .eager [key ]
69
+ else :
70
+ del self .lazy [key ]
71
+
72
+ def __contains__ (self , key ):
73
+ return key in self .eager or key in self .lazy
74
+
75
+ def __iter__ (self ):
76
+ return chain (iter (self .eager ), iter (self .lazy ))
77
+
78
+ def __len__ (self ):
79
+ return len (self .eager ) + len (self .lazy )
80
+
81
+ def __str__ (self ):
82
+ return "Lazy{%s}" % (
83
+ ", " .join ("%r: %r" % (k , v ) for k , v in
84
+ chain (self .eager .iteritems (), ((k , "not evaluated" )
85
+ for k in self .lazy ))))
86
+
87
+ def update (self , other ):
88
+ if isinstance (other , LazyDict ):
89
+ self .eager .update (other .eager )
90
+ self .lazy .update (other .lazy )
91
+ else :
92
+ self .eager .update (other )
93
+
94
+ def iteritems (self ):
95
+ """Warning: This forces the evaluation all of the items in this LazyDict
96
+ that are iterated over."""
97
+ for k , v in self .eager .iteritems ():
98
+ yield k , v
99
+ for k in self .lazy .keys ():
100
+ yield k , self [k ]
101
+
102
+ def apply (self , fn ):
103
+ """Delay the application of a computation to all items of the lazy dict.
104
+ Does no computation now. Instead the comuptation is performed when a
105
+ consumer attempts to access a value in this LazyDict"""
106
+ new_lazy = {}
107
+ for k , f in self .lazy .iteritems ():
108
+ def closure (f = f ):
109
+ return fn (f ())
110
+ new_lazy [k ] = closure
111
+ for k , v in self .eager .iteritems ():
112
+ def closure (v = v ):
113
+ return fn (v )
114
+ new_lazy [k ] = closure
115
+ self .lazy = new_lazy
116
+ self .eager = {}
117
+
45
118
class Resources :
46
119
def __init__ (self , base_path = None ):
47
120
self .base_path = base_path
@@ -74,7 +147,7 @@ def __init__(self, base_path=None):
74
147
self .json_files = []
75
148
76
149
# Features
77
- self .features = {}
150
+ self .features = LazyDict ()
78
151
79
152
def __add__ (self , resources ):
80
153
if resources is None :
@@ -165,7 +238,9 @@ def relative_to(self, base, dot=False):
165
238
v = [rel_path (f , base , dot ) for f in getattr (self , field )]
166
239
setattr (self , field , v )
167
240
168
- self .features = {k : f .relative_to (base , dot ) for k , f in self .features .iteritems () if f }
241
+ def to_apply (feature , base = base , dot = dot ):
242
+ feature .relative_to (base , dot )
243
+ self .features .apply (to_apply )
169
244
170
245
if self .linker_script is not None :
171
246
self .linker_script = rel_path (self .linker_script , base , dot )
@@ -178,7 +253,9 @@ def win_to_unix(self):
178
253
v = [f .replace ('\\ ' , '/' ) for f in getattr (self , field )]
179
254
setattr (self , field , v )
180
255
181
- self .features = {k : f .win_to_unix () for k , f in self .features .iteritems () if f }
256
+ def to_apply (feature ):
257
+ feature .win_to_unix ()
258
+ self .features .apply (to_apply )
182
259
183
260
if self .linker_script is not None :
184
261
self .linker_script = self .linker_script .replace ('\\ ' , '/' )
@@ -306,6 +383,7 @@ def __init__(self, target, notify=None, macros=None, silent=False,
306
383
307
384
# Ignore patterns from .mbedignore files
308
385
self .ignore_patterns = []
386
+ self ._ignore_regex = re .compile ("$^" )
309
387
310
388
# Pre-mbed 2.0 ignore dirs
311
389
self .legacy_ignore_dirs = (LEGACY_IGNORE_DIRS | TOOLCHAINS ) - set ([target .name , LEGACY_TOOLCHAIN_NAMES [self .name ]])
@@ -511,10 +589,7 @@ def need_update(self, target, dependencies):
511
589
512
590
def is_ignored (self , file_path ):
513
591
"""Check if file path is ignored by any .mbedignore thus far"""
514
- for pattern in self .ignore_patterns :
515
- if fnmatch .fnmatch (file_path , pattern ):
516
- return True
517
- return False
592
+ return self ._ignore_regex .match (normcase (file_path ))
518
593
519
594
def add_ignore_patterns (self , root , base_path , patterns ):
520
595
"""Add a series of patterns to the ignored paths
@@ -526,9 +601,10 @@ def add_ignore_patterns(self, root, base_path, patterns):
526
601
"""
527
602
real_base = relpath (root , base_path )
528
603
if real_base == "." :
529
- self .ignore_patterns .extend (patterns )
604
+ self .ignore_patterns .extend (normcase ( p ) for p in patterns )
530
605
else :
531
- self .ignore_patterns .extend (join (real_base , pat ) for pat in patterns )
606
+ self .ignore_patterns .extend (normcase (join (real_base , pat )) for pat in patterns )
607
+ self ._ignore_regex = re .compile ("|" .join (fnmatch .translate (p ) for p in self .ignore_patterns ))
532
608
533
609
# Create a Resources object from the path pointed to by *path* by either traversing a
534
610
# a directory structure, when *path* is a directory, or adding *path* to the resources,
@@ -604,7 +680,9 @@ def _add_dir(self, path, resources, base_path, exclude_paths=None):
604
680
elif d .startswith ('FEATURE_' ):
605
681
# Recursively scan features but ignore them in the current scan.
606
682
# These are dynamically added by the config system if the conditions are matched
607
- resources .features [d [8 :]] = self .scan_resources (dir_path , base_path = base_path )
683
+ def closure (dir_path = dir_path , base_path = base_path ):
684
+ return self .scan_resources (dir_path , base_path = base_path )
685
+ resources .features .add_lazy (d [8 :], closure )
608
686
dirs .remove (d )
609
687
elif exclude_paths :
610
688
for exclude_path in exclude_paths :
0 commit comments