diff options
author | Steven Knight <knight@baldmt.com> | 2004-04-25 19:47:31 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2004-04-25 19:47:31 (GMT) |
commit | ae9f03ddef2d4a346bd49e10e8b033ddbf7b852a (patch) | |
tree | 8d8a4602fe35bf6d30f890c083280157cd8487da /src/engine | |
parent | bd74d2939db1d55119af3faf56a89f07722d487a (diff) | |
download | SCons-ae9f03ddef2d4a346bd49e10e8b033ddbf7b852a.zip SCons-ae9f03ddef2d4a346bd49e10e8b033ddbf7b852a.tar.gz SCons-ae9f03ddef2d4a346bd49e10e8b033ddbf7b852a.tar.bz2 |
Have SConsignFile() use a dblite.py module by default, so we can control the behavior. (Ralf W. Grosse-Kunstleve)
Diffstat (limited to 'src/engine')
-rw-r--r-- | src/engine/MANIFEST.in | 1 | ||||
-rw-r--r-- | src/engine/SCons/Environment.py | 2 | ||||
-rw-r--r-- | src/engine/SCons/EnvironmentTests.py | 4 | ||||
-rw-r--r-- | src/engine/SCons/Sig/SigTests.py | 2 | ||||
-rw-r--r-- | src/engine/SCons/Sig/__init__.py | 4 | ||||
-rw-r--r-- | src/engine/SCons/dblite.py | 149 |
6 files changed, 158 insertions, 4 deletions
diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in index a8bac0a..4942be8 100644 --- a/src/engine/MANIFEST.in +++ b/src/engine/MANIFEST.in @@ -2,6 +2,7 @@ SCons/__init__.py SCons/Action.py SCons/Builder.py SCons/Conftest.py +SCons/dblite.py SCons/Debug.py SCons/Defaults.py SCons/Environment.py diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index c312f31..d214e9b 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -1153,7 +1153,7 @@ class Base: nkw = self.subst_kw(kw) return apply(SCons.Scanner.Base, nargs, nkw) - def SConsignFile(self, name=".sconsign.dbm", dbm_module=None): + def SConsignFile(self, name=".sconsign", dbm_module=None): name = self.subst(name) if not os.path.isabs(name): name = os.path.join(str(self.fs.SConstruct_dir), name) diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 0995a05..d141d49 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -2245,6 +2245,10 @@ class EnvironmentTestCase(unittest.TestCase): env.SConsignFile('__$BAR', 7) assert fnames[4] == os.path.join(os.sep, 'dir', '__', 'File'), fnames assert dbms[4] == 7, dbms + + env.SConsignFile() + assert fnames[5] == os.path.join(os.sep, 'dir', '.sconsign'), fnames + assert dbms[5] == None, dbms finally: SCons.Sig.SConsignFile = save_Sig_SConsignFile diff --git a/src/engine/SCons/Sig/SigTests.py b/src/engine/SCons/Sig/SigTests.py index 98465ff..76cd931 100644 --- a/src/engine/SCons/Sig/SigTests.py +++ b/src/engine/SCons/Sig/SigTests.py @@ -502,7 +502,7 @@ class SConsignFileTestCase(unittest.TestCase): SCons.Sig.SConsignFile(file) - assert not SCons.Sig.SConsign_db is None, SCons.Sig.SConsign_db + assert not SCons.Sig.SConsign_db is SCons.dblite, SCons.Sig.SConsign_db class Fake_DBM: def open(self, name, mode): diff --git a/src/engine/SCons/Sig/__init__.py b/src/engine/SCons/Sig/__init__.py index d703194..6bdfe09 100644 --- a/src/engine/SCons/Sig/__init__.py +++ b/src/engine/SCons/Sig/__init__.py @@ -326,8 +326,8 @@ def SConsignFile(name, dbm_module=None): global SConsign_db if SConsign_db is None: if dbm_module is None: - import anydbm - dbm_module = anydbm + import SCons.dblite + dbm_module = SCons.dblite SConsign_db = dbm_module.open(name, "c") global SConsignForDirectory diff --git a/src/engine/SCons/dblite.py b/src/engine/SCons/dblite.py new file mode 100644 index 0000000..df04d80 --- /dev/null +++ b/src/engine/SCons/dblite.py @@ -0,0 +1,149 @@ +# dblite.py module contributed by Ralf W. Grosse-Kunstleve. + +import cPickle +import time +import shutil +import os +import __builtin__ + +_open = __builtin__.open # avoid name clash + +keep_all_files = 00000 +ignore_corrupt_dbfiles = 0 + +class dblite: + + def __init__(self, file_base_name, flag, mode): + assert flag in (None, "r", "w", "c", "n") + if (flag is None): flag = "r" + if file_base_name[-7:] != '.dblite': + file_base_name = file_base_name + '.dblite' + self._file_name = file_base_name + self._flag = flag + self._mode = mode + self._dict = {} + self._needs_sync = 00000 + if (self._flag == "n"): + _open(self._file_name, "wb", self._mode) + else: + try: + f = _open(self._file_name, "rb") + except IOError, e: + if (self._flag != "c"): + raise e + _open(self._file_name, "wb", self._mode) + else: + p = f.read() + if (len(p) > 0): + try: + self._dict = cPickle.loads(p) + except: + if (ignore_corrupt_dbfiles == 0): raise + if (ignore_corrupt_dbfiles == 1): + print "Warning: Discarding corrupt database:", self._file_name + + def __del__(self): + if (self._needs_sync): + self.sync() + + def sync(self): + self._check_writable() + f = _open(self._file_name, "wb", self._mode) + cPickle.dump(self._dict, f, 1) + f.close() + self._needs_sync = 00000 + if (keep_all_files): + shutil.copyfile( + self._file_name, + self._file_name + "_" + str(int(time.time()))) + + def _check_writable(self): + if (self._flag == "r"): + raise IOError("Read-only database: %s" % self._file_name) + + def __getitem__(self, key): + return self._dict[key] + + def __setitem__(self, key, value): + self._check_writable() + if (type(key) != type("")): + raise TypeError, "key must be a string" + if (type(value) != type("")): + raise TypeError, "value must be a string" + self._dict[key] = value + self._needs_sync = 0001 + + def keys(self): + return self._dict.keys() + + def has_key(self, key): + return key in self._dict + + def __contains__(self, key): + return key in self._dict + + def iterkeys(self): + return self._dict.iterkeys() + + __iter__ = iterkeys + + def __len__(self): + return len(self._dict) + +def open(file, flag=None, mode=0666): + return dblite(file, flag, mode) + +def _exercise(): + db = open("tmp", "n") + assert len(db) == 0 + db["foo"] = "bar" + assert db["foo"] == "bar" + db.sync() + db = open("tmp", "c") + assert len(db) == 1 + assert db["foo"] == "bar" + db["bar"] = "foo" + assert db["bar"] == "foo" + db.sync() + db = open("tmp", "r") + assert len(db) == 2 + assert db["foo"] == "bar" + assert db["bar"] == "foo" + try: + db.sync() + except IOError, e: + assert str(e) == "Read-only database: tmp.dblite" + else: + raise RuntimeError, "IOError expected." + db = open("tmp", "w") + assert len(db) == 2 + db["ping"] = "pong" + db.sync() + db = open("tmp", "r") + assert len(db) == 3 + db = open("tmp", "n") + assert len(db) == 0 + _open("tmp.dblite", "w") + db = open("tmp", "r") + _open("tmp.dblite", "w").write("x") + try: + db = open("tmp", "r") + except cPickle.UnpicklingError: + pass + else: + raise RuntimeError, "cPickle exception expected." + global ignore_corrupt_dbfiles + ignore_corrupt_dbfiles = 2 + db = open("tmp", "r") + assert len(db) == 0 + os.unlink("tmp.dblite") + try: + db = open("tmp", "w") + except IOError, e: + assert str(e) == "Database does not exist: tmp.dblite" + else: + raise RuntimeError, "IOError expected." + print "OK" + +if (__name__ == "__main__"): + _exercise() |