blob: 6b4f96518802b68c8106fec4b3d96d123bacf79a [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001#----------------------------------------------------------------------
2# Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3# and Andrew Kuchling. All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
8#
9# o Redistributions of source code must retain the above copyright
10# notice, this list of conditions, and the disclaimer that follows.
11#
12# o Redistributions in binary form must reproduce the above copyright
13# notice, this list of conditions, and the following disclaimer in
14# the documentation and/or other materials provided with the
15# distribution.
16#
17# o Neither the name of Digital Creations nor the names of its
18# contributors may be used to endorse or promote products derived
19# from this software without specific prior written permission.
20#
21# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22# IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32# DAMAGE.
33#----------------------------------------------------------------------
34
35
Barry Warsaw9a0d7792002-12-30 20:53:52 +000036"""Support for BerkeleyDB 3.1 through 4.1.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000037"""
38
Martin v. Löwis65730a42002-11-24 08:26:01 +000039try:
40 import _bsddb
41except ImportError:
42 # Remove ourselves from sys.modules
43 import sys
44 del sys.modules[__name__]
45 raise
Tim Peters0eadaac2003-04-24 16:02:54 +000046
Barry Warsawf71de3e2003-01-28 17:20:44 +000047# bsddb3 calls it db, but provide _db for backwards compatibility
48db = _db = _bsddb
49__version__ = db.__version__
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000050
Barry Warsawf71de3e2003-01-28 17:20:44 +000051error = db.DBError # So bsddb.error will mean something...
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000052
53#----------------------------------------------------------------------
54
Gregory P. Smithcec1b3f2003-09-20 23:51:34 +000055import sys
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000056
Gregory P. Smithcec1b3f2003-09-20 23:51:34 +000057# for backwards compatibility with python versions older than 2.3, the
58# iterator interface is dynamically defined and added using a mixin
59# class. old python can't tokenize it due to the yield keyword.
60if sys.version >= '2.3':
61 exec """
62import UserDict
63class _iter_mixin(UserDict.DictMixin):
64 def __iter__(self):
65 try:
66 yield self.first()[0]
67 next = self.next
68 while 1:
69 yield next()[0]
70 except _bsddb.DBNotFoundError:
71 return
72
73 def iteritems(self):
74 try:
75 yield self.first()
76 next = self.next
77 while 1:
78 yield next()
79 except _bsddb.DBNotFoundError:
80 return
81"""
82else:
83 class _iter_mixin: pass
84
85
86class _DBWithCursor(_iter_mixin):
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000087 """
88 A simple wrapper around DB that makes it look like the bsddbobject in
89 the old module. It uses a cursor as needed to provide DB traversal.
90 """
91 def __init__(self, db):
92 self.db = db
93 self.dbc = None
94 self.db.set_get_returns_none(0)
95
96 def __del__(self):
97 self.close()
98
99 def _checkCursor(self):
100 if self.dbc is None:
101 self.dbc = self.db.cursor()
102
103 def _checkOpen(self):
104 if self.db is None:
105 raise error, "BSDDB object has already been closed"
106
107 def isOpen(self):
108 return self.db is not None
109
110 def __len__(self):
111 self._checkOpen()
112 return len(self.db)
113
114 def __getitem__(self, key):
115 self._checkOpen()
116 return self.db[key]
117
118 def __setitem__(self, key, value):
119 self._checkOpen()
120 self.db[key] = value
121
122 def __delitem__(self, key):
123 self._checkOpen()
124 del self.db[key]
125
126 def close(self):
127 if self.dbc is not None:
128 self.dbc.close()
129 v = 0
130 if self.db is not None:
131 v = self.db.close()
132 self.dbc = None
133 self.db = None
134 return v
135
136 def keys(self):
137 self._checkOpen()
138 return self.db.keys()
139
140 def has_key(self, key):
141 self._checkOpen()
142 return self.db.has_key(key)
143
144 def set_location(self, key):
145 self._checkOpen()
146 self._checkCursor()
147 return self.dbc.set(key)
148
149 def next(self):
150 self._checkOpen()
151 self._checkCursor()
152 rv = self.dbc.next()
153 return rv
154
155 def previous(self):
156 self._checkOpen()
157 self._checkCursor()
158 rv = self.dbc.prev()
159 return rv
160
161 def first(self):
162 self._checkOpen()
163 self._checkCursor()
164 rv = self.dbc.first()
165 return rv
166
167 def last(self):
168 self._checkOpen()
169 self._checkCursor()
170 rv = self.dbc.last()
171 return rv
172
173 def sync(self):
174 self._checkOpen()
175 return self.db.sync()
176
Raymond Hettinger2e9da602003-09-13 03:18:34 +0000177
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000178#----------------------------------------------------------------------
179# Compatibility object factory functions
180
181def hashopen(file, flag='c', mode=0666, pgsize=None, ffactor=None, nelem=None,
182 cachesize=None, lorder=None, hflags=0):
183
184 flags = _checkflag(flag)
Barry Warsawf71de3e2003-01-28 17:20:44 +0000185 d = db.DB()
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000186 d.set_flags(hflags)
187 if cachesize is not None: d.set_cachesize(0, cachesize)
188 if pgsize is not None: d.set_pagesize(pgsize)
189 if lorder is not None: d.set_lorder(lorder)
190 if ffactor is not None: d.set_h_ffactor(ffactor)
191 if nelem is not None: d.set_h_nelem(nelem)
Barry Warsawf71de3e2003-01-28 17:20:44 +0000192 d.open(file, db.DB_HASH, flags, mode)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000193 return _DBWithCursor(d)
194
195#----------------------------------------------------------------------
196
197def btopen(file, flag='c', mode=0666,
198 btflags=0, cachesize=None, maxkeypage=None, minkeypage=None,
199 pgsize=None, lorder=None):
200
201 flags = _checkflag(flag)
Barry Warsawf71de3e2003-01-28 17:20:44 +0000202 d = db.DB()
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000203 if cachesize is not None: d.set_cachesize(0, cachesize)
204 if pgsize is not None: d.set_pagesize(pgsize)
205 if lorder is not None: d.set_lorder(lorder)
206 d.set_flags(btflags)
207 if minkeypage is not None: d.set_bt_minkey(minkeypage)
208 if maxkeypage is not None: d.set_bt_maxkey(maxkeypage)
Barry Warsawf71de3e2003-01-28 17:20:44 +0000209 d.open(file, db.DB_BTREE, flags, mode)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000210 return _DBWithCursor(d)
211
212#----------------------------------------------------------------------
213
214
215def rnopen(file, flag='c', mode=0666,
216 rnflags=0, cachesize=None, pgsize=None, lorder=None,
217 rlen=None, delim=None, source=None, pad=None):
218
219 flags = _checkflag(flag)
Barry Warsawf71de3e2003-01-28 17:20:44 +0000220 d = db.DB()
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000221 if cachesize is not None: d.set_cachesize(0, cachesize)
222 if pgsize is not None: d.set_pagesize(pgsize)
223 if lorder is not None: d.set_lorder(lorder)
224 d.set_flags(rnflags)
225 if delim is not None: d.set_re_delim(delim)
226 if rlen is not None: d.set_re_len(rlen)
227 if source is not None: d.set_re_source(source)
228 if pad is not None: d.set_re_pad(pad)
Barry Warsawf71de3e2003-01-28 17:20:44 +0000229 d.open(file, db.DB_RECNO, flags, mode)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000230 return _DBWithCursor(d)
231
232#----------------------------------------------------------------------
233
234
235def _checkflag(flag):
236 if flag == 'r':
Barry Warsawf71de3e2003-01-28 17:20:44 +0000237 flags = db.DB_RDONLY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000238 elif flag == 'rw':
239 flags = 0
240 elif flag == 'w':
Barry Warsawf71de3e2003-01-28 17:20:44 +0000241 flags = db.DB_CREATE
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000242 elif flag == 'c':
Barry Warsawf71de3e2003-01-28 17:20:44 +0000243 flags = db.DB_CREATE
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000244 elif flag == 'n':
Barry Warsawf71de3e2003-01-28 17:20:44 +0000245 flags = db.DB_CREATE | db.DB_TRUNCATE
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000246 else:
247 raise error, "flags should be one of 'r', 'w', 'c' or 'n'"
Barry Warsawf71de3e2003-01-28 17:20:44 +0000248 return flags | db.DB_THREAD
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000249
250#----------------------------------------------------------------------
251
252
253# This is a silly little hack that allows apps to continue to use the
254# DB_THREAD flag even on systems without threads without freaking out
255# BerkeleyDB.
256#
257# This assumes that if Python was built with thread support then
258# BerkeleyDB was too.
259
260try:
261 import thread
262 del thread
263except ImportError:
Barry Warsawf71de3e2003-01-28 17:20:44 +0000264 db.DB_THREAD = 0
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000265
266
267#----------------------------------------------------------------------