summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2008-12-30 19:59:43 (GMT)
committerSteven Knight <knight@baldmt.com>2008-12-30 19:59:43 (GMT)
commit312f88d4f0daa0aa8ccdad202c76b7e297b605cd (patch)
treecbc1682df3b74751e0126f55fe16238135e07b86 /src
parent7b36529d703b12ee4f16c3aa5bd34a002235371d (diff)
downloadSCons-312f88d4f0daa0aa8ccdad202c76b7e297b605cd.zip
SCons-312f88d4f0daa0aa8ccdad202c76b7e297b605cd.tar.gz
SCons-312f88d4f0daa0aa8ccdad202c76b7e297b605cd.tar.bz2
Issue 1417: Fix use of attributes (${SOURCES.windows}, e.g.) with null
lists of targets and sources.
Diffstat (limited to 'src')
-rw-r--r--src/CHANGES.txt3
-rw-r--r--src/engine/SCons/Subst.py14
-rw-r--r--src/engine/SCons/Util.py39
3 files changed, 30 insertions, 26 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 4b759f0..d5e1bf9 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -18,6 +18,9 @@ RELEASE 1.X - XXX
- Add a --warn=future-deprecated option for advance warnings about
deprecated features that still have warnings hidden by default.
+ - Fix use of $SOURCE and $SOURCES attributes when there are no
+ sources specified in the Builder call.
+
From Arve Knudsen:
- Document TestCommon.shobj_prefix variable.
diff --git a/src/engine/SCons/Subst.py b/src/engine/SCons/Subst.py
index 752bbff..fc9d7d9 100644
--- a/src/engine/SCons/Subst.py
+++ b/src/engine/SCons/Subst.py
@@ -253,6 +253,12 @@ class Target_or_Source:
return repr(nl[0])
return ''
+class NullNodeList(SCons.Util.NullSeq):
+ def __call__(self, *args, **kwargs): return ''
+ def __str__(self): return ''
+
+NullNodesList = NullNodeList()
+
def subst_dict(target, source):
"""Create a dictionary for substitution of special
construction variables.
@@ -280,8 +286,8 @@ def subst_dict(target, source):
dict['TARGETS'] = Targets_or_Sources(tnl)
dict['TARGET'] = Target_or_Source(tnl)
else:
- dict['TARGETS'] = None
- dict['TARGET'] = None
+ dict['TARGETS'] = NullNodesList
+ dict['TARGET'] = NullNodesList
if source:
def get_src_subst_proxy(node):
@@ -299,8 +305,8 @@ def subst_dict(target, source):
dict['SOURCES'] = Targets_or_Sources(snl)
dict['SOURCE'] = Target_or_Source(snl)
else:
- dict['SOURCES'] = None
- dict['SOURCE'] = None
+ dict['SOURCES'] = NullNodesList
+ dict['SOURCE'] = NullNodesList
return dict
diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py
index 641db9c..bbd985d 100644
--- a/src/engine/SCons/Util.py
+++ b/src/engine/SCons/Util.py
@@ -136,11 +136,6 @@ class NodeList(UserList):
return string.join(map(str, self.data))
def __getattr__(self, name):
- if not self.data:
- # If there is nothing in the list, then we have no attributes to
- # pass through, so raise AttributeError for everything.
- raise AttributeError, "NodeList has no attribute: %s" % name
-
# Return a list of the attribute, gotten from every element
# in the list
attrList = map(lambda x, n=name: getattr(x, n), self.data)
@@ -1549,29 +1544,29 @@ def MD5collect(signatures):
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68205
# ASPN: Python Cookbook: Null Object Design Pattern
+# TODO(1.5):
+#class Null(object):
class Null:
- """ Null objects always and reliably "do nothging." """
-
+ """ Null objects always and reliably "do nothing." """
def __new__(cls, *args, **kwargs):
if not '_inst' in vars(cls):
#cls._inst = type.__new__(cls, *args, **kwargs)
cls._inst = apply(type.__new__, (cls,) + args, kwargs)
return cls._inst
- def __init__(self, *args, **kwargs):
- pass
- def __call__(self, *args, **kwargs):
- return self
- def __repr__(self):
- return "Null()"
- def __nonzero__(self):
- return False
- def __getattr__(self, mname):
- return self
- def __setattr__(self, name, value):
- return self
- def __delattr__(self, name):
- return self
-
+ def __init__(self, *args, **kwargs): pass
+ def __call__(self, *args, **kwargs): return self
+ def __repr__(self): return "Null(0x%08X)" % id(self)
+ def __nonzero__(self): return False
+ def __getattr__(self, mname): return self
+ def __setattr__(self, name, value): return self
+ def __delattr__(self, name): return self
+
+class NullSeq(Null):
+ def __len__(self): return 0
+ def __iter__(self): return iter(())
+ def __getitem__(self, i): return self
+ def __delitem__(self, i): return self
+ def __setitem__(self, i, v): return self
del __revision__