Remove some unused variable definitions.
[cvs2svn.git] / cvs2svn_lib / database.py
blob07493e5f279970db4a4cd8f123ac7eb531691622
1 # (Be in -*- python -*- mode.)
3 # ====================================================================
4 # Copyright (c) 2000-2009 CollabNet. All rights reserved.
6 # This software is licensed as described in the file COPYING, which
7 # you should have received as part of this distribution. The terms
8 # are also available at http://subversion.tigris.org/license-1.html.
9 # If newer versions of this license are posted there, you may use a
10 # newer version instead, at your option.
12 # This software consists of voluntary contributions made by many
13 # individuals. For exact contribution history, see the revision
14 # history and logs, available at http://cvs2svn.tigris.org/.
15 # ====================================================================
17 """This module contains database facilities used by cvs2svn."""
20 import sys
21 import os
22 import cPickle
24 from cvs2svn_lib.common import DB_OPEN_NEW
25 from cvs2svn_lib.common import warning_prefix
26 from cvs2svn_lib.common import error_prefix
27 from cvs2svn_lib.log import logger
30 # DBM module selection
32 # 1. If we have bsddb3, it is probably newer than bsddb. Fake bsddb = bsddb3,
33 # so that the dbhash module used by anydbm will use bsddb3.
34 try:
35 import bsddb3
36 sys.modules['bsddb'] = bsddb3
37 except ImportError:
38 pass
40 # 2. These DBM modules are not good for cvs2svn.
41 import anydbm
42 if anydbm._defaultmod.__name__ in ['dumbdbm', 'dbm']:
43 logger.error(
44 '%s: cvs2svn uses the anydbm package, which depends on lower level '
45 'dbm\n'
46 'libraries. Your system has %s, with which cvs2svn is known to have\n'
47 'problems. To use cvs2svn, you must install a Python dbm library '
48 'other than\n'
49 'dumbdbm or dbm. See '
50 'http://python.org/doc/current/lib/module-anydbm.html\n'
51 'for more information.\n'
52 % (error_prefix, anydbm._defaultmod.__name__,)
54 sys.exit(1)
56 # 3. If we are using the old bsddb185 module, then try prefer gdbm instead.
57 # Unfortunately, gdbm appears not to be trouble free, either.
58 if hasattr(anydbm._defaultmod, 'bsddb') \
59 and not hasattr(anydbm._defaultmod.bsddb, '__version__'):
60 try:
61 gdbm = __import__('gdbm')
62 except ImportError:
63 logger.warn(
64 '%s: The version of the bsddb module found on your computer '
65 'has been\n'
66 'reported to malfunction on some datasets, causing KeyError '
67 'exceptions.\n'
68 % (warning_prefix,)
70 else:
71 anydbm._defaultmod = gdbm
74 class Database:
75 """A database that uses a Serializer to store objects of a certain type.
77 The serializer is stored in the database under the key
78 self.serializer_key. (This implies that self.serializer_key may not
79 be used as a key for normal entries.)
81 The backing database is an anydbm-based DBM.
83 """
85 serializer_key = '_.%$1\t;_ '
87 def __init__(self, filename, mode, serializer=None):
88 """Constructor.
90 The database stores its Serializer, so none needs to be supplied
91 when opening an existing database."""
93 # pybsddb3 has a bug which prevents it from working with
94 # Berkeley DB 4.2 if you open the db with 'n' ("new"). This
95 # causes the DB_TRUNCATE flag to be passed, which is disallowed
96 # for databases protected by lock and transaction support
97 # (bsddb databases use locking from bsddb version 4.2.4 onwards).
99 # Therefore, manually perform the removal (we can do this, because
100 # we know that for bsddb - but *not* anydbm in general - the database
101 # consists of one file with the name we specify, rather than several
102 # based on that name).
103 if mode == DB_OPEN_NEW and anydbm._defaultmod.__name__ == 'dbhash':
104 if os.path.isfile(filename):
105 os.unlink(filename)
106 self.db = anydbm.open(filename, 'c')
107 else:
108 self.db = anydbm.open(filename, mode)
110 # Import implementations for many mapping interface methods.
111 for meth_name in ('__delitem__',
112 '__iter__', 'has_key', '__contains__', 'iterkeys', 'clear'):
113 meth_ref = getattr(self.db, meth_name, None)
114 if meth_ref:
115 setattr(self, meth_name, meth_ref)
117 if mode == DB_OPEN_NEW:
118 self.serializer = serializer
119 self.db[self.serializer_key] = cPickle.dumps(self.serializer)
120 else:
121 self.serializer = cPickle.loads(self.db[self.serializer_key])
123 def __getitem__(self, key):
124 return self.serializer.loads(self.db[key])
126 def __setitem__(self, key, value):
127 self.db[key] = self.serializer.dumps(value)
129 def __delitem__(self, key):
130 # gdbm defines a __delitem__ method, but it cannot be assigned. So
131 # this method provides a fallback definition via explicit delegation:
132 del self.db[key]
134 def keys(self):
135 retval = self.db.keys()
136 retval.remove(self.serializer_key)
137 return retval
139 def __iter__(self):
140 for key in self.keys():
141 yield key
143 def has_key(self, key):
144 try:
145 self.db[key]
146 return True
147 except KeyError:
148 return False
150 def __contains__(self, key):
151 return self.has_key(key)
153 def iterkeys(self):
154 return self.__iter__()
156 def clear(self):
157 for key in self.keys():
158 del self[key]
160 def items(self):
161 return [(key, self[key],) for key in self.keys()]
163 def values(self):
164 return [self[key] for key in self.keys()]
166 def get(self, key, default=None):
167 try:
168 return self[key]
169 except KeyError:
170 return default
172 def close(self):
173 self.db.close()
174 self.db = None