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'''
2020This module defines a backend that saves the hyperdatabase in a database
2121chosen 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