Skip to content

Commit b17acad

Browse files
committed
Make db modules' error classes inherit IOError.
Stop dbm from importing every dbm module when imported.
1 parent e81f5ef commit b17acad

File tree

5 files changed

+50
-51
lines changed

5 files changed

+50
-51
lines changed

Lib/dbm/__init__.py

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -48,27 +48,26 @@ class error(Exception):
4848
pass
4949

5050
_names = ['dbm.bsd', 'dbm.gnu', 'dbm.ndbm', 'dbm.dumb']
51-
_errors = [error]
5251
_defaultmod = None
5352
_modules = {}
5453

55-
for _name in _names:
56-
try:
57-
_mod = __import__(_name, fromlist=['open'])
58-
except ImportError:
59-
continue
60-
if not _defaultmod:
61-
_defaultmod = _mod
62-
_modules[_name] = _mod
63-
_errors.append(_mod.error)
64-
65-
if not _defaultmod:
66-
raise ImportError("no dbm clone found; tried %s" % _names)
67-
68-
error = tuple(_errors)
54+
error = (error, IOError)
6955

7056

7157
def open(file, flag = 'r', mode = 0o666):
58+
global _defaultmod
59+
if _defaultmod is None:
60+
for name in _names:
61+
try:
62+
mod = __import__(name, fromlist=['open'])
63+
except ImportError:
64+
continue
65+
if not _defaultmod:
66+
_defaultmod = mod
67+
_modules[name] = mod
68+
if not _defaultmod:
69+
raise ImportError("no dbm clone found; tried %s" % _names)
70+
7271
# guess the type of an existing database
7372
result = whichdb(file)
7473
if result is None:
@@ -81,19 +80,14 @@ def open(file, flag = 'r', mode = 0o666):
8180
elif result == "":
8281
# db type cannot be determined
8382
raise error("db type could not be determined")
83+
elif result not in _modules:
84+
raise error("db type is {0}, but the module is not "
85+
"available".format(result))
8486
else:
8587
mod = _modules[result]
8688
return mod.open(file, flag, mode)
8789

8890

89-
try:
90-
from dbm import ndbm
91-
_dbmerror = ndbm.error
92-
except ImportError:
93-
ndbm = None
94-
# just some sort of valid exception which might be raised in the ndbm test
95-
_dbmerror = IOError
96-
9791
def whichdb(filename):
9892
"""Guess which db package to use to open a db file.
9993
@@ -129,7 +123,7 @@ def whichdb(filename):
129123
d = ndbm.open(filename)
130124
d.close()
131125
return "dbm.ndbm"
132-
except (IOError, _dbmerror):
126+
except IOError:
133127
pass
134128

135129
# Check for dumbdbm next -- this has a .dir and a .dat file

Lib/dbm/bsd.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
__all__ = ["error", "open"]
66

7-
error = bsddb.error
7+
class error(bsddb.error, IOError):
8+
pass
89

910
def open(file, flag = 'r', mode=0o666):
1011
return bsddb.hashopen(file, flag, mode)

Lib/test/test_dbm.py

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
# setting dbm to use each in turn, and yielding that module
1515
#
1616
def dbm_iterator():
17-
old_default = dbm._defaultmod
18-
for module in dbm._modules.values():
19-
dbm._defaultmod = module
20-
yield module
21-
dbm._defaultmod = old_default
17+
for name in dbm._names:
18+
try:
19+
mod = __import__(name, fromlist=['open'])
20+
except ImportError:
21+
continue
22+
dbm._modules[name] = mod
23+
yield mod
2224

2325
#
2426
# Clean up all scratch databases we might have created during testing
@@ -40,8 +42,20 @@ class AnyDBMTestCase(unittest.TestCase):
4042
'g': b'intended',
4143
}
4244

43-
def __init__(self, *args):
44-
unittest.TestCase.__init__(self, *args)
45+
def init_db(self):
46+
f = dbm.open(_fname, 'n')
47+
for k in self._dict:
48+
f[k.encode("ascii")] = self._dict[k]
49+
f.close()
50+
51+
def keys_helper(self, f):
52+
keys = sorted(k.decode("ascii") for k in f.keys())
53+
dkeys = sorted(self._dict.keys())
54+
self.assertEqual(keys, dkeys)
55+
return keys
56+
57+
def test_error(self):
58+
self.assert_(issubclass(self.module.error, IOError))
4559

4660
def test_anydbm_creation(self):
4761
f = dbm.open(_fname, 'c')
@@ -83,22 +97,11 @@ def read_helper(self, f):
8397
for key in self._dict:
8498
self.assertEqual(self._dict[key], f[key.encode("ascii")])
8599

86-
def init_db(self):
87-
f = dbm.open(_fname, 'n')
88-
for k in self._dict:
89-
f[k.encode("ascii")] = self._dict[k]
90-
f.close()
91-
92-
def keys_helper(self, f):
93-
keys = sorted(k.decode("ascii") for k in f.keys())
94-
dkeys = sorted(self._dict.keys())
95-
self.assertEqual(keys, dkeys)
96-
return keys
97-
98100
def tearDown(self):
99101
delete_files()
100102

101103
def setUp(self):
104+
dbm._defaultmod = self.module
102105
delete_files()
103106

104107

@@ -137,11 +140,11 @@ def setUp(self):
137140

138141

139142
def test_main():
140-
try:
141-
for module in dbm_iterator():
142-
test.support.run_unittest(AnyDBMTestCase, WhichDBTestCase)
143-
finally:
144-
delete_files()
143+
classes = [WhichDBTestCase]
144+
for mod in dbm_iterator():
145+
classes.append(type("TestCase-" + mod.__name__, (AnyDBMTestCase,),
146+
{'module': mod}))
147+
test.support.run_unittest(*classes)
145148

146149
if __name__ == "__main__":
147150
test_main()

Modules/_dbmmodule.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,8 @@ init_dbm(void) {
401401
return;
402402
d = PyModule_GetDict(m);
403403
if (DbmError == NULL)
404-
DbmError = PyErr_NewException("_dbm.error", NULL, NULL);
404+
DbmError = PyErr_NewException("_dbm.error",
405+
PyExc_IOError, NULL);
405406
s = PyUnicode_FromString(which_dbm);
406407
if (s != NULL) {
407408
PyDict_SetItemString(d, "library", s);

Modules/_gdbmmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ init_gdbm(void) {
523523
if (m == NULL)
524524
return;
525525
d = PyModule_GetDict(m);
526-
DbmError = PyErr_NewException("_gdbm.error", NULL, NULL);
526+
DbmError = PyErr_NewException("_gdbm.error", PyExc_IOError, NULL);
527527
if (DbmError != NULL) {
528528
PyDict_SetItemString(d, "error", DbmError);
529529
s = PyUnicode_FromString(dbmmodule_open_flags);

0 commit comments

Comments
 (0)