Index: third_party/scons/scons-local/SCons/Node/FS.py |
=================================================================== |
--- third_party/scons/scons-local/SCons/Node/FS.py (revision 7505) |
+++ third_party/scons/scons-local/SCons/Node/FS.py (working copy) |
@@ -33,7 +33,7 @@ |
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
# |
-__revision__ = "src/engine/SCons/Node/FS.py 3603 2008/10/10 05:46:45 scons" |
+__revision__ = "src/engine/SCons/Node/FS.py 3842 2008/12/20 22:59:52 scons" |
import fnmatch |
from itertools import izip |
@@ -61,6 +61,23 @@ |
do_store_info = True |
+ |
+class EntryProxyAttributeError(AttributeError): |
+ """ |
+ An AttributeError subclass for recording and displaying the name |
+ of the underlying Entry involved in an AttributeError exception. |
+ """ |
+ def __init__(self, entry_proxy, attribute): |
+ AttributeError.__init__(self) |
+ self.entry_proxy = entry_proxy |
+ self.attribute = attribute |
+ def __str__(self): |
+ entry = self.entry_proxy.get() |
+ fmt = "%s instance %s has no attribute %s" |
+ return fmt % (entry.__class__.__name__, |
+ repr(entry.name), |
+ repr(self.attribute)) |
+ |
# The max_drift value: by default, use a cached signature value for |
# any file that's been untouched for more than two days. |
default_max_drift = 2*24*60*60 |
@@ -225,8 +242,6 @@ |
if func == Link_Funcs[-1]: |
# exception of the last link method (copy) are fatal |
raise |
- else: |
- pass |
return 0 |
Link = SCons.Action.Action(LinkFunc, None) |
@@ -485,16 +500,11 @@ |
except KeyError: |
try: |
attr = SCons.Util.Proxy.__getattr__(self, name) |
- except AttributeError: |
- entry = self.get() |
- classname = string.split(str(entry.__class__), '.')[-1] |
- if classname[-2:] == "'>": |
- # new-style classes report their name as: |
- # "<class 'something'>" |
- # instead of the classic classes: |
- # "something" |
- classname = classname[:-2] |
- raise AttributeError, "%s instance '%s' has no attribute '%s'" % (classname, entry.name, name) |
+ except AttributeError, e: |
+ # Raise our own AttributeError subclass with an |
+ # overridden __str__() method that identifies the |
+ # name of the entry that caused the exception. |
+ raise EntryProxyAttributeError(self, name) |
return attr |
else: |
return attr_function(self) |
@@ -592,7 +602,7 @@ |
if self.duplicate or self.is_derived(): |
return self.get_path() |
srcnode = self.srcnode() |
- if srcnode.stat() is None and not self.stat() is None: |
+ if srcnode.stat() is None and self.stat() is not None: |
result = self.get_path() |
else: |
result = srcnode.get_path() |
@@ -607,7 +617,7 @@ |
# values that the underlying stat() method saved. |
try: del self._memo['stat'] |
except KeyError: pass |
- if not self is srcnode: |
+ if self is not srcnode: |
try: del srcnode._memo['stat'] |
except KeyError: pass |
return result |
@@ -625,7 +635,7 @@ |
return result |
def exists(self): |
- return not self.stat() is None |
+ return self.stat() is not None |
def rexists(self): |
return self.rfile().exists() |
@@ -642,11 +652,11 @@ |
def isdir(self): |
st = self.stat() |
- return not st is None and stat.S_ISDIR(st[stat.ST_MODE]) |
+ return st is not None and stat.S_ISDIR(st[stat.ST_MODE]) |
def isfile(self): |
st = self.stat() |
- return not st is None and stat.S_ISREG(st[stat.ST_MODE]) |
+ return st is not None and stat.S_ISREG(st[stat.ST_MODE]) |
if hasattr(os, 'symlink'): |
def islink(self): |
@@ -886,7 +896,7 @@ |
def must_be_same(self, klass): |
"""Called to make sure a Node is a Dir. Since we're an |
Entry, we can morph into one.""" |
- if not self.__class__ is klass: |
+ if self.__class__ is not klass: |
self.__class__ = klass |
self._morph() |
self.clear() |
@@ -910,7 +920,7 @@ |
def rel_path(self, other): |
d = self.disambiguate() |
- if d.__class__ == Entry: |
+ if d.__class__ is Entry: |
raise "rel_path() could not disambiguate File/Dir" |
return d.rel_path(other) |
@@ -1065,7 +1075,7 @@ |
""" |
curr=self._cwd |
try: |
- if not dir is None: |
+ if dir is not None: |
self._cwd = dir |
if change_os_dir: |
os.chdir(dir.abspath) |
@@ -1171,7 +1181,7 @@ |
return root._lookup_abs(p, fsclass, create) |
def Entry(self, name, directory = None, create = 1): |
- """Lookup or create a generic Entry node with the specified name. |
+ """Look up or create a generic Entry node with the specified name. |
If the name is a relative path (begins with ./, ../, or a file |
name), then it is looked up relative to the supplied directory |
node, or to the top level directory of the FS (supplied at |
@@ -1180,7 +1190,7 @@ |
return self._lookup(name, directory, Entry, create) |
def File(self, name, directory = None, create = 1): |
- """Lookup or create a File node with the specified name. If |
+ """Look up or create a File node with the specified name. If |
the name is a relative path (begins with ./, ../, or a file name), |
then it is looked up relative to the supplied directory node, |
or to the top level directory of the FS (supplied at construction |
@@ -1192,7 +1202,7 @@ |
return self._lookup(name, directory, File, create) |
def Dir(self, name, directory = None, create = True): |
- """Lookup or create a Dir node with the specified name. If |
+ """Look up or create a Dir node with the specified name. If |
the name is a relative path (begins with ./, ../, or a file name), |
then it is looked up relative to the supplied directory node, |
or to the top level directory of the FS (supplied at construction |
@@ -1348,7 +1358,7 @@ |
del node._srcreps |
except AttributeError: |
pass |
- if duplicate != None: |
+ if duplicate is not None: |
node.duplicate=duplicate |
def __resetDuplicate(self, node): |
@@ -1367,8 +1377,7 @@ |
Looks up or creates a directory node named 'name' relative to |
this directory. |
""" |
- dir = self.fs.Dir(name, self, create) |
- return dir |
+ return self.fs.Dir(name, self, create) |
def File(self, name): |
""" |
@@ -1451,15 +1460,15 @@ |
"""Return a path to "other" relative to this directory. |
""" |
- # This complicated and expensive method, which constructs relative |
- # paths between arbitrary Node.FS objects, is no longer used |
- # by SCons itself. It was introduced to store dependency paths |
- # in .sconsign files relative to the target, but that ended up |
- # being significantly inefficient. |
+ # This complicated and expensive method, which constructs relative |
+ # paths between arbitrary Node.FS objects, is no longer used |
+ # by SCons itself. It was introduced to store dependency paths |
+ # in .sconsign files relative to the target, but that ended up |
+ # being significantly inefficient. |
# |
- # We're continuing to support the method because some SConstruct |
- # files out there started using it when it was available, and |
- # we're all about backwards compatibility.. |
+ # We're continuing to support the method because some SConstruct |
+ # files out there started using it when it was available, and |
+ # we're all about backwards compatibility.. |
try: |
memo_dict = self._memo['rel_path'] |
@@ -1473,11 +1482,9 @@ |
pass |
if self is other: |
- |
result = '.' |
elif not other in self.path_elements: |
- |
try: |
other_dir = other.get_dir() |
except AttributeError: |
@@ -1491,9 +1498,7 @@ |
result = other.name |
else: |
result = dir_rel_path + os.sep + other.name |
- |
else: |
- |
i = self.path_elements.index(other) + 1 |
path_elems = ['..'] * (len(self.path_elements) - i) \ |
@@ -1544,7 +1549,7 @@ |
def build(self, **kw): |
"""A null "builder" for directories.""" |
global MkdirBuilder |
- if not self.builder is MkdirBuilder: |
+ if self.builder is not MkdirBuilder: |
apply(SCons.Node.Node.build, [self,], kw) |
# |
@@ -1560,10 +1565,9 @@ |
if parent.exists(): |
break |
listDirs.append(parent) |
- p = parent.up() |
- if p is None: |
- raise SCons.Errors.StopError, parent.path |
- parent = p |
+ parent = parent.up() |
+ else: |
+ raise SCons.Errors.StopError, parent.path |
listDirs.reverse() |
for dirnode in listDirs: |
try: |
@@ -1583,7 +1587,7 @@ |
def multiple_side_effect_has_builder(self): |
global MkdirBuilder |
- return not self.builder is MkdirBuilder and self.has_builder() |
+ return self.builder is not MkdirBuilder and self.has_builder() |
def alter_targets(self): |
"""Return any corresponding targets in a variant directory. |
@@ -1622,7 +1626,7 @@ |
def is_up_to_date(self): |
"""If any child is not up-to-date, then this directory isn't, |
either.""" |
- if not self.builder is MkdirBuilder and not self.exists(): |
+ if self.builder is not MkdirBuilder and not self.exists(): |
return 0 |
up_to_date = SCons.Node.up_to_date |
for kid in self.children(): |
@@ -1795,7 +1799,7 @@ |
except TypeError: pass |
node = self.srcdir_duplicate(name) |
if isinstance(node, Dir): |
- node = None |
+ return None |
return node |
def walk(self, func, arg): |
@@ -1888,6 +1892,7 @@ |
for srcdir in self.srcdir_list(): |
search_dir_list.extend(srcdir.get_all_rdirs()) |
+ selfEntry = self.Entry |
names = [] |
for dir in search_dir_list: |
# We use the .name attribute from the Node because the keys of |
@@ -1900,35 +1905,36 @@ |
if not strings: |
# Make sure the working directory (self) actually has |
# entries for all Nodes in repositories or variant dirs. |
- map(self.Entry, node_names) |
+ map(selfEntry, node_names) |
if ondisk: |
try: |
disk_names = os.listdir(dir.abspath) |
except os.error: |
- pass |
- else: |
- names.extend(disk_names) |
- if not strings: |
- # We're going to return corresponding Nodes in |
- # the local directory, so we need to make sure |
- # those Nodes exist. We only want to create |
- # Nodes for the entries that will match the |
- # specified pattern, though, which means we |
- # need to filter the list here, even though |
- # the overall list will also be filtered later, |
- # after we exit this loop. |
- if pattern[0] != '.': |
- #disk_names = [ d for d in disk_names if d[0] != '.' ] |
- disk_names = filter(lambda x: x[0] != '.', disk_names) |
- disk_names = fnmatch.filter(disk_names, pattern) |
- rep_nodes = map(dir.Entry, disk_names) |
- #rep_nodes = [ n.disambiguate() for n in rep_nodes ] |
- rep_nodes = map(lambda n: n.disambiguate(), rep_nodes) |
- for node, name in izip(rep_nodes, disk_names): |
- n = self.Entry(name) |
- if n.__class__ != node.__class__: |
- n.__class__ = node.__class__ |
- n._morph() |
+ continue |
+ names.extend(disk_names) |
+ if not strings: |
+ # We're going to return corresponding Nodes in |
+ # the local directory, so we need to make sure |
+ # those Nodes exist. We only want to create |
+ # Nodes for the entries that will match the |
+ # specified pattern, though, which means we |
+ # need to filter the list here, even though |
+ # the overall list will also be filtered later, |
+ # after we exit this loop. |
+ if pattern[0] != '.': |
+ #disk_names = [ d for d in disk_names if d[0] != '.' ] |
+ disk_names = filter(lambda x: x[0] != '.', disk_names) |
+ disk_names = fnmatch.filter(disk_names, pattern) |
+ dirEntry = dir.Entry |
+ for name in disk_names: |
+ # Add './' before disk filename so that '#' at |
+ # beginning of filename isn't interpreted. |
+ name = './' + name |
+ node = dirEntry(name).disambiguate() |
+ n = selfEntry(name) |
+ if n.__class__ != node.__class__: |
+ n.__class__ = node.__class__ |
+ n._morph() |
names = set(names) |
if pattern[0] != '.': |
@@ -2137,14 +2143,13 @@ |
strings = getattr(self, nattr) |
nodeinfos = getattr(self, sattr) |
except AttributeError: |
- pass |
- else: |
- nodes = [] |
- for s, ni in izip(strings, nodeinfos): |
- if not isinstance(s, SCons.Node.Node): |
- s = ni.str_to_node(s) |
- nodes.append(s) |
- setattr(self, nattr, nodes) |
+ continue |
+ nodes = [] |
+ for s, ni in izip(strings, nodeinfos): |
+ if not isinstance(s, SCons.Node.Node): |
+ s = ni.str_to_node(s) |
+ nodes.append(s) |
+ setattr(self, nattr, nodes) |
def format(self, names=0): |
result = [] |
bkids = self.bsources + self.bdepends + self.bimplicit |
@@ -2177,26 +2182,25 @@ |
def Entry(self, name): |
"""Create an entry node named 'name' relative to |
- the SConscript directory of this file.""" |
- cwd = self.cwd or self.fs._cwd |
- return cwd.Entry(name) |
+ the directory of this file.""" |
+ return self.dir.Entry(name) |
def Dir(self, name, create=True): |
"""Create a directory node named 'name' relative to |
- the SConscript directory of this file.""" |
- cwd = self.cwd or self.fs._cwd |
- return cwd.Dir(name, create) |
+ the directory of this file.""" |
+ return self.dir.Dir(name, create=create) |
def Dirs(self, pathlist): |
"""Create a list of directories relative to the SConscript |
directory of this file.""" |
+ # TODO(1.5) |
+ # return [self.Dir(p) for p in pathlist] |
return map(lambda p, s=self: s.Dir(p), pathlist) |
def File(self, name): |
"""Create a file node named 'name' relative to |
- the SConscript directory of this file.""" |
- cwd = self.cwd or self.fs._cwd |
- return cwd.File(name) |
+ the directory of this file.""" |
+ return self.dir.File(name) |
#def generate_build_dict(self): |
# """Return an appropriate dictionary of values for building |
@@ -2390,26 +2394,24 @@ |
try: |
value = getattr(old_entry, attr) |
except AttributeError: |
- pass |
- else: |
- setattr(binfo, attr, value) |
- delattr(old_entry, attr) |
+ continue |
+ setattr(binfo, attr, value) |
+ delattr(old_entry, attr) |
for attr in self.convert_sig_attrs: |
try: |
sig_list = getattr(old_entry, attr) |
except AttributeError: |
- pass |
- else: |
- value = [] |
- for sig in sig_list: |
- ninfo = self.new_ninfo() |
- if len(sig) == 32: |
- ninfo.csig = sig |
- else: |
- ninfo.timestamp = sig |
- value.append(ninfo) |
- setattr(binfo, attr, value) |
- delattr(old_entry, attr) |
+ continue |
+ value = [] |
+ for sig in sig_list: |
+ ninfo = self.new_ninfo() |
+ if len(sig) == 32: |
+ ninfo.csig = sig |
+ else: |
+ ninfo.timestamp = sig |
+ value.append(ninfo) |
+ setattr(binfo, attr, value) |
+ delattr(old_entry, attr) |
return new_entry |
memoizer_counters.append(SCons.Memoize.CountValue('get_stored_info')) |
@@ -2473,6 +2475,7 @@ |
pass |
if scanner: |
+ # result = [n.disambiguate() for n in scanner(self, env, path)] |
result = scanner(self, env, path) |
result = map(lambda N: N.disambiguate(), result) |
else: |
@@ -2576,7 +2579,7 @@ |
scb = self.sbuilder |
except AttributeError: |
scb = self.sbuilder = self.find_src_builder() |
- return not scb is None |
+ return scb is not None |
def alter_targets(self): |
"""Return any corresponding targets in a variant directory. |
@@ -2649,7 +2652,7 @@ |
# Duplicate from source path if we are set up to do this. |
if self.duplicate and not self.is_derived() and not self.linked: |
src = self.srcnode() |
- if not src is self: |
+ if src is not self: |
# At this point, src is meant to be copied in a variant directory. |
src = src.rfile() |
if src.abspath != self.abspath: |
@@ -2683,23 +2686,22 @@ |
old = self.get_stored_info() |
mtime = self.get_timestamp() |
- csig = None |
max_drift = self.fs.max_drift |
if max_drift > 0: |
if (time.time() - mtime) > max_drift: |
try: |
n = old.ninfo |
if n.timestamp and n.csig and n.timestamp == mtime: |
- csig = n.csig |
+ return n.csig |
except AttributeError: |
pass |
elif max_drift == 0: |
try: |
- csig = old.ninfo.csig |
+ return old.ninfo.csig |
except AttributeError: |
pass |
- return csig |
+ return None |
def get_csig(self): |
""" |
@@ -2754,7 +2756,7 @@ |
return 1 |
def changed_state(self, target, prev_ni): |
- return (self.state != SCons.Node.up_to_date) |
+ return self.state != SCons.Node.up_to_date |
def changed_timestamp_then_content(self, target, prev_ni): |
if not self.changed_timestamp_match(target, prev_ni): |
@@ -2875,13 +2877,14 @@ |
# Add the path to the cache signature, because multiple |
# targets built by the same action will all have the same |
# build signature, and we have to differentiate them somehow. |
- children = self.children() |
+ children = self.children() |
+ executor = self.get_executor() |
+ # sigs = [n.get_cachedir_csig() for n in children] |
sigs = map(lambda n: n.get_cachedir_csig(), children) |
- executor = self.get_executor() |
sigs.append(SCons.Util.MD5signature(executor.get_contents())) |
sigs.append(self.path) |
- self.cachesig = SCons.Util.MD5collect(sigs) |
- return self.cachesig |
+ result = self.cachesig = SCons.Util.MD5collect(sigs) |
+ return result |
default_fs = None |
@@ -2971,14 +2974,11 @@ |
except KeyError: |
pass |
- if verbose: |
+ if verbose and not callable(verbose): |
if not SCons.Util.is_String(verbose): |
verbose = "find_file" |
- if not callable(verbose): |
- verbose = ' %s: ' % verbose |
- verbose = lambda s, v=verbose: sys.stdout.write(v + s) |
- else: |
- verbose = lambda x: x |
+ verbose = ' %s: ' % verbose |
+ verbose = lambda s, v=verbose: sys.stdout.write(v + s) |
filedir, filename = os.path.split(filename) |
if filedir: |
@@ -3017,10 +3017,12 @@ |
result = None |
for dir in paths: |
- verbose("looking for '%s' in '%s' ...\n" % (filename, dir)) |
+ if verbose: |
+ verbose("looking for '%s' in '%s' ...\n" % (filename, dir)) |
node, d = dir.srcdir_find_file(filename) |
if node: |
- verbose("... FOUND '%s' in '%s'\n" % (filename, d)) |
+ if verbose: |
+ verbose("... FOUND '%s' in '%s'\n" % (filename, d)) |
result = node |
break |
@@ -3048,12 +3050,11 @@ |
# affected. XXX The way to check if Execute() is in the stacktrace |
# is a very dirty hack and should be replaced by a more sensible |
# solution. |
- must_invalidate = 0 |
- tb = extract_stack() |
- for f in tb: |
+ for f in extract_stack(): |
if f[2] == 'Execute' and f[0][-14:] == 'Environment.py': |
- must_invalidate = 1 |
- if not must_invalidate: |
+ break |
+ else: |
+ # Dont have to invalidate, so return |
return |
if not SCons.Util.is_List(targets): |