summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2003-10-18 19:22:25 (GMT)
committerSteven Knight <knight@baldmt.com>2003-10-18 19:22:25 (GMT)
commite48bef4f0520f04d71dfa2654621f3aa8a4fabe9 (patch)
treeeb654ea23be6a82f3a29d8b451e652d9cd2e883b /src
parent528ebad33f8ecbe8401ef779ce64648a7de0851a (diff)
downloadSCons-e48bef4f0520f04d71dfa2654621f3aa8a4fabe9.zip
SCons-e48bef4f0520f04d71dfa2654621f3aa8a4fabe9.tar.gz
SCons-e48bef4f0520f04d71dfa2654621f3aa8a4fabe9.tar.bz2
Allow SConsignFile() to take a dbm module argument; portability fixes. (Ralf W. Grosse-Kunstleve) Make ParseConfig() and env.Append() work regardless of initial construction variable values. Make new Dir() support work with empty directories and timestamps. Make the new Queue-based Job implementation portable to Python 1.5.2.
Diffstat (limited to 'src')
-rw-r--r--src/CHANGES.txt8
-rw-r--r--src/engine/SCons/Environment.py38
-rw-r--r--src/engine/SCons/EnvironmentTests.py105
-rw-r--r--src/engine/SCons/Executor.py2
-rw-r--r--src/engine/SCons/ExecutorTests.py2
-rw-r--r--src/engine/SCons/Job.py10
-rw-r--r--src/engine/SCons/JobTests.py4
-rw-r--r--src/engine/SCons/Node/FS.py4
-rw-r--r--src/engine/SCons/Node/FSTests.py21
-rw-r--r--src/engine/SCons/Sig/SigTests.py36
-rw-r--r--src/engine/SCons/Sig/__init__.py8
11 files changed, 177 insertions, 61 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 1ab7499..6e81a3e 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -56,6 +56,9 @@ RELEASE X.XX - XXX
- Accomodate anydbm modules that don't have a sync() method.
+ - Allow SConsignFile() to take an argument specifying the DBM
+ module to be used.
+
From Stephen Kennedy:
- Add support for a configurable global .sconsign.dbm file which
@@ -118,6 +121,11 @@ RELEASE X.XX - XXX
- Remove the long-obsolete {Get,Set}CommandHandler() functions.
+ - Enhance env.Append() to suppress null values when appropriate.
+
+ - Fix ParseConfig() so it works regardless of initial construction
+ variable values.
+
From Clark McGrew:
- Generalize the action for .tex files so that it will decide whether
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index f8ff6c3..e320f05 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -427,10 +427,14 @@ class Base:
self._dict[key] = kw[key]
elif SCons.Util.is_List(self._dict[key]) and not \
SCons.Util.is_List(kw[key]):
- self._dict[key] = self._dict[key] + [ kw[key] ]
+ if not kw[key] is None and kw[key] != '':
+ self._dict[key] = self._dict[key] + [ kw[key] ]
elif SCons.Util.is_List(kw[key]) and not \
SCons.Util.is_List(self._dict[key]):
- self._dict[key] = [ self._dict[key] ] + kw[key]
+ if self._dict[key] is None or self._dict[key] == '':
+ self._dict[key] = kw[key]
+ else:
+ self._dict[key] = [ self._dict[key] ] + kw[key]
elif SCons.Util.is_Dict(self._dict[key]) and \
SCons.Util.is_Dict(kw[key]):
self._dict[key].update(kw[key])
@@ -549,34 +553,30 @@ class Base:
# the default parse function
def parse_conf(env, output):
- env_dict = env.Dictionary()
+ dict = {
+ 'CPPPATH' : [],
+ 'LIBPATH' : [],
+ 'LIBS' : [],
+ 'CCFLAGS' : [],
+ }
static_libs = []
- # setup all the dictionary options
- if not env_dict.has_key('CPPPATH'):
- env_dict['CPPPATH'] = []
- if not env_dict.has_key('LIBPATH'):
- env_dict['LIBPATH'] = []
- if not env_dict.has_key('LIBS'):
- env_dict['LIBS'] = []
- if not env_dict.has_key('CCFLAGS') or env_dict['CCFLAGS'] == "":
- env_dict['CCFLAGS'] = []
-
params = string.split(output)
for arg in params:
switch = arg[0:1]
opt = arg[1:2]
if switch == '-':
if opt == 'L':
- env_dict['LIBPATH'].append(arg[2:])
+ dict['LIBPATH'].append(arg[2:])
elif opt == 'l':
- env_dict['LIBS'].append(arg[2:])
+ dict['LIBS'].append(arg[2:])
elif opt == 'I':
- env_dict['CPPPATH'].append(arg[2:])
+ dict['CPPPATH'].append(arg[2:])
else:
- env_dict['CCFLAGS'].append(arg)
+ dict['CCFLAGS'].append(arg)
else:
static_libs.append(arg)
+ apply(env.Append, (), dict)
return static_libs
if function is None:
@@ -940,11 +940,11 @@ class Base:
nkw = self.subst_kw(kw)
return apply(SCons.Scanner.Base, nargs, nkw)
- def SConsignFile(self, name=".sconsign.dbm"):
+ def SConsignFile(self, name=".sconsign.dbm", dbm_module=None):
name = self.subst(name)
if not os.path.isabs(name):
name = os.path.join(str(self.fs.SConstruct_dir), name)
- SCons.Sig.SConsignFile(name)
+ SCons.Sig.SConsignFile(name, dbm_module)
def SideEffect(self, side_effect, target):
"""Tell scons that side_effects are built as side
diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py
index 49d6ac7..2ad0a32 100644
--- a/src/engine/SCons/EnvironmentTests.py
+++ b/src/engine/SCons/EnvironmentTests.py
@@ -724,20 +724,58 @@ class EnvironmentTestCase(unittest.TestCase):
import UserList
UL = UserList.UserList
- env1 = Environment(AAA = 'a', BBB = 'b', CCC = 'c', DDD = 'd',
- EEE = ['e'], FFF = ['f'], GGG = ['g'], HHH = ['h'],
- III = UL(['i']), JJJ = UL(['j']),
- KKK = UL(['k']), LLL = UL(['l']))
- env1.Append(BBB = 'B', CCC = ['C'], DDD = UL(['D']),
- FFF = 'F', GGG = ['G'], HHH = UL(['H']),
- JJJ = 'J', KKK = ['K'], LLL = UL(['L']))
- env2 = Environment(AAA = 'a', BBB = 'bB',
- CCC = ['c', 'C'], DDD = UL(['d', 'D']),
- EEE = ['e'], FFF = ['f', 'F'],
- GGG = ['g', 'G'], HHH = UL(['h', 'H']),
- III = UL(['i']), JJJ = UL(['j', 'J']),
- KKK = UL(['k', 'K']), LLL = UL(['l', 'L']))
- assert env1 == env2, diff_env(env1, env2)
+ env1 = Environment(AAA = 'a',
+ AAA1 = 'a1', AAA2 = 'a2', AAA3 = 'a3',
+ EEE = ['e'],
+ EEE1 = ['e1'], EEE2 = ['e2'], EEE3 = ['e3'],
+ III = UL(['i']),
+ III1 = UL(['i1']), III2 = UL(['i2']), III3 = UL(['i3']),
+ MMM = '',
+ MMM1 = '', MMM2 = '', MMM3 = '',
+ NNN = [],
+ NNN1 = [], NNN2 = [], NNN3 = [],
+ OOO = UL([]),
+ OOO1 = UL([]), OOO2 = UL([]), OOO3 = UL([]),
+ PPP = [''],
+ PPP1 = [''], PPP2 = [''], PPP3 = [''],
+ QQQ = UL(['']),
+ QQQ1 = UL(['']), QQQ2 = UL(['']), QQQ3 = UL(['']))
+ env1.Append(AAA1 = 'A1', AAA2 = ['A2'], AAA3 = UL(['A3']),
+ EEE1 = 'E1', EEE2 = ['E2'], EEE3 = UL(['E3']),
+ III1 = 'I1', III2 = ['I2'], III3 = UL(['I3']),
+ MMM1 = 'M1', MMM2 = ['M2'], MMM3 = UL(['M3']),
+ NNN1 = 'N1', NNN2 = ['N2'], NNN3 = UL(['N3']),
+ OOO1 = 'O1', OOO2 = ['O2'], OOO3 = UL(['O3']),
+ PPP1 = 'P1', PPP2 = ['P2'], PPP3 = UL(['P3']),
+ QQQ1 = 'Q1', QQQ2 = ['Q2'], QQQ3 = UL(['Q3']))
+ assert env1['AAA'] == 'a', env1['AAA']
+ assert env1['AAA1'] == 'a1A1', env1['AAA1']
+ assert env1['AAA2'] == ['a2', 'A2'], env1['AAA2']
+ assert env1['AAA3'] == UL(['a3', 'A3']), env1['AAA3']
+ assert env1['EEE'] == ['e'], env1['EEE']
+ assert env1['EEE1'] == ['e1', 'E1'], env1['EEE1']
+ assert env1['EEE2'] == ['e2', 'E2'], env1['EEE2']
+ assert env1['EEE3'] == UL(['e3', 'E3']), env1['EEE3']
+ assert env1['III'] == UL(['i']), env1['III']
+ assert env1['III1'] == UL(['i1', 'I1']), env1['III1']
+ assert env1['III2'] == UL(['i2', 'I2']), env1['III2']
+ assert env1['III3'] == UL(['i3', 'I3']), env1['III3']
+ assert env1['MMM'] == '', env1['MMM']
+ assert env1['MMM1'] == 'M1', env1['MMM1']
+ assert env1['MMM2'] == ['M2'], env1['MMM2']
+ assert env1['MMM3'] == UL(['M3']), env1['MMM3']
+ assert env1['NNN1'] == ['N1'], env1['NNN1']
+ assert env1['NNN2'] == ['N2'], env1['NNN2']
+ assert env1['NNN3'] == UL(['N3']), env1['NNN3']
+ assert env1['OOO1'] == ['O1'], env1['OOO1']
+ assert env1['OOO2'] == ['O2'], env1['OOO2']
+ assert env1['OOO3'] == UL(['O3']), env1['OOO3']
+ assert env1['PPP1'] == ['', 'P1'], env1['PPP1']
+ assert env1['PPP2'] == ['', 'P2'], env1['PPP2']
+ assert env1['PPP3'] == UL(['', 'P3']), env1['PPP3']
+ assert env1['QQQ1'] == UL(['', 'Q1']), env1['QQQ1']
+ assert env1['QQQ2'] == UL(['', 'Q2']), env1['QQQ2']
+ assert env1['QQQ3'] == UL(['', 'Q3']), env1['QQQ3']
env3 = Environment(X = {'x1' : 7})
env3.Append(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10})
@@ -946,7 +984,11 @@ class EnvironmentTestCase(unittest.TestCase):
def test_ParseConfig(self):
"""Test the ParseConfig() method"""
- env = Environment(COMMAND='command')
+ env = Environment(COMMAND='command',
+ CPPPATH='string',
+ LIBPATH=['list'],
+ LIBS='',
+ CCFLAGS=[''])
save_command = []
orig_popen = os.popen
def my_popen(command, save_command=save_command):
@@ -961,10 +1003,10 @@ class EnvironmentTestCase(unittest.TestCase):
libs = env.ParseConfig("fake $COMMAND")
assert save_command == ['fake command'], save_command
assert libs == ['abc'], libs
- assert env['CPPPATH'] == ['/usr/include/fum', 'bar'], env['CPPPATH']
- assert env['LIBPATH'] == ['/usr/fax', 'foo'], env['LIBPATH']
+ assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar'], env['CPPPATH']
+ assert env['LIBPATH'] == ['list', '/usr/fax', 'foo'], env['LIBPATH']
assert env['LIBS'] == ['xxx'], env['LIBS']
- assert env['CCFLAGS'] == ['-X'], env['CCFLAGS']
+ assert env['CCFLAGS'] == ['', '-X'], env['CCFLAGS']
finally:
os.popen = orig_popen
@@ -1723,27 +1765,34 @@ class EnvironmentTestCase(unittest.TestCase):
env.fs = MyFS()
try:
- save = []
- def capture(name, save=save):
- save.append(name)
+ fnames = []
+ dbms = []
+ def capture(name, dbm_module, fnames=fnames, dbms=dbms):
+ fnames.append(name)
+ dbms.append(dbm_module)
save_Sig_SConsignFile = SCons.Sig.SConsignFile
SCons.Sig.SConsignFile = capture
env.SConsignFile('foo')
- assert save[0] == os.path.join(os.sep, 'dir', 'foo'), save
+ assert fnames[0] == os.path.join(os.sep, 'dir', 'foo'), fnames
+ assert dbms[0] == None, dbms
env.SConsignFile('$FOO')
- assert save[1] == os.path.join(os.sep, 'dir', 'SConsign'), save
+ assert fnames[1] == os.path.join(os.sep, 'dir', 'SConsign'), fnames
+ assert dbms[1] == None, dbms
env.SConsignFile('/$FOO')
- assert save[2] == '/SConsign', save
+ assert fnames[2] == '/SConsign', fnames
+ assert dbms[2] == None, dbms
- env.SConsignFile('$BAR')
- assert save[3] == os.path.join(os.sep, 'File'), save
+ env.SConsignFile('$BAR', 'x')
+ assert fnames[3] == os.path.join(os.sep, 'File'), fnames
+ assert dbms[3] == 'x', dbms
- env.SConsignFile('__$BAR')
- assert save[4] == os.path.join(os.sep, 'dir', '__', 'File'), save
+ env.SConsignFile('__$BAR', 7)
+ assert fnames[4] == os.path.join(os.sep, 'dir', '__', 'File'), fnames
+ assert dbms[4] == 7, dbms
finally:
SCons.Sig.SConsignFile = save_Sig_SConsignFile
diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py
index 2b4e634..12dfcc7 100644
--- a/src/engine/SCons/Executor.py
+++ b/src/engine/SCons/Executor.py
@@ -138,4 +138,4 @@ class Executor:
course (only files do), but this is the interface used by the
timestamp module.
"""
- return None
+ return 0
diff --git a/src/engine/SCons/ExecutorTests.py b/src/engine/SCons/ExecutorTests.py
index 6af5794..6ead306 100644
--- a/src/engine/SCons/ExecutorTests.py
+++ b/src/engine/SCons/ExecutorTests.py
@@ -160,7 +160,7 @@ class ExecutorTestCase(unittest.TestCase):
"""Test fetching the "timestamp" """
x = SCons.Executor.Executor('b', 'e', 'o', 't', ['s1', 's2'])
ts = x.get_timestamp()
- assert ts is None, ts
+ assert ts == 0, ts
if __name__ == "__main__":
diff --git a/src/engine/SCons/Job.py b/src/engine/SCons/Job.py
index 0c01b85..b5296dc 100644
--- a/src/engine/SCons/Job.py
+++ b/src/engine/SCons/Job.py
@@ -136,9 +136,9 @@ class Worker(threading.Thread):
try:
task.execute()
except:
- ok = False
+ ok = 0
else:
- ok = True
+ ok = 1
self.resultsQueue.put((task, ok))
@@ -147,8 +147,8 @@ class ThreadPool:
def __init__(self, num):
"""Create the request and reply queues, and 'num' worker threads."""
- self.requestQueue = Queue.Queue()
- self.resultsQueue = Queue.Queue()
+ self.requestQueue = Queue.Queue(0)
+ self.resultsQueue = Queue.Queue(0)
# Create worker threads
for i in range(num):
@@ -165,7 +165,7 @@ class ThreadPool:
def get_nowait(self):
"""Remove and result a result tuple from the results queue
without blocking."""
- return self.get(False)
+ return self.get(0)
class Parallel:
"""This class is used to execute tasks in parallel, and is somewhat
diff --git a/src/engine/SCons/JobTests.py b/src/engine/SCons/JobTests.py
index 2c84028..1b09fd6 100644
--- a/src/engine/SCons/JobTests.py
+++ b/src/engine/SCons/JobTests.py
@@ -172,9 +172,9 @@ class Taskmaster:
def is_blocked(self):
if self.stop or self.all_tasks_are_executed():
- return False
+ return 0
if self.all_tasks_are_iterated():
- return True
+ return 1
# simulate blocking tasks
return self.num_iterated - self.num_executed >= max(num_jobs/2, 2)
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index d93a6a4..b183a88 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -912,7 +912,7 @@ class DummyExecutor:
def get_contents(self):
return ''
def get_timestamp(self):
- return None
+ return 0
class Dir(Base):
"""A class for directories in a file system.
@@ -1148,7 +1148,7 @@ class Dir(Base):
def get_timestamp(self):
"""Return the latest timestamp from among our children"""
- stamp = None
+ stamp = 0
for kid in self.children(None):
if kid.get_timestamp() > stamp:
stamp = kid.get_timestamp()
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index 53e2013..2237959 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -985,6 +985,27 @@ class FSTestCase(unittest.TestCase):
finally:
test.unlink("tstamp")
+ test.subdir('tdir1')
+ d = fs.Dir('tdir1')
+ t = d.get_timestamp()
+ assert t == 0, "expected 0, got %s" % str(t)
+
+ test.subdir('tdir2')
+ d = fs.Dir('tdir2')
+ f1 = test.workpath('tdir2', 'file1')
+ f2 = test.workpath('tdir2', 'file2')
+ test.write(f1, 'file1\n')
+ test.write(f2, 'file2\n')
+ fs.File(f1)
+ fs.File(f2)
+ current_time = float(int(time.time() / 2) * 2)
+ t1 = current_time - 4.0
+ t2 = current_time - 2.0
+ os.utime(f1, (t1 - 2.0, t1))
+ os.utime(f2, (t2 - 2.0, t2))
+ t = d.get_timestamp()
+ assert t == t2, "expected %f, got %f" % (t2, t)
+
#XXX test get_prevsiginfo()
skey = fs.Entry('eee.x').scanner_key()
diff --git a/src/engine/SCons/Sig/SigTests.py b/src/engine/SCons/Sig/SigTests.py
index c82d2c5..f297464 100644
--- a/src/engine/SCons/Sig/SigTests.py
+++ b/src/engine/SCons/Sig/SigTests.py
@@ -490,6 +490,41 @@ class SConsignDirFileTestCase(unittest.TestCase):
assert f.get('foo') == (3, 1, 2)
assert f.get_implicit('foo') == ['bar']
+class SConsignFileTestCase(unittest.TestCase):
+
+ def runTest(self):
+ test = TestCmd.TestCmd(workdir = '')
+ file = test.workpath('sconsign_file')
+
+ assert SCons.Sig.SConsign_db is None, SCons.Sig.SConsign_db
+
+ SCons.Sig.SConsignFile(file)
+
+ assert not SCons.Sig.SConsign_db is None, SCons.Sig.SConsign_db
+
+ class Fake_DBM:
+ def open(self, name, mode):
+ self.name = name
+ self.mode = mode
+ return self
+
+ fake_dbm = Fake_DBM()
+
+ SCons.Sig.SConsignFile(file, fake_dbm)
+
+ assert not SCons.Sig.SConsign_db is None, SCons.Sig.SConsign_db
+ assert not hasattr(fake_dbm, 'name'), fake_dbm
+ assert not hasattr(fake_dbm, 'mode'), fake_dbm
+
+ SCons.Sig.SConsign_db = None
+
+ SCons.Sig.SConsignFile(file, fake_dbm)
+
+ assert not SCons.Sig.SConsign_db is None, SCons.Sig.SConsign_db
+ assert fake_dbm.name == file, fake_dbm.name
+ assert fake_dbm.mode == "c", fake_dbm.mode
+
+
def suite():
suite = unittest.TestSuite()
@@ -500,6 +535,7 @@ def suite():
suite.addTest(_SConsignTestCase())
suite.addTest(SConsignDBTestCase())
suite.addTest(SConsignDirFileTestCase())
+ suite.addTest(SConsignFileTestCase())
return suite
if __name__ == "__main__":
diff --git a/src/engine/SCons/Sig/__init__.py b/src/engine/SCons/Sig/__init__.py
index 4898f29..dfddf34 100644
--- a/src/engine/SCons/Sig/__init__.py
+++ b/src/engine/SCons/Sig/__init__.py
@@ -301,15 +301,17 @@ class SConsignDirFile(SConsignDir):
SConsignForDirectory = SConsignDirFile
-def SConsignFile(name):
+def SConsignFile(name, dbm_module=None):
"""
Arrange for all signatures to be stored in a global .sconsign.dbm
file.
"""
global SConsign_db
if SConsign_db is None:
- import anydbm
- SConsign_db = anydbm.open(name, "c")
+ if dbm_module is None:
+ import anydbm
+ dbm_module = anydbm
+ SConsign_db = dbm_module.open(name, "c")
global SConsignForDirectory
SConsignForDirectory = SConsignDB