ยปCore Development>Code coverage>Lib/bsddb/__init__.py

Python code coverage for Lib/bsddb/__init__.py

#countcontent
1n/a#----------------------------------------------------------------------
2n/a# Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3n/a# and Andrew Kuchling. All rights reserved.
4n/a#
5n/a# Redistribution and use in source and binary forms, with or without
6n/a# modification, are permitted provided that the following conditions are
7n/a# met:
8n/a#
9n/a# o Redistributions of source code must retain the above copyright
10n/a# notice, this list of conditions, and the disclaimer that follows.
11n/a#
12n/a# o Redistributions in binary form must reproduce the above copyright
13n/a# notice, this list of conditions, and the following disclaimer in
14n/a# the documentation and/or other materials provided with the
15n/a# distribution.
16n/a#
17n/a# o Neither the name of Digital Creations nor the names of its
18n/a# contributors may be used to endorse or promote products derived
19n/a# from this software without specific prior written permission.
20n/a#
21n/a# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22n/a# IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23n/a# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24n/a# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25n/a# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26n/a# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27n/a# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28n/a# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29n/a# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30n/a# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31n/a# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32n/a# DAMAGE.
33n/a#----------------------------------------------------------------------
34n/a
35n/a
36n/a"""Support for Berkeley DB 4.1 through 4.8 with a simple interface.
37n/a
38n/aFor the full featured object oriented interface use the bsddb.db module
39n/ainstead. It mirrors the Oracle Berkeley DB C API.
401"""
41n/a
421import sys
431absolute_import = (sys.version_info[0] >= 3)
44n/a
451if (sys.version_info >= (2, 6)) and (sys.version_info < (3, 0)) :
461 import warnings
471 if sys.py3kwarning and (__name__ != 'bsddb3') :
480 warnings.warnpy3k("in 3.x, the bsddb module has been removed; "
49n/a "please use the pybsddb project instead",
500 DeprecationWarning, 2)
511 warnings.filterwarnings("ignore", ".*CObject.*", DeprecationWarning,
521 "bsddb.__init__")
53n/a
541try:
551 if __name__ == 'bsddb3':
56n/a # import _pybsddb binary as it should be the more recent version from
57n/a # a standalone pybsddb addon package than the version included with
58n/a # python as bsddb._bsddb.
590 if absolute_import :
60n/a # Because this syntaxis is not valid before Python 2.5
610 exec("from . import _pybsddb")
62n/a else :
630 import _pybsddb
640 _bsddb = _pybsddb
650 from bsddb3.dbutils import DeadlockWrap as _DeadlockWrap
66n/a else:
671 import _bsddb
681 from bsddb.dbutils import DeadlockWrap as _DeadlockWrap
690except ImportError:
70n/a # Remove ourselves from sys.modules
710 import sys
720 del sys.modules[__name__]
730 raise
74n/a
75n/a# bsddb3 calls it db, but provide _db for backwards compatibility
761db = _db = _bsddb
771__version__ = db.__version__
78n/a
791error = db.DBError # So bsddb.error will mean something...
80n/a
81n/a#----------------------------------------------------------------------
82n/a
831import sys, os
84n/a
851from weakref import ref
86n/a
871if sys.version_info < (2, 6) :
880 import UserDict
890 MutableMapping = UserDict.DictMixin
90n/aelse :
911 import collections
921 MutableMapping = collections.MutableMapping
93n/a
942class _iter_mixin(MutableMapping):
951 def _make_iter_cursor(self):
96283 cur = _DeadlockWrap(self.db.cursor)
97283 key = id(cur)
98283 self._cursor_refs[key] = ref(cur, self._gen_cref_cleaner(key))
99283 return cur
100n/a
1011 def _gen_cref_cleaner(self, key):
102n/a # use generate the function for the weakref callback here
103n/a # to ensure that we do not hold a strict reference to cur
104n/a # in the callback.
105561 return lambda ref: self._cursor_refs.pop(key, None)
106n/a
1071 def __iter__(self):
108153 self._kill_iteration = False
109153 self._in_iter += 1
110153 try:
111153 try:
112153 cur = self._make_iter_cursor()
113n/a
114n/a # FIXME-20031102-greg: race condition. cursor could
115n/a # be closed by another thread before this call.
116n/a
117n/a # since we're only returning keys, we call the cursor
118n/a # methods with flags=0, dlen=0, dofs=0
119153 key = _DeadlockWrap(cur.first, 0,0,0)[0]
120138 yield key
121n/a
122103 next = getattr(cur, "next")
123103 while 1:
124648 try:
125648 key = _DeadlockWrap(next, 0,0,0)[0]
126485 yield key
127163 except _bsddb.DBCursorClosedError:
12865 if self._kill_iteration:
1295 raise RuntimeError('Database changed size '
130n/a 'during iteration.')
13160 cur = self._make_iter_cursor()
132n/a # FIXME-20031101-greg: race condition. cursor could
133n/a # be closed by another thread before this call.
13460 _DeadlockWrap(cur.set, key,0,0,0)
13560 next = getattr(cur, "next")
136153 except _bsddb.DBNotFoundError:
137113 pass
13840 except _bsddb.DBCursorClosedError:
139n/a # the database was modified during iteration. abort.
1400 pass
141n/a# When Python 2.3 not supported in bsddb3, we can change this to "finally"
14240 except :
14340 self._in_iter -= 1
14440 raise
145n/a
146113 self._in_iter -= 1
147n/a
1481 def iteritems(self):
14935 if not self.db:
1500 return
15135 self._kill_iteration = False
15235 self._in_iter += 1
15335 try:
15435 try:
15535 cur = self._make_iter_cursor()
156n/a
157n/a # FIXME-20031102-greg: race condition. cursor could
158n/a # be closed by another thread before this call.
159n/a
16035 kv = _DeadlockWrap(cur.first)
16135 key = kv[0]
16235 yield kv
163n/a
16430 next = getattr(cur, "next")
16530 while 1:
166190 try:
167190 kv = _DeadlockWrap(next)
168125 key = kv[0]
169125 yield kv
17065 except _bsddb.DBCursorClosedError:
17140 if self._kill_iteration:
1725 raise RuntimeError('Database changed size '
173n/a 'during iteration.')
17435 cur = self._make_iter_cursor()
175n/a # FIXME-20031101-greg: race condition. cursor could
176n/a # be closed by another thread before this call.
17735 _DeadlockWrap(cur.set, key,0,0,0)
17835 next = getattr(cur, "next")
17930 except _bsddb.DBNotFoundError:
18025 pass
1815 except _bsddb.DBCursorClosedError:
182n/a # the database was modified during iteration. abort.
1830 pass
184n/a# When Python 2.3 not supported in bsddb3, we can change this to "finally"
1855 except :
1865 self._in_iter -= 1
1875 raise
188n/a
18925 self._in_iter -= 1
190n/a
191n/a
1922class _DBWithCursor(_iter_mixin):
193n/a """
194n/a A simple wrapper around DB that makes it look like the bsddbobject in
195n/a the old module. It uses a cursor as needed to provide DB traversal.
1961 """
1971 def __init__(self, db):
198217 self.db = db
199217 self.db.set_get_returns_none(0)
200n/a
201n/a # FIXME-20031101-greg: I believe there is still the potential
202n/a # for deadlocks in a multithreaded environment if someone
203n/a # attempts to use the any of the cursor interfaces in one
204n/a # thread while doing a put or delete in another thread. The
205n/a # reason is that _checkCursor and _closeCursors are not atomic
206n/a # operations. Doing our own locking around self.dbc,
207n/a # self.saved_dbc_key and self._cursor_refs could prevent this.
208n/a # TODO: A test case demonstrating the problem needs to be written.
209n/a
210n/a # self.dbc is a DBCursor object used to implement the
211n/a # first/next/previous/last/set_location methods.
212217 self.dbc = None
213217 self.saved_dbc_key = None
214n/a
215n/a # a collection of all DBCursor objects currently allocated
216n/a # by the _iter_mixin interface.
217217 self._cursor_refs = {}
218217 self._in_iter = 0
219217 self._kill_iteration = False
220n/a
2211 def __del__(self):
222216 self.close()
223n/a
2241 def _checkCursor(self):
225152 if self.dbc is None:
22688 self.dbc = _DeadlockWrap(self.db.cursor)
22788 if self.saved_dbc_key is not None:
2280 _DeadlockWrap(self.dbc.set, self.saved_dbc_key)
2290 self.saved_dbc_key = None
230n/a
231n/a # This method is needed for all non-cursor DB calls to avoid
232n/a # Berkeley DB deadlocks (due to being opened with DB_INIT_LOCK
233n/a # and DB_THREAD to be thread safe) when intermixing database
234n/a # operations that use the cursor internally with those that don't.
2351 def _closeCursors(self, save=1):
2361534 if self.dbc:
23788 c = self.dbc
23888 self.dbc = None
23988 if save:
24070 try:
24170 self.saved_dbc_key = _DeadlockWrap(c.current, 0,0,0)[0]
2420 except db.DBError:
2430 pass
24488 _DeadlockWrap(c.close)
24588 del c
2461639 for cref in self._cursor_refs.values():
247105 c = cref()
248105 if c is not None:
249105 _DeadlockWrap(c.close)
250n/a
2511 def _checkOpen(self):
2522521 if self.db is None:
2530 raise error, "BSDDB object has already been closed"
254n/a
2551 def isOpen(self):
2560 return self.db is not None
257n/a
2581 def __len__(self):
25967 self._checkOpen()
260134 return _DeadlockWrap(lambda: len(self.db)) # len(self.db)
261n/a
2621 if sys.version_info >= (2, 6) :
2631 def __repr__(self) :
2640 if self.isOpen() :
2650 return repr(dict(_DeadlockWrap(self.db.items)))
2660 return repr(dict())
267n/a
2681 def __getitem__(self, key):
269833 self._checkOpen()
2701666 return _DeadlockWrap(lambda: self.db[key]) # self.db[key]
271n/a
2721 def __setitem__(self, key, value):
273975 self._checkOpen()
274975 self._closeCursors()
275975 if self._in_iter and key not in self:
2765 self._kill_iteration = True
277975 def wrapF():
278975 self.db[key] = value
279975 _DeadlockWrap(wrapF) # self.db[key] = value
280n/a
2811 def __delitem__(self, key):
282126 self._checkOpen()
283126 self._closeCursors()
284126 if self._in_iter and key in self:
2855 self._kill_iteration = True
286126 def wrapF():
287126 del self.db[key]
288126 _DeadlockWrap(wrapF) # del self.db[key]
289n/a
2901 def close(self):
291433 self._closeCursors(save=0)
292433 if self.dbc is not None:
2930 _DeadlockWrap(self.dbc.close)
294433 v = 0
295433 if self.db is not None:
296217 v = _DeadlockWrap(self.db.close)
297433 self.dbc = None
298433 self.db = None
299433 return v
300n/a
3011 def keys(self):
302127 self._checkOpen()
303127 return _DeadlockWrap(self.db.keys)
304n/a
3051 def has_key(self, key):
30635 self._checkOpen()
30735 return _DeadlockWrap(self.db.has_key, key)
308n/a
3091 def set_location(self, key):
3105 self._checkOpen()
3115 self._checkCursor()
3125 return _DeadlockWrap(self.dbc.set_range, key)
313n/a
3141 def next(self): # Renamed by "2to3"
31533 self._checkOpen()
31633 self._checkCursor()
31733 rv = _DeadlockWrap(getattr(self.dbc, "next"))
31833 return rv
319n/a
3201 if sys.version_info[0] >= 3 : # For "2to3" conversion
3210 next = __next__
322n/a
3231 def previous(self):
32428 self._checkOpen()
32528 self._checkCursor()
32628 rv = _DeadlockWrap(self.dbc.prev)
32728 return rv
328n/a
3291 def first(self):
33048 self._checkOpen()
331n/a # fix 1725856: don't needlessly try to restore our cursor position
33248 self.saved_dbc_key = None
33348 self._checkCursor()
33448 rv = _DeadlockWrap(self.dbc.first)
33548 return rv
336n/a
3371 def last(self):
33838 self._checkOpen()
339n/a # fix 1725856: don't needlessly try to restore our cursor position
34038 self.saved_dbc_key = None
34138 self._checkCursor()
34238 rv = _DeadlockWrap(self.dbc.last)
34338 return rv
344n/a
3451 def sync(self):
346206 self._checkOpen()
347206 return _DeadlockWrap(self.db.sync)
348n/a
349n/a
350n/a#----------------------------------------------------------------------
351n/a# Compatibility object factory functions
352n/a
3531def hashopen(file, flag='c', mode=0666, pgsize=None, ffactor=None, nelem=None,
3541 cachesize=None, lorder=None, hflags=0):
355n/a
356141 flags = _checkflag(flag, file)
357141 e = _openDBEnv(cachesize)
358141 d = db.DB(e)
359141 d.set_flags(hflags)
360141 if pgsize is not None: d.set_pagesize(pgsize)
361141 if lorder is not None: d.set_lorder(lorder)
362141 if ffactor is not None: d.set_h_ffactor(ffactor)
363141 if nelem is not None: d.set_h_nelem(nelem)
364141 d.open(file, db.DB_HASH, flags, mode)
365141 return _DBWithCursor(d)
366n/a
367n/a#----------------------------------------------------------------------
368n/a
3691def btopen(file, flag='c', mode=0666,
3701 btflags=0, cachesize=None, maxkeypage=None, minkeypage=None,
3711 pgsize=None, lorder=None):
372n/a
37376 flags = _checkflag(flag, file)
37476 e = _openDBEnv(cachesize)
37576 d = db.DB(e)
37676 if pgsize is not None: d.set_pagesize(pgsize)
37776 if lorder is not None: d.set_lorder(lorder)
37876 d.set_flags(btflags)
37976 if minkeypage is not None: d.set_bt_minkey(minkeypage)
38076 if maxkeypage is not None: d.set_bt_maxkey(maxkeypage)
38176 d.open(file, db.DB_BTREE, flags, mode)
38276 return _DBWithCursor(d)
383n/a
384n/a#----------------------------------------------------------------------
385n/a
386n/a
3871def rnopen(file, flag='c', mode=0666,
3881 rnflags=0, cachesize=None, pgsize=None, lorder=None,
3891 rlen=None, delim=None, source=None, pad=None):
390n/a
3910 flags = _checkflag(flag, file)
3920 e = _openDBEnv(cachesize)
3930 d = db.DB(e)
3940 if pgsize is not None: d.set_pagesize(pgsize)
3950 if lorder is not None: d.set_lorder(lorder)
3960 d.set_flags(rnflags)
3970 if delim is not None: d.set_re_delim(delim)
3980 if rlen is not None: d.set_re_len(rlen)
3990 if source is not None: d.set_re_source(source)
4000 if pad is not None: d.set_re_pad(pad)
4010 d.open(file, db.DB_RECNO, flags, mode)
4020 return _DBWithCursor(d)
403n/a
404n/a#----------------------------------------------------------------------
405n/a
4061def _openDBEnv(cachesize):
407217 e = db.DBEnv()
408217 if cachesize is not None:
409125 if cachesize >= 20480:
410125 e.set_cachesize(0, cachesize)
411n/a else:
4120 raise error, "cachesize must be >= 20480"
413217 e.set_lk_detect(db.DB_LOCK_DEFAULT)
414217 e.open('.', db.DB_PRIVATE | db.DB_CREATE | db.DB_THREAD | db.DB_INIT_LOCK | db.DB_INIT_MPOOL)
415217 return e
416n/a
4171def _checkflag(flag, file):
418217 if flag == 'r':
4192 flags = db.DB_RDONLY
420215 elif flag == 'rw':
4210 flags = 0
422215 elif flag == 'w':
4233 flags = db.DB_CREATE
424212 elif flag == 'c':
425184 flags = db.DB_CREATE
42628 elif flag == 'n':
42728 flags = db.DB_CREATE
428n/a #flags = db.DB_CREATE | db.DB_TRUNCATE
429n/a # we used db.DB_TRUNCATE flag for this before but Berkeley DB
430n/a # 4.2.52 changed to disallowed truncate with txn environments.
43128 if file is not None and os.path.isfile(file):
4320 os.unlink(file)
433n/a else:
4340 raise error, "flags should be one of 'r', 'w', 'c' or 'n'"
435217 return flags | db.DB_THREAD
436n/a
437n/a#----------------------------------------------------------------------
438n/a
439n/a
440n/a# This is a silly little hack that allows apps to continue to use the
441n/a# DB_THREAD flag even on systems without threads without freaking out
442n/a# Berkeley DB.
443n/a#
444n/a# This assumes that if Python was built with thread support then
445n/a# Berkeley DB was too.
446n/a
4471try:
448n/a # 2to3 automatically changes "import thread" to "import _thread"
4491 import thread as T
4501 del T
451n/a
4520except ImportError:
4530 db.DB_THREAD = 0
454n/a
455n/a#----------------------------------------------------------------------