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

Python code coverage for Lib/bsddb/dbshelve.py

#countcontent
1n/a#!/usr/bin/env python
2n/a#------------------------------------------------------------------------
3n/a# Copyright (c) 1997-2001 by Total Control Software
4n/a# All Rights Reserved
5n/a#------------------------------------------------------------------------
6n/a#
7n/a# Module Name: dbShelve.py
8n/a#
9n/a# Description: A reimplementation of the standard shelve.py that
10n/a# forces the use of cPickle, and DB.
11n/a#
12n/a# Creation Date: 11/3/97 3:39:04PM
13n/a#
14n/a# License: This is free software. You may use this software for any
15n/a# purpose including modification/redistribution, so long as
16n/a# this header remains intact and that you do not claim any
17n/a# rights of ownership or authorship of this software. This
18n/a# software has been tested, but no warranty is expressed or
19n/a# implied.
20n/a#
21n/a# 13-Dec-2000: Updated to be used with the new bsddb3 package.
22n/a# Added DBShelfCursor class.
23n/a#
24n/a#------------------------------------------------------------------------
25n/a
26n/a"""Manage shelves of pickled objects using bsddb database files for the
27n/astorage.
28n/a"""
29n/a
30n/a#------------------------------------------------------------------------
31n/a
32n/aimport sys
33n/aabsolute_import = (sys.version_info[0] >= 3)
34n/aif absolute_import :
35n/a # Because this syntaxis is not valid before Python 2.5
36n/a exec("from . import db")
37n/aelse :
38n/a import db
39n/a
40n/aif sys.version_info[0] >= 3 :
41n/a import cPickle # Will be converted to "pickle" by "2to3"
42n/aelse :
43n/a if sys.version_info < (2, 6) :
44n/a import cPickle
45n/a else :
46n/a # When we drop support for python 2.3 and 2.4
47n/a # we could use: (in 2.5 we need a __future__ statement)
48n/a #
49n/a # with warnings.catch_warnings():
50n/a # warnings.filterwarnings(...)
51n/a # ...
52n/a #
53n/a # We can not use "with" as is, because it would be invalid syntax
54n/a # in python 2.3, 2.4 and (with no __future__) 2.5.
55n/a # Here we simulate "with" following PEP 343 :
56n/a import warnings
57n/a w = warnings.catch_warnings()
58n/a w.__enter__()
59n/a try :
60n/a warnings.filterwarnings('ignore',
61n/a message='the cPickle module has been removed in Python 3.0',
62n/a category=DeprecationWarning)
63n/a import cPickle
64n/a finally :
65n/a w.__exit__()
66n/a del w
67n/a
68n/a#At version 2.3 cPickle switched to using protocol instead of bin
69n/aif sys.version_info >= (2, 3):
70n/a HIGHEST_PROTOCOL = cPickle.HIGHEST_PROTOCOL
71n/a# In python 2.3.*, "cPickle.dumps" accepts no
72n/a# named parameters. "pickle.dumps" accepts them,
73n/a# so this seems a bug.
74n/a if sys.version_info < (2, 4):
75n/a def _dumps(object, protocol):
76n/a return cPickle.dumps(object, protocol)
77n/a else :
78n/a def _dumps(object, protocol):
79n/a return cPickle.dumps(object, protocol=protocol)
80n/a
81n/aelse:
82n/a HIGHEST_PROTOCOL = None
83n/a def _dumps(object, protocol):
84n/a return cPickle.dumps(object, bin=protocol)
85n/a
86n/a
87n/aif sys.version_info < (2, 6) :
88n/a try:
89n/a from UserDict import DictMixin
90n/a except ImportError:
91n/a # DictMixin is new in Python 2.3
92n/a class DictMixin: pass
93n/a MutableMapping = DictMixin
94n/aelse :
95n/a import collections
96n/a MutableMapping = collections.MutableMapping
97n/a
98n/a#------------------------------------------------------------------------
99n/a
100n/a
101n/adef open(filename, flags=db.DB_CREATE, mode=0660, filetype=db.DB_HASH,
102n/a dbenv=None, dbname=None):
103n/a """
104n/a A simple factory function for compatibility with the standard
105n/a shleve.py module. It can be used like this, where key is a string
106n/a and data is a pickleable object:
107n/a
108n/a from bsddb import dbshelve
109n/a db = dbshelve.open(filename)
110n/a
111n/a db[key] = data
112n/a
113n/a db.close()
114n/a """
115n/a if type(flags) == type(''):
116n/a sflag = flags
117n/a if sflag == 'r':
118n/a flags = db.DB_RDONLY
119n/a elif sflag == 'rw':
120n/a flags = 0
121n/a elif sflag == 'w':
122n/a flags = db.DB_CREATE
123n/a elif sflag == 'c':
124n/a flags = db.DB_CREATE
125n/a elif sflag == 'n':
126n/a flags = db.DB_TRUNCATE | db.DB_CREATE
127n/a else:
128n/a raise db.DBError, "flags should be one of 'r', 'w', 'c' or 'n' or use the bsddb.db.DB_* flags"
129n/a
130n/a d = DBShelf(dbenv)
131n/a d.open(filename, dbname, filetype, flags, mode)
132n/a return d
133n/a
134n/a#---------------------------------------------------------------------------
135n/a
136n/aclass DBShelveError(db.DBError): pass
137n/a
138n/a
139n/aclass DBShelf(MutableMapping):
140n/a """A shelf to hold pickled objects, built upon a bsddb DB object. It
141n/a automatically pickles/unpickles data objects going to/from the DB.
142n/a """
143n/a def __init__(self, dbenv=None):
144n/a self.db = db.DB(dbenv)
145n/a self._closed = True
146n/a if HIGHEST_PROTOCOL:
147n/a self.protocol = HIGHEST_PROTOCOL
148n/a else:
149n/a self.protocol = 1
150n/a
151n/a
152n/a def __del__(self):
153n/a self.close()
154n/a
155n/a
156n/a def __getattr__(self, name):
157n/a """Many methods we can just pass through to the DB object.
158n/a (See below)
159n/a """
160n/a return getattr(self.db, name)
161n/a
162n/a
163n/a #-----------------------------------
164n/a # Dictionary access methods
165n/a
166n/a def __len__(self):
167n/a return len(self.db)
168n/a
169n/a
170n/a def __getitem__(self, key):
171n/a data = self.db[key]
172n/a return cPickle.loads(data)
173n/a
174n/a
175n/a def __setitem__(self, key, value):
176n/a data = _dumps(value, self.protocol)
177n/a self.db[key] = data
178n/a
179n/a
180n/a def __delitem__(self, key):
181n/a del self.db[key]
182n/a
183n/a
184n/a def keys(self, txn=None):
185n/a if txn is not None:
186n/a return self.db.keys(txn)
187n/a else:
188n/a return self.db.keys()
189n/a
190n/a if sys.version_info >= (2, 6) :
191n/a def __iter__(self) : # XXX: Load all keys in memory :-(
192n/a for k in self.db.keys() :
193n/a yield k
194n/a
195n/a # Do this when "DB" support iteration
196n/a # Or is it enough to pass thru "getattr"?
197n/a #
198n/a # def __iter__(self) :
199n/a # return self.db.__iter__()
200n/a
201n/a
202n/a def open(self, *args, **kwargs):
203n/a self.db.open(*args, **kwargs)
204n/a self._closed = False
205n/a
206n/a
207n/a def close(self, *args, **kwargs):
208n/a self.db.close(*args, **kwargs)
209n/a self._closed = True
210n/a
211n/a
212n/a def __repr__(self):
213n/a if self._closed:
214n/a return '<DBShelf @ 0x%x - closed>' % (id(self))
215n/a else:
216n/a return repr(dict(self.iteritems()))
217n/a
218n/a
219n/a def items(self, txn=None):
220n/a if txn is not None:
221n/a items = self.db.items(txn)
222n/a else:
223n/a items = self.db.items()
224n/a newitems = []
225n/a
226n/a for k, v in items:
227n/a newitems.append( (k, cPickle.loads(v)) )
228n/a return newitems
229n/a
230n/a def values(self, txn=None):
231n/a if txn is not None:
232n/a values = self.db.values(txn)
233n/a else:
234n/a values = self.db.values()
235n/a
236n/a return map(cPickle.loads, values)
237n/a
238n/a #-----------------------------------
239n/a # Other methods
240n/a
241n/a def __append(self, value, txn=None):
242n/a data = _dumps(value, self.protocol)
243n/a return self.db.append(data, txn)
244n/a
245n/a def append(self, value, txn=None):
246n/a if self.get_type() == db.DB_RECNO:
247n/a return self.__append(value, txn=txn)
248n/a raise DBShelveError, "append() only supported when dbshelve opened with filetype=dbshelve.db.DB_RECNO"
249n/a
250n/a
251n/a def associate(self, secondaryDB, callback, flags=0):
252n/a def _shelf_callback(priKey, priData, realCallback=callback):
253n/a # Safe in Python 2.x because expresion short circuit
254n/a if sys.version_info[0] < 3 or isinstance(priData, bytes) :
255n/a data = cPickle.loads(priData)
256n/a else :
257n/a data = cPickle.loads(bytes(priData, "iso8859-1")) # 8 bits
258n/a return realCallback(priKey, data)
259n/a
260n/a return self.db.associate(secondaryDB, _shelf_callback, flags)
261n/a
262n/a
263n/a #def get(self, key, default=None, txn=None, flags=0):
264n/a def get(self, *args, **kw):
265n/a # We do it with *args and **kw so if the default value wasn't
266n/a # given nothing is passed to the extension module. That way
267n/a # an exception can be raised if set_get_returns_none is turned
268n/a # off.
269n/a data = self.db.get(*args, **kw)
270n/a try:
271n/a return cPickle.loads(data)
272n/a except (EOFError, TypeError, cPickle.UnpicklingError):
273n/a return data # we may be getting the default value, or None,
274n/a # so it doesn't need unpickled.
275n/a
276n/a def get_both(self, key, value, txn=None, flags=0):
277n/a data = _dumps(value, self.protocol)
278n/a data = self.db.get(key, data, txn, flags)
279n/a return cPickle.loads(data)
280n/a
281n/a
282n/a def cursor(self, txn=None, flags=0):
283n/a c = DBShelfCursor(self.db.cursor(txn, flags))
284n/a c.protocol = self.protocol
285n/a return c
286n/a
287n/a
288n/a def put(self, key, value, txn=None, flags=0):
289n/a data = _dumps(value, self.protocol)
290n/a return self.db.put(key, data, txn, flags)
291n/a
292n/a
293n/a def join(self, cursorList, flags=0):
294n/a raise NotImplementedError
295n/a
296n/a
297n/a #----------------------------------------------
298n/a # Methods allowed to pass-through to self.db
299n/a #
300n/a # close, delete, fd, get_byteswapped, get_type, has_key,
301n/a # key_range, open, remove, rename, stat, sync,
302n/a # upgrade, verify, and all set_* methods.
303n/a
304n/a
305n/a#---------------------------------------------------------------------------
306n/a
307n/aclass DBShelfCursor:
308n/a """
309n/a """
310n/a def __init__(self, cursor):
311n/a self.dbc = cursor
312n/a
313n/a def __del__(self):
314n/a self.close()
315n/a
316n/a
317n/a def __getattr__(self, name):
318n/a """Some methods we can just pass through to the cursor object. (See below)"""
319n/a return getattr(self.dbc, name)
320n/a
321n/a
322n/a #----------------------------------------------
323n/a
324n/a def dup(self, flags=0):
325n/a c = DBShelfCursor(self.dbc.dup(flags))
326n/a c.protocol = self.protocol
327n/a return c
328n/a
329n/a
330n/a def put(self, key, value, flags=0):
331n/a data = _dumps(value, self.protocol)
332n/a return self.dbc.put(key, data, flags)
333n/a
334n/a
335n/a def get(self, *args):
336n/a count = len(args) # a method overloading hack
337n/a method = getattr(self, 'get_%d' % count)
338n/a method(*args)
339n/a
340n/a def get_1(self, flags):
341n/a rec = self.dbc.get(flags)
342n/a return self._extract(rec)
343n/a
344n/a def get_2(self, key, flags):
345n/a rec = self.dbc.get(key, flags)
346n/a return self._extract(rec)
347n/a
348n/a def get_3(self, key, value, flags):
349n/a data = _dumps(value, self.protocol)
350n/a rec = self.dbc.get(key, flags)
351n/a return self._extract(rec)
352n/a
353n/a
354n/a def current(self, flags=0): return self.get_1(flags|db.DB_CURRENT)
355n/a def first(self, flags=0): return self.get_1(flags|db.DB_FIRST)
356n/a def last(self, flags=0): return self.get_1(flags|db.DB_LAST)
357n/a def next(self, flags=0): return self.get_1(flags|db.DB_NEXT)
358n/a def prev(self, flags=0): return self.get_1(flags|db.DB_PREV)
359n/a def consume(self, flags=0): return self.get_1(flags|db.DB_CONSUME)
360n/a def next_dup(self, flags=0): return self.get_1(flags|db.DB_NEXT_DUP)
361n/a def next_nodup(self, flags=0): return self.get_1(flags|db.DB_NEXT_NODUP)
362n/a def prev_nodup(self, flags=0): return self.get_1(flags|db.DB_PREV_NODUP)
363n/a
364n/a
365n/a def get_both(self, key, value, flags=0):
366n/a data = _dumps(value, self.protocol)
367n/a rec = self.dbc.get_both(key, flags)
368n/a return self._extract(rec)
369n/a
370n/a
371n/a def set(self, key, flags=0):
372n/a rec = self.dbc.set(key, flags)
373n/a return self._extract(rec)
374n/a
375n/a def set_range(self, key, flags=0):
376n/a rec = self.dbc.set_range(key, flags)
377n/a return self._extract(rec)
378n/a
379n/a def set_recno(self, recno, flags=0):
380n/a rec = self.dbc.set_recno(recno, flags)
381n/a return self._extract(rec)
382n/a
383n/a set_both = get_both
384n/a
385n/a def _extract(self, rec):
386n/a if rec is None:
387n/a return None
388n/a else:
389n/a key, data = rec
390n/a # Safe in Python 2.x because expresion short circuit
391n/a if sys.version_info[0] < 3 or isinstance(data, bytes) :
392n/a return key, cPickle.loads(data)
393n/a else :
394n/a return key, cPickle.loads(bytes(data, "iso8859-1")) # 8 bits
395n/a
396n/a #----------------------------------------------
397n/a # Methods allowed to pass-through to self.dbc
398n/a #
399n/a # close, count, delete, get_recno, join_item
400n/a
401n/a
402n/a#---------------------------------------------------------------------------