Mercurial > p > roundup > code
diff roundup/backends/back_anydbm.py @ 4357:13b3155869e0
Beginnings of a big code cleanup / modernisation to make 2to3 happy
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Mon, 22 Feb 2010 05:26:57 +0000 |
| parents | 1f89953f8c8a |
| children | 0e81742d0e2f |
line wrap: on
line diff
--- a/roundup/backends/back_anydbm.py Fri Feb 19 05:09:38 2010 +0000 +++ b/roundup/backends/back_anydbm.py Mon Feb 22 05:26:57 2010 +0000 @@ -22,30 +22,22 @@ """ __docformat__ = 'restructuredtext' -try: - import anydbm, sys - # dumbdbm only works in python 2.1.2+ - if sys.version_info < (2,1,2): - import dumbdbm - assert anydbm._defaultmod != dumbdbm - del dumbdbm -except AssertionError: - print "WARNING: you should upgrade to python 2.1.3" +import os, marshal, re, weakref, string, copy, time, shutil, logging -import whichdb, os, marshal, re, weakref, string, copy, time, shutil, logging +from roundup.anypy.dbm_ import anydbm, whichdb from roundup import hyperdb, date, password, roundupdb, security, support from roundup.support import reversed from roundup.backends import locking from roundup.i18n import _ -from blobfiles import FileStorage -from sessions_dbm import Sessions, OneTimeKeys +from roundup.backends.blobfiles import FileStorage +from roundup.backends.sessions_dbm import Sessions, OneTimeKeys try: - from indexer_xapian import Indexer + from roundup.backends.indexer_xapian import Indexer except ImportError: - from indexer_dbm import Indexer + from roundup.backends.indexer_dbm import Indexer def db_exists(config): # check for the user db @@ -146,13 +138,13 @@ # def __getattr__(self, classname): """A convenient way of calling self.getclass(classname).""" - if self.classes.has_key(classname): + if classname in self.classes: return self.classes[classname] raise AttributeError, classname def addclass(self, cl): cn = cl.classname - if self.classes.has_key(cn): + if cn in self.classes: raise ValueError, cn self.classes[cn] = cl @@ -166,9 +158,7 @@ def getclasses(self): """Return a list of the names of all existing classes.""" - l = self.classes.keys() - l.sort() - return l + return sorted(self.classes) def getclass(self, classname): """Get the Class object representing a particular class. @@ -178,7 +168,7 @@ try: return self.classes[classname] except KeyError: - raise KeyError, 'There is no class called "%s"'%classname + raise KeyError('There is no class called "%s"'%classname) # # Class DBs @@ -187,7 +177,7 @@ """Delete all database contents """ logging.getLogger('hyperdb').info('clear') - for cn in self.classes.keys(): + for cn in self.classes: for dummy in 'nodes', 'journals': path = os.path.join(self.dir, 'journals.%s'%cn) if os.path.exists(path): @@ -212,10 +202,9 @@ """ db_type = '' if os.path.exists(path): - db_type = whichdb.whichdb(path) + db_type = whichdb(path) if not db_type: - raise hyperdb.DatabaseError, \ - _("Couldn't identify database type") + raise hyperdb.DatabaseError(_("Couldn't identify database type")) elif os.path.exists(path+'.db'): # if the path ends in '.db', it's a dbm database, whether # anydbm says it's dbhash or not! @@ -231,21 +220,24 @@ db_type = self.determine_db_type(path) # new database? let anydbm pick the best dbm - if not db_type: + # in Python 3+ the "dbm" ("anydbm" to us) module already uses the + # whichdb() function to do this + if not db_type or hasattr(anydbm, 'whichdb'): if __debug__: - logging.getLogger('hyperdb').debug("opendb anydbm.open(%r, 'c')"%path) + logging.getLogger('hyperdb').debug( + "opendb anydbm.open(%r, 'c')"%path) return anydbm.open(path, 'c') - # open the database with the correct module + # in Python <3 it anydbm was a little dumb so manually open the + # database with the correct module try: dbm = __import__(db_type) except ImportError: - raise hyperdb.DatabaseError, \ - _("Couldn't open database - the required module '%s'"\ - " is not available")%db_type + raise hyperdb.DatabaseError(_("Couldn't open database - the " + "required module '%s' is not available")%db_type) if __debug__: - logging.getLogger('hyperdb').debug("opendb %r.open(%r, %r)"%(db_type, path, - mode)) + logging.getLogger('hyperdb').debug( + "opendb %r.open(%r, %r)"%(db_type, path, mode)) return dbm.open(path, mode) # @@ -256,7 +248,7 @@ """ # open the ids DB - create if if doesn't exist db = self.opendb('_ids', 'c') - if db.has_key(classname): + if classname in db: newid = db[classname] = str(int(db[classname]) + 1) else: # the count() bit is transitional - older dbs won't start at 1 @@ -280,7 +272,7 @@ """ add the specified node to its class's db """ # we'll be supplied these props if we're doing an import - if not node.has_key('creator'): + if 'creator' not in node: # add in the "calculated" properties (dupe so we don't affect # calling code's node assumptions) node = node.copy() @@ -316,7 +308,7 @@ """ # try the cache cache_dict = self.cache.setdefault(classname, {}) - if cache_dict.has_key(nodeid): + if nodeid in cache_dict: if __debug__: logging.getLogger('hyperdb').debug('get %s%s cached'%(classname, nodeid)) self.stats['cache_hits'] += 1 @@ -330,13 +322,13 @@ # get from the database and save in the cache if db is None: db = self.getclassdb(classname) - if not db.has_key(nodeid): - raise IndexError, "no such %s %s"%(classname, nodeid) + if nodeid not in db: + raise IndexError("no such %s %s"%(classname, nodeid)) # check the uncommitted, destroyed nodes - if (self.destroyednodes.has_key(classname) and - self.destroyednodes[classname].has_key(nodeid)): - raise IndexError, "no such %s %s"%(classname, nodeid) + if (classname in self.destroyednodes and + nodeid in self.destroyednodes[classname]): + raise IndexError("no such %s %s"%(classname, nodeid)) # decode res = marshal.loads(db[nodeid]) @@ -360,11 +352,9 @@ logging.getLogger('hyperdb').info('destroy %s%s'%(classname, nodeid)) # remove from cache and newnodes if it's there - if (self.cache.has_key(classname) and - self.cache[classname].has_key(nodeid)): + if (classname in self.cache and nodeid in self.cache[classname]): del self.cache[classname][nodeid] - if (self.newnodes.has_key(classname) and - self.newnodes[classname].has_key(nodeid)): + if (classname in self.newnodes and nodeid in self.newnodes[classname]): del self.newnodes[classname][nodeid] # see if there's any obvious commit actions that we should get rid of @@ -385,13 +375,13 @@ """ properties = self.getclass(classname).getprops() d = {} - for k, v in node.items(): + for k, v in node.iteritems(): if k == self.RETIRED_FLAG: d[k] = v continue # if the property doesn't exist then we really don't care - if not properties.has_key(k): + if k not in properties: continue # get the property spec @@ -412,10 +402,10 @@ """ properties = self.getclass(classname).getprops() d = {} - for k, v in node.items(): + for k, v in node.iteritems(): # if the property doesn't exist, or is the "retired" flag then # it won't be in the properties dict - if not properties.has_key(k): + if k not in properties: d[k] = v continue @@ -439,29 +429,27 @@ """ # try the cache cache = self.cache.setdefault(classname, {}) - if cache.has_key(nodeid): + if nodeid in cache: return 1 # not in the cache - check the database if db is None: db = self.getclassdb(classname) - res = db.has_key(nodeid) - return res + return nodeid in db def countnodes(self, classname, db=None): count = 0 # include the uncommitted nodes - if self.newnodes.has_key(classname): + if classname in self.newnodes: count += len(self.newnodes[classname]) - if self.destroyednodes.has_key(classname): + if classname in self.destroyednodes: count -= len(self.destroyednodes[classname]) # and count those in the DB if db is None: db = self.getclassdb(classname) - count = count + len(db.keys()) - return count + return count + len(db) # @@ -529,14 +517,14 @@ db = self.opendb('journals.%s'%classname, 'r') except anydbm.error, error: if str(error) == "need 'c' or 'n' flag to open new db": - raise IndexError, 'no such %s %s'%(classname, nodeid) + raise IndexError('no such %s %s'%(classname, nodeid)) elif error.args[0] != 2: # this isn't a "not found" error, be alarmed! raise if res: # we have unsaved journal entries, return them return res - raise IndexError, 'no such %s %s'%(classname, nodeid) + raise IndexError('no such %s %s'%(classname, nodeid)) try: journal = marshal.loads(db[nodeid]) except KeyError: @@ -544,7 +532,7 @@ if res: # we have some unsaved journal entries, be happy! return res - raise IndexError, 'no such %s %s'%(classname, nodeid) + raise IndexError('no such %s %s'%(classname, nodeid)) db.close() # add all the saved journal entries for this node @@ -564,7 +552,7 @@ db_type = self.determine_db_type(path) db = self.opendb(db_name, 'w') - for key in db.keys(): + for key in db: # get the journal for this db entry journal = marshal.loads(db[key]) l = [] @@ -617,7 +605,7 @@ reindex[method(*args)] = 1 finally: # make sure we close all the database files - for db in self.databases.values(): + for db in self.databases.itervalues(): db.close() del self.databases @@ -627,7 +615,7 @@ self.transactions = [] # reindex the nodes that request it - for classname, nodeid in filter(None, reindex.keys()): + for classname, nodeid in [k for k in reindex if k]: self.getclass(classname).index(nodeid) # save the indexer state @@ -648,7 +636,7 @@ """ # get the database handle db_name = 'nodes.%s'%classname - if not self.databases.has_key(db_name): + if db_name not in self.databases: self.databases[db_name] = self.getclassdb(classname, 'c') return self.databases[db_name] @@ -666,7 +654,7 @@ """ # get the database handle db_name = 'journals.%s'%classname - if not self.databases.has_key(db_name): + if db_name not in self.databases: self.databases[db_name] = self.opendb(db_name, 'c') return self.databases[db_name] @@ -691,7 +679,7 @@ db = self.getCachedJournalDB(classname) # now insert the journal entry - if db.has_key(nodeid): + if nodeid in db: # append to existing s = db[nodeid] l = marshal.loads(s) @@ -716,12 +704,12 @@ def doDestroyNode(self, classname, nodeid): # delete from the class database db = self.getCachedClassDB(classname) - if db.has_key(nodeid): + if nodeid in db: del db[nodeid] # delete from the database db = self.getCachedJournalDB(classname) - if db.has_key(nodeid): + if nodeid in db: del db[nodeid] def rollback(self): @@ -785,7 +773,7 @@ to modify the "creation" or "activity" properties cause a KeyError. """ if self.db.journaltag is None: - raise hyperdb.DatabaseError, _('Database open read-only') + raise hyperdb.DatabaseError(_('Database open read-only')) self.fireAuditors('create', None, propvalues) newid = self.create_inner(**propvalues) self.fireReactors('create', newid, None) @@ -794,48 +782,49 @@ def create_inner(self, **propvalues): """ Called by create, in-between the audit and react calls. """ - if propvalues.has_key('id'): - raise KeyError, '"id" is reserved' + if 'id' in propvalues: + raise KeyError('"id" is reserved') if self.db.journaltag is None: - raise hyperdb.DatabaseError, _('Database open read-only') + raise hyperdb.DatabaseError(_('Database open read-only')) - if propvalues.has_key('creation') or propvalues.has_key('activity'): - raise KeyError, '"creation" and "activity" are reserved' + if 'creation' in propvalues or 'activity' in propvalues: + raise KeyError('"creation" and "activity" are reserved') # new node's id newid = self.db.newid(self.classname) # validate propvalues num_re = re.compile('^\d+$') - for key, value in propvalues.items(): + for key, value in propvalues.iteritems(): if key == self.key: try: self.lookup(value) except KeyError: pass else: - raise ValueError, 'node with key "%s" exists'%value + raise ValueError('node with key "%s" exists'%value) # try to handle this property try: prop = self.properties[key] except KeyError: - raise KeyError, '"%s" has no property "%s"'%(self.classname, - key) + raise KeyError('"%s" has no property "%s"'%(self.classname, + key)) if value is not None and isinstance(prop, hyperdb.Link): if type(value) != type(''): - raise ValueError, 'link value must be String' + raise ValueError('link value must be String') link_class = self.properties[key].classname # if it isn't a number, it's a key if not num_re.match(value): try: value = self.db.classes[link_class].lookup(value) except (TypeError, KeyError): - raise IndexError, 'new property "%s": %s not a %s'%( - key, value, link_class) + raise IndexError('new property "%s": %s not a %s'%( + key, value, link_class)) elif not self.db.getclass(link_class).hasnode(value): - raise IndexError, '%s has no node %s'%(link_class, value) + raise IndexError('%s has no node %s'%(link_class, + value)) # save off the value propvalues[key] = value @@ -849,22 +838,22 @@ if value is None: value = [] if not hasattr(value, '__iter__'): - raise TypeError, 'new property "%s" not an iterable of ids'%key + raise TypeError('new property "%s" not an iterable of ids'%key) # clean up and validate the list of links link_class = self.properties[key].classname l = [] for entry in value: if type(entry) != type(''): - raise ValueError, '"%s" multilink value (%r) '\ - 'must contain Strings'%(key, value) + raise ValueError('"%s" multilink value (%r) '\ + 'must contain Strings'%(key, value)) # if it isn't a number, it's a key if not num_re.match(entry): try: entry = self.db.classes[link_class].lookup(entry) except (TypeError, KeyError): - raise IndexError, 'new property "%s": %s not a %s'%( - key, entry, self.properties[key].classname) + raise IndexError('new property "%s": %s not a %s'%( + key, entry, self.properties[key].classname)) l.append(entry) value = l propvalues[key] = value @@ -872,8 +861,8 @@ # handle additions for nodeid in value: if not self.db.getclass(link_class).hasnode(nodeid): - raise IndexError, '%s has no node %s'%(link_class, - nodeid) + raise IndexError('%s has no node %s'%(link_class, + nodeid)) # register the link with the newly linked node if self.do_journal and self.properties[key].do_journal: self.db.addjournal(link_class, nodeid, 'link', @@ -881,41 +870,41 @@ elif isinstance(prop, hyperdb.String): if type(value) != type('') and type(value) != type(u''): - raise TypeError, 'new property "%s" not a string'%key + raise TypeError('new property "%s" not a string'%key) if prop.indexme: self.db.indexer.add_text((self.classname, newid, key), value) elif isinstance(prop, hyperdb.Password): if not isinstance(value, password.Password): - raise TypeError, 'new property "%s" not a Password'%key + raise TypeError('new property "%s" not a Password'%key) elif isinstance(prop, hyperdb.Date): if value is not None and not isinstance(value, date.Date): - raise TypeError, 'new property "%s" not a Date'%key + raise TypeError('new property "%s" not a Date'%key) elif isinstance(prop, hyperdb.Interval): if value is not None and not isinstance(value, date.Interval): - raise TypeError, 'new property "%s" not an Interval'%key + raise TypeError('new property "%s" not an Interval'%key) elif value is not None and isinstance(prop, hyperdb.Number): try: float(value) except ValueError: - raise TypeError, 'new property "%s" not numeric'%key + raise TypeError('new property "%s" not numeric'%key) elif value is not None and isinstance(prop, hyperdb.Boolean): try: int(value) except ValueError: - raise TypeError, 'new property "%s" not boolean'%key + raise TypeError('new property "%s" not boolean'%key) # make sure there's data where there needs to be - for key, prop in self.properties.items(): - if propvalues.has_key(key): + for key, prop in self.properties.iteritems(): + if key in propvalues: continue if key == self.key: - raise ValueError, 'key property "%s" is required'%key + raise ValueError('key property "%s" is required'%key) if isinstance(prop, hyperdb.Multilink): propvalues[key] = [] @@ -946,10 +935,10 @@ # check for one of the special props if propname == 'creation': - if d.has_key('creation'): + if 'creation' in d: return d['creation'] if not self.do_journal: - raise ValueError, 'Journalling is disabled for this class' + raise ValueError('Journalling is disabled for this class') journal = self.db.getjournal(self.classname, nodeid) if journal: return journal[0][1] @@ -957,10 +946,10 @@ # on the strange chance that there's no journal return date.Date() if propname == 'activity': - if d.has_key('activity'): + if 'activity' in d: return d['activity'] if not self.do_journal: - raise ValueError, 'Journalling is disabled for this class' + raise ValueError('Journalling is disabled for this class') journal = self.db.getjournal(self.classname, nodeid) if journal: return self.db.getjournal(self.classname, nodeid)[-1][1] @@ -968,10 +957,10 @@ # on the strange chance that there's no journal return date.Date() if propname == 'creator': - if d.has_key('creator'): + if 'creator' in d: return d['creator'] if not self.do_journal: - raise ValueError, 'Journalling is disabled for this class' + raise ValueError('Journalling is disabled for this class') journal = self.db.getjournal(self.classname, nodeid) if journal: num_re = re.compile('^\d+$') @@ -988,10 +977,10 @@ else: return self.db.getuid() if propname == 'actor': - if d.has_key('actor'): + if 'actor' in d: return d['actor'] if not self.do_journal: - raise ValueError, 'Journalling is disabled for this class' + raise ValueError('Journalling is disabled for this class') journal = self.db.getjournal(self.classname, nodeid) if journal: num_re = re.compile('^\d+$') @@ -1011,7 +1000,7 @@ # get the property (raises KeyErorr if invalid) prop = self.properties[propname] - if not d.has_key(propname): + if propname not in d: if default is _marker: if isinstance(prop, hyperdb.Multilink): return [] @@ -1048,12 +1037,12 @@ to modify the "creation" or "activity" properties cause a KeyError. """ if self.db.journaltag is None: - raise hyperdb.DatabaseError, _('Database open read-only') + raise hyperdb.DatabaseError(_('Database open read-only')) self.fireAuditors('set', nodeid, propvalues) oldvalues = copy.deepcopy(self.db.getnode(self.classname, nodeid)) - for name,prop in self.getprops(protected=0).items(): - if oldvalues.has_key(name): + for name, prop in self.getprops(protected=0).iteritems(): + if name in oldvalues: continue if isinstance(prop, hyperdb.Multilink): oldvalues[name] = [] @@ -1069,24 +1058,25 @@ if not propvalues: return propvalues - if propvalues.has_key('creation') or propvalues.has_key('activity'): + if 'creation' in propvalues or 'activity' in propvalues: raise KeyError, '"creation" and "activity" are reserved' - if propvalues.has_key('id'): + if 'id' in propvalues: raise KeyError, '"id" is reserved' if self.db.journaltag is None: - raise hyperdb.DatabaseError, _('Database open read-only') + raise hyperdb.DatabaseError(_('Database open read-only')) node = self.db.getnode(self.classname, nodeid) - if node.has_key(self.db.RETIRED_FLAG): + if self.db.RETIRED_FLAG in node: raise IndexError num_re = re.compile('^\d+$') # if the journal value is to be different, store it in here journalvalues = {} - for propname, value in propvalues.items(): + # list() propvalues 'cos it might be modified by the loop + for propname, value in list(propvalues.items()): # check to make sure we're not duplicating an existing key if propname == self.key and node[propname] != value: try: @@ -1094,7 +1084,7 @@ except KeyError: pass else: - raise ValueError, 'node with key "%s" exists'%value + raise ValueError('node with key "%s" exists'%value) # this will raise the KeyError if the property isn't valid # ... we don't use getprops() here because we only care about @@ -1102,8 +1092,8 @@ try: prop = self.properties[propname] except KeyError: - raise KeyError, '"%s" has no property named "%s"'%( - self.classname, propname) + raise KeyError('"%s" has no property named "%s"'%( + self.classname, propname)) # if the value's the same as the existing value, no sense in # doing anything @@ -1118,22 +1108,23 @@ link_class = prop.classname # if it isn't a number, it's a key if value is not None and not isinstance(value, type('')): - raise ValueError, 'property "%s" link value be a string'%( - propname) + raise ValueError('property "%s" link value be a string'%( + propname)) if isinstance(value, type('')) and not num_re.match(value): try: value = self.db.classes[link_class].lookup(value) except (TypeError, KeyError): - raise IndexError, 'new property "%s": %s not a %s'%( - propname, value, prop.classname) + raise IndexError('new property "%s": %s not a %s'%( + propname, value, prop.classname)) if (value is not None and not self.db.getclass(link_class).hasnode(value)): - raise IndexError, '%s has no node %s'%(link_class, value) + raise IndexError('%s has no node %s'%(link_class, + value)) if self.do_journal and prop.do_journal: # register the unlink with the old linked node - if node.has_key(propname) and node[propname] is not None: + if propname in node and node[propname] is not None: self.db.addjournal(link_class, node[propname], 'unlink', (self.classname, nodeid, propname)) @@ -1146,22 +1137,22 @@ if value is None: value = [] if not hasattr(value, '__iter__'): - raise TypeError, 'new property "%s" not an iterable of'\ - ' ids'%propname + raise TypeError('new property "%s" not an iterable of' + ' ids'%propname) link_class = self.properties[propname].classname l = [] for entry in value: # if it isn't a number, it's a key if type(entry) != type(''): - raise ValueError, 'new property "%s" link value ' \ - 'must be a string'%propname + raise ValueError('new property "%s" link value ' + 'must be a string'%propname) if not num_re.match(entry): try: entry = self.db.classes[link_class].lookup(entry) except (TypeError, KeyError): - raise IndexError, 'new property "%s": %s not a %s'%( + raise IndexError('new property "%s": %s not a %s'%( propname, entry, - self.properties[propname].classname) + self.properties[propname].classname)) l.append(entry) value = l propvalues[propname] = value @@ -1171,7 +1162,7 @@ remove = [] # handle removals - if node.has_key(propname): + if propname in node: l = node[propname] else: l = [] @@ -1188,7 +1179,8 @@ # handle additions for id in value: if not self.db.getclass(link_class).hasnode(id): - raise IndexError, '%s has no node %s'%(link_class, id) + raise IndexError('%s has no node %s'%(link_class, + id)) if id in l: continue # register the link with the newly linked node @@ -1209,38 +1201,43 @@ elif isinstance(prop, hyperdb.String): if value is not None and type(value) != type('') and type(value) != type(u''): - raise TypeError, 'new property "%s" not a string'%propname + raise TypeError('new property "%s" not a ' + 'string'%propname) if prop.indexme: self.db.indexer.add_text((self.classname, nodeid, propname), value) elif isinstance(prop, hyperdb.Password): if not isinstance(value, password.Password): - raise TypeError, 'new property "%s" not a Password'%propname + raise TypeError('new property "%s" not a ' + 'Password'%propname) propvalues[propname] = value elif value is not None and isinstance(prop, hyperdb.Date): if not isinstance(value, date.Date): - raise TypeError, 'new property "%s" not a Date'% propname + raise TypeError('new property "%s" not a ' + 'Date'%propname) propvalues[propname] = value elif value is not None and isinstance(prop, hyperdb.Interval): if not isinstance(value, date.Interval): - raise TypeError, 'new property "%s" not an '\ - 'Interval'%propname + raise TypeError('new property "%s" not an ' + 'Interval'%propname) propvalues[propname] = value elif value is not None and isinstance(prop, hyperdb.Number): try: float(value) except ValueError: - raise TypeError, 'new property "%s" not numeric'%propname + raise TypeError('new property "%s" not ' + 'numeric'%propname) elif value is not None and isinstance(prop, hyperdb.Boolean): try: int(value) except ValueError: - raise TypeError, 'new property "%s" not boolean'%propname + raise TypeError('new property "%s" not ' + 'boolean'%propname) node[propname] = value @@ -1273,7 +1270,7 @@ to modify the "creation" or "activity" properties cause a KeyError. """ if self.db.journaltag is None: - raise hyperdb.DatabaseError, _('Database open read-only') + raise hyperdb.DatabaseError(_('Database open read-only')) self.fireAuditors('retire', nodeid, None) @@ -1291,7 +1288,7 @@ Make node available for all operations like it was before retirement. """ if self.db.journaltag is None: - raise hyperdb.DatabaseError, _('Database open read-only') + raise hyperdb.DatabaseError(_('Database open read-only')) node = self.db.getnode(self.classname, nodeid) # check if key property was overrided @@ -1301,8 +1298,8 @@ except KeyError: pass else: - raise KeyError, "Key property (%s) of retired node clashes with \ - existing one (%s)" % (key, node[key]) + raise KeyError("Key property (%s) of retired node clashes " + "with existing one (%s)" % (key, node[key])) # Now we can safely restore node self.fireAuditors('restore', nodeid, None) del node[self.db.RETIRED_FLAG] @@ -1316,7 +1313,7 @@ """Return true if the node is retired. """ node = self.db.getnode(self.classname, nodeid, cldb) - if node.has_key(self.db.RETIRED_FLAG): + if self.db.RETIRED_FLAG in node: return 1 return 0 @@ -1337,7 +1334,7 @@ support the session storage of the cgi interface. """ if self.db.journaltag is None: - raise hyperdb.DatabaseError, _('Database open read-only') + raise hyperdb.DatabaseError(_('Database open read-only')) self.db.destroynode(self.classname, nodeid) def history(self, nodeid): @@ -1354,7 +1351,7 @@ 'tag' is the journaltag specified when the database was opened. """ if not self.do_journal: - raise ValueError, 'Journalling is disabled for this class' + raise ValueError('Journalling is disabled for this class') return self.db.getjournal(self.classname, nodeid) # Locating nodes: @@ -1373,7 +1370,7 @@ """ prop = self.getprops()[propname] if not isinstance(prop, hyperdb.String): - raise TypeError, 'key properties must be String' + raise TypeError('key properties must be String') self.key = propname def getkey(self): @@ -1390,21 +1387,22 @@ otherwise a KeyError is raised. """ if not self.key: - raise TypeError, 'No key property set for class %s'%self.classname + raise TypeError('No key property set for ' + 'class %s'%self.classname) cldb = self.db.getclassdb(self.classname) try: for nodeid in self.getnodeids(cldb): node = self.db.getnode(self.classname, nodeid, cldb) - if node.has_key(self.db.RETIRED_FLAG): + if self.db.RETIRED_FLAG in node: continue - if not node.has_key(self.key): + if self.key not in node: continue if node[self.key] == keyvalue: return nodeid finally: cldb.close() - raise KeyError, 'No key (%s) value "%s" for "%s"'%(self.key, - keyvalue, self.classname) + raise KeyError('No key (%s) value "%s" for "%s"'%(self.key, + keyvalue, self.classname)) # change from spec - allows multiple props to match def find(self, **propspec): @@ -1422,12 +1420,12 @@ db.issue.find(messages='1') db.issue.find(messages={'1':1,'3':1}, files={'7':1}) """ - propspec = propspec.items() - for propname, itemids in propspec: + for propname, itemids in propspec.iteritems(): # check the prop is OK prop = self.properties[propname] if not isinstance(prop, hyperdb.Link) and not isinstance(prop, hyperdb.Multilink): - raise TypeError, "'%s' not a Link/Multilink property"%propname + raise TypeError("'%s' not a Link/Multilink " + "property"%propname) # ok, now do the find cldb = self.db.getclassdb(self.classname) @@ -1435,15 +1433,15 @@ try: for id in self.getnodeids(db=cldb): item = self.db.getnode(self.classname, id, db=cldb) - if item.has_key(self.db.RETIRED_FLAG): + if self.db.RETIRED_FLAG in item: continue - for propname, itemids in propspec: + for propname, itemids in propspec.iteritems(): if type(itemids) is not type({}): itemids = {itemids:1} # special case if the item doesn't have this property - if not item.has_key(propname): - if itemids.has_key(None): + if propname not in item: + if None in itemids: l.append(id) break continue @@ -1451,13 +1449,13 @@ # grab the property definition and its value on this item prop = self.properties[propname] value = item[propname] - if isinstance(prop, hyperdb.Link) and itemids.has_key(value): + if isinstance(prop, hyperdb.Link) and value in itemids: l.append(id) break elif isinstance(prop, hyperdb.Multilink): hit = 0 for v in value: - if itemids.has_key(v): + if v in itemids: l.append(id) hit = 1 break @@ -1475,20 +1473,20 @@ The return is a list of the id of all nodes that match. """ - for propname in requirements.keys(): + for propname in requirements: prop = self.properties[propname] if not isinstance(prop, hyperdb.String): - raise TypeError, "'%s' not a String property"%propname + raise TypeError("'%s' not a String property"%propname) requirements[propname] = requirements[propname].lower() l = [] cldb = self.db.getclassdb(self.classname) try: for nodeid in self.getnodeids(cldb): node = self.db.getnode(self.classname, nodeid, cldb) - if node.has_key(self.db.RETIRED_FLAG): + if self.db.RETIRED_FLAG in node: continue - for key, value in requirements.items(): - if not node.has_key(key): + for key, value in requirements.iteritems(): + if key not in node: break if node[key] is None or node[key].lower() != value: break @@ -1507,7 +1505,7 @@ try: for nodeid in self.getnodeids(cldb): node = self.db.getnode(cn, nodeid, cldb) - if node.has_key(self.db.RETIRED_FLAG): + if self.db.RETIRED_FLAG in node: continue l.append(nodeid) finally: @@ -1524,20 +1522,20 @@ res = [] # start off with the new nodes - if self.db.newnodes.has_key(self.classname): - res += self.db.newnodes[self.classname].keys() + if self.classname in self.db.newnodes: + res.extend(self.db.newnodes[self.classname]) must_close = False if db is None: db = self.db.getclassdb(self.classname) must_close = True try: - res = res + db.keys() + res.extend(db) # remove the uncommitted, destroyed nodes - if self.db.destroyednodes.has_key(self.classname): - for nodeid in self.db.destroyednodes[self.classname].keys(): - if db.has_key(nodeid): + if self.classname in self.db.destroyednodes: + for nodeid in self.db.destroyednodes[self.classname]: + if nodeid in db: res.remove(nodeid) # check retired flag @@ -1545,7 +1543,7 @@ l = [] for nodeid in res: node = self.db.getnode(self.classname, nodeid, db) - is_ret = node.has_key(self.db.RETIRED_FLAG) + is_ret = self.db.RETIRED_FLAG in node if retired == is_ret: l.append(nodeid) res = l @@ -1588,7 +1586,7 @@ INTERVAL = 'spec:interval' OTHER = 'spec:other' - for k, v in filterspec.items(): + for k, v in filterspec.iteritems(): propclass = props[k] if isinstance(propclass, hyperdb.Link): if type(v) is not type([]): @@ -1662,7 +1660,7 @@ # TODO: only full-scan once (use items()) for nodeid in self.getnodeids(cldb): node = self.db.getnode(cn, nodeid, cldb) - if node.has_key(self.db.RETIRED_FLAG): + if self.db.RETIRED_FLAG in node: continue # apply filter for t, k, v in filterspec: @@ -1758,7 +1756,7 @@ try: v = item[prop] except KeyError: - if JPROPS.has_key(prop): + if prop in JPROPS: # force lookup of the special journal prop v = self.get(itemid, prop) else: @@ -1787,7 +1785,7 @@ key = link.orderprop() child = pt.propdict[key] if key!='id': - if not lcache.has_key(v): + if v not in lcache: # open the link class db if it's not already if lcldb is None: lcldb = self.db.getclassdb(lcn) @@ -1852,15 +1850,15 @@ may collide with the names of existing properties, or a ValueError is raised before any properties have been added. """ - for key in properties.keys(): - if self.properties.has_key(key): - raise ValueError, key + for key in properties: + if key in self.properties: + raise ValueError(key) self.properties.update(properties) def index(self, nodeid): """ Add (or refresh) the node to search indexes """ # find all the String properties that have indexme - for prop, propclass in self.getprops().items(): + for prop, propclass in self.getprops().iteritems(): if isinstance(propclass, hyperdb.String) and propclass.indexme: # index them under (classname, nodeid, property) try: @@ -1907,7 +1905,7 @@ Return the nodeid of the node imported. """ if self.db.journaltag is None: - raise hyperdb.DatabaseError, _('Database open read-only') + raise hyperdb.DatabaseError(_('Database open read-only')) properties = self.getprops() # make the new node's property map @@ -1967,8 +1965,8 @@ date = date.get_tuple() if action == 'set': export_data = {} - for propname, value in params.items(): - if not properties.has_key(propname): + for propname, value in params.iteritems(): + if propname not in properties: # property no longer in the schema continue @@ -1988,8 +1986,8 @@ value = str(value) export_data[propname] = value params = export_data - l = [nodeid, date, user, action, params] - r.append(map(repr, l)) + r.append([repr(nodeid), repr(date), repr(user), + repr(action), repr(params)]) return r def import_journals(self, entries): @@ -1999,11 +1997,10 @@ properties = self.getprops() d = {} for l in entries: - l = map(eval, l) - nodeid, jdate, user, action, params = l + nodeid, jdate, user, action, params = tuple(map(eval, l)) r = d.setdefault(nodeid, []) if action == 'set': - for propname, value in params.items(): + for propname, value in params.iteritems(): prop = properties[propname] if value is None: pass @@ -2018,7 +2015,7 @@ params[propname] = value r.append((nodeid, date.Date(jdate), user, action, params)) - for nodeid, l in d.items(): + for nodeid, l in d.iteritems(): self.db.setjournal(self.classname, nodeid, l) class FileClass(hyperdb.FileClass, Class): @@ -2034,9 +2031,9 @@ """The newly-created class automatically includes the "content" and "type" properties. """ - if not properties.has_key('content'): + if 'content' not in properties: properties['content'] = hyperdb.String(indexme='yes') - if not properties.has_key('type'): + if 'type' not in properties: properties['type'] = hyperdb.String() Class.__init__(self, db, classname, **properties) @@ -2074,7 +2071,7 @@ if propname == 'content': try: return self.db.getfile(self.classname, nodeid, None) - except IOError, (strerror): + except IOError, strerror: # XXX by catching this we don't see an error in the log. return 'ERROR reading file: %s%s\n%s\n%s'%( self.classname, nodeid, poss_msg, strerror) @@ -2090,8 +2087,8 @@ # create the oldvalues dict - fill in any missing values oldvalues = copy.deepcopy(self.db.getnode(self.classname, itemid)) - for name,prop in self.getprops(protected=0).items(): - if oldvalues.has_key(name): + for name, prop in self.getprops(protected=0).iteritems(): + if name in oldvalues: continue if isinstance(prop, hyperdb.Multilink): oldvalues[name] = [] @@ -2100,7 +2097,7 @@ # now remove the content property so it's not stored in the db content = None - if propvalues.has_key('content'): + if 'content' in propvalues: content = propvalues['content'] del propvalues['content'] @@ -2127,7 +2124,7 @@ Use the content-type property for the content property. """ # find all the String properties that have indexme - for prop, propclass in self.getprops().items(): + for prop, propclass in self.getprops().iteritems(): if prop == 'content' and propclass.indexme: mime_type = self.get(nodeid, 'type', self.default_mime_type) self.db.indexer.add_text((self.classname, nodeid, 'content'), @@ -2150,17 +2147,17 @@ dictionary attempts to specify any of these properties or a "creation" or "activity" property, a ValueError is raised. """ - if not properties.has_key('title'): + if 'title' not in properties: properties['title'] = hyperdb.String(indexme='yes') - if not properties.has_key('messages'): + if 'messages' not in properties: properties['messages'] = hyperdb.Multilink("msg") - if not properties.has_key('files'): + if 'files' not in properties: properties['files'] = hyperdb.Multilink("file") - if not properties.has_key('nosy'): + if 'nosy' not in properties: # note: journalling is turned off as it really just wastes # space. this behaviour may be overridden in an instance properties['nosy'] = hyperdb.Multilink("user", do_journal="no") - if not properties.has_key('superseder'): + if 'superseder' not in properties: properties['superseder'] = hyperdb.Multilink(classname) Class.__init__(self, db, classname, **properties)
