Skip to content

Commit cdcc952

Browse files
author
Richard Jones
committed
Cor blimey this anydbm/whichdb stuff is yecchy.
Turns out that whichdb incorrectly identifies a dbm file as a dbhash file on my system. This has been submitted to the python bug tracker as issue [SF#491888]: https://sourceforge.net/tracker/index.php?func=detail&aid=491888&group_id=5470&atid=105470
1 parent 96531b0 commit cdcc952

File tree

1 file changed

+31
-17
lines changed

1 file changed

+31
-17
lines changed

roundup/backends/back_anydbm.py

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
#$Id: back_anydbm.py,v 1.15 2001-12-12 02:30:51 richard Exp $
18+
#$Id: back_anydbm.py,v 1.16 2001-12-12 03:23:14 richard Exp $
1919
'''
2020
This module defines a backend that saves the hyperdatabase in a database
2121
chosen by anydbm. It is guaranteed to always be available in python
@@ -102,18 +102,23 @@ def getclassdb(self, classname, mode='r'):
102102
''' grab a connection to the class db that will be used for
103103
multiple actions
104104
'''
105-
# determine which DB wrote the class file
106-
path = os.path.join(os.getcwd(), self.dir, 'nodes.%s'%classname)
107-
db_type = whichdb.whichdb(path)
108-
if not db_type:
109-
# dbm appends ".db"
110-
db_type = whichdb.whichdb(path+'.db')
111-
db_type = whichdb.whichdb(path)
105+
return self._opendb('nodes.%s'%classname, mode)
112106

113-
# if we can't identify it and it exists...
114-
if not db_type and os.path.exists(path) or os.path.exists(path+'.db'):
115-
raise hyperdb.DatabaseError, \
116-
"Couldn't identify the database type"
107+
def _opendb(self, name, mode):
108+
'''Low-level database opener that gets around anydbm/dbm
109+
eccentricities.
110+
'''
111+
# determine which DB wrote the class file
112+
db_type = ''
113+
path = os.path.join(os.getcwd(), self.dir, name)
114+
if os.path.exists(path):
115+
db_type = whichdb.whichdb(path)
116+
if not db_type:
117+
raise hyperdb.DatabaseError, "Couldn't identify database type"
118+
elif os.path.exists(path+'.db'):
119+
# if the path ends in '.db', it's a dbm database, whether
120+
# anydbm says it's dbhash or not!
121+
db_type = 'dbm'
117122

118123
# new database? let anydbm pick the best dbm
119124
if not db_type:
@@ -122,7 +127,7 @@ def getclassdb(self, classname, mode='r'):
122127
# open the database with the correct module
123128
try:
124129
dbm = __import__(db_type)
125-
except:
130+
except ImportError:
126131
raise hyperdb.DatabaseError, \
127132
"Couldn't open database - the required module '%s'"\
128133
"is not available"%db_type
@@ -217,10 +222,10 @@ def getjournal(self, classname, nodeid):
217222
# attempt to open the journal - in some rare cases, the journal may
218223
# not exist
219224
try:
220-
db = anydbm.open(os.path.join(self.dir, 'journals.%s'%classname),
221-
'r')
222-
except anydbm.open, error:
223-
if error.args[0] != 2: raise
225+
db = self._opendb('journals.%s'%classname, 'r')
226+
except anydbm.error, error:
227+
if str(error) == "need 'c' or 'n' flag to open new db": return []
228+
elif error.args[0] != 2: raise
224229
return []
225230
journal = marshal.loads(db[nodeid])
226231
res = []
@@ -278,6 +283,15 @@ def rollback(self):
278283

279284
#
280285
#$Log: not supported by cvs2svn $
286+
#Revision 1.15 2001/12/12 02:30:51 richard
287+
#I fixed the problems with people whose anydbm was using the dbm module at the
288+
#backend. It turns out the dbm module modifies the file name to append ".db"
289+
#and my check to determine if we're opening an existing or new db just
290+
#tested os.path.exists() on the filename. Well, no longer! We now perform a
291+
#much better check _and_ cope with the anydbm implementation module changing
292+
#too!
293+
#I also fixed the backends __init__ so only ImportError is squashed.
294+
#
281295
#Revision 1.14 2001/12/10 22:20:01 richard
282296
#Enabled transaction support in the bsddb backend. It uses the anydbm code
283297
#where possible, only replacing methods where the db is opened (it uses the

0 commit comments

Comments
 (0)