From: richard Date: Fri, 26 Feb 2010 00:38:53 +0000 (+0000) Subject: more modernisation X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=e6e1758683add8dcfeb6e9772bfd87aa28a02288;p=roundup.git more modernisation git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/roundup/trunk@4468 57a73879-2fb5-44c3-a270-3262357dd7e2 --- diff --git a/2to3-done.txt b/2to3-done.txt index b9cac19..5aeb5fa 100644 --- a/2to3-done.txt +++ b/2to3-done.txt @@ -2,19 +2,9 @@ CAN'T VERIFY ./roundup/backends/back_mysql.py ./roundup/backends/back_tsearch2.py -./roundup/backends/indexer_xapian.py TODO -./roundup/backends/sessions_dbm.py -./roundup/backends/sessions_rdbms.py -./roundup/backends/tsearch2_setup.py -./roundup/cgi/__init__.py -./roundup/cgi/accept_language.py -./roundup/cgi/actions.py -./roundup/cgi/apache.py -./roundup/cgi/cgitb.py -./roundup/cgi/client.py ./roundup/cgi/exceptions.py ./roundup/cgi/form_parser.py ./roundup/cgi/MultiMapping.py @@ -133,24 +123,37 @@ TODO ./frontends/ZRoundup/ZRoundup.py - DONE ./doc/conf.py -./roundup/__init__.py ./roundup/admin.py -./roundup/actions.py -./roundup/anypy/__init__.py -./roundup/anypy/hashlib_.py -./roundup/anypy/sets_.py ./roundup/backends/__init__.py ./roundup/backends/back_anydbm.py ./roundup/backends/back_postgresql.py ./roundup/backends/back_sqlite.py -./roundup/backends/blobfiles.py ./roundup/backends/indexer_common.py ./roundup/backends/indexer_dbm.py ./roundup/backends/indexer_rdbms.py ./roundup/backends/locking.py ./roundup/backends/portalocker.py ./roundup/backends/rdbms_common.py +./roundup/backends/sessions_dbm.py +./roundup/backends/sessions_rdbms.py +./roundup/cgi/accept_language.py +./roundup/cgi/actions.py +./roundup/cgi/cgitb.py + + +NOTHING DONE + +./roundup/__init__.py +./roundup/actions.py +./roundup/anypy/__init__.py +./roundup/anypy/hashlib_.py +./roundup/anypy/sets_.py +./roundup/backends/blobfiles.py +./roundup/backends/indexer_xapian.py +./roundup/backends/tsearch2_setup.py +./roundup/cgi/__init__.py +./roundup/cgi/apache.py +./roundup/cgi/client.py diff --git a/roundup/anypy/cookie_.py b/roundup/anypy/cookie_.py new file mode 100644 index 0000000..44bf93a --- /dev/null +++ b/roundup/anypy/cookie_.py @@ -0,0 +1,8 @@ + +try: + from http import cookies as Cookie + from http.cookies import CookieError, BaseCookie, SimpleCookie + from http.cookies import _getdate as get_cookie_date +except: + from Cookie import CookieError, BaseCookie, SimpleCookie + from Cookie import _getdate as get_cookie_date diff --git a/roundup/anypy/http_.py b/roundup/anypy/http_.py new file mode 100644 index 0000000..a7f5238 --- /dev/null +++ b/roundup/anypy/http_.py @@ -0,0 +1,5 @@ +try: + from http import client +except: + import httplib as client + diff --git a/roundup/anypy/io_.py b/roundup/anypy/io_.py new file mode 100644 index 0000000..86f8023 --- /dev/null +++ b/roundup/anypy/io_.py @@ -0,0 +1,6 @@ + +try: + from io import StringIO +except: + from StringIO import StringIO + diff --git a/roundup/anypy/urllib_.py b/roundup/anypy/urllib_.py new file mode 100644 index 0000000..d1a8a4b --- /dev/null +++ b/roundup/anypy/urllib_.py @@ -0,0 +1,6 @@ + +try: + from urllib.parse import quote, urlparse +except: + from urllib import quote + from urlparse import urlparse diff --git a/roundup/backends/indexer_dbm.py b/roundup/backends/indexer_dbm.py index 0b8562c..11ed64f 100644 --- a/roundup/backends/indexer_dbm.py +++ b/roundup/backends/indexer_dbm.py @@ -168,7 +168,7 @@ class Indexer(IndexerBase): hits[k] = self.fileids[k] else: # Eliminate hits for every non-match - for fileid in hits: + for fileid in list(hits): if fileid not in entry: del hits[fileid] if hits is None: diff --git a/roundup/backends/sessions_dbm.py b/roundup/backends/sessions_dbm.py index 1087967..27b6c52 100644 --- a/roundup/backends/sessions_dbm.py +++ b/roundup/backends/sessions_dbm.py @@ -7,9 +7,11 @@ class. It's now also used for One Time Key handling too. """ __docformat__ = 'restructuredtext' -import anydbm, whichdb, os, marshal, time +import os, marshal, time + from roundup import hyperdb from roundup.i18n import _ +from roundup.anypy.dbm_ import anydbm, whichdb class BasicDatabase: ''' Provide a nice encapsulation of an anydbm store. @@ -26,7 +28,7 @@ class BasicDatabase: def exists(self, infoid): db = self.opendb('c') try: - return db.has_key(infoid) + return infoid in db finally: db.close() @@ -46,8 +48,8 @@ class BasicDatabase: if os.path.exists(path): db_type = whichdb.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! @@ -58,12 +60,12 @@ class BasicDatabase: def get(self, infoid, value, default=_marker): db = self.opendb('c') try: - if db.has_key(infoid): + if infoid in db: values = marshal.loads(db[infoid]) else: if default != self._marker: return default - raise KeyError, 'No such %s "%s"'%(self.name, infoid) + raise KeyError('No such %s "%s"'%(self.name, infoid)) return values.get(value, None) finally: db.close() @@ -76,14 +78,14 @@ class BasicDatabase: del d['__timestamp'] return d except KeyError: - raise KeyError, 'No such %s "%s"'%(self.name, infoid) + raise KeyError('No such %s "%s"'%(self.name, infoid)) finally: db.close() def set(self, infoid, **newvalues): db = self.opendb('c') try: - if db.has_key(infoid): + if infoid in db: values = marshal.loads(db[infoid]) else: values = {'__timestamp': time.time()} @@ -95,14 +97,14 @@ class BasicDatabase: def list(self): db = self.opendb('r') try: - return db.keys() + return list(db) finally: db.close() def destroy(self, infoid): db = self.opendb('c') try: - if db.has_key(infoid): + if infoid in db: del db[infoid] finally: db.close() diff --git a/roundup/backends/sessions_rdbms.py b/roundup/backends/sessions_rdbms.py index 4370252..c5dc189 100644 --- a/roundup/backends/sessions_rdbms.py +++ b/roundup/backends/sessions_rdbms.py @@ -36,7 +36,7 @@ class BasicDatabase: if not res: if default != self._marker: return default - raise KeyError, 'No such %s "%s"'%(self.name, infoid) + raise KeyError('No such %s "%s"'%(self.name, infoid)) values = eval(res[0]) return values.get(value, None) @@ -46,7 +46,7 @@ class BasicDatabase: n, n, self.db.arg), (infoid,)) res = self.cursor.fetchone() if not res: - raise KeyError, 'No such %s "%s"'%(self.name, infoid) + raise KeyError('No such %s "%s"'%(self.name, infoid)) return eval(res[0]) def set(self, infoid, **newvalues): diff --git a/roundup/cgi/accept_language.py b/roundup/cgi/accept_language.py index d3d7328..09c06cf 100755 --- a/roundup/cgi/accept_language.py +++ b/roundup/cgi/accept_language.py @@ -35,7 +35,7 @@ qlre = "([A-Za-z]+[-[A-Za-z]+]*);q=([\d\.]+)" # both lre = re.compile(nqlre + "|" + qlre) -ascii = ''.join([chr(x) for x in xrange(256)]) +ascii = ''.join([chr(x) for x in range(256)]) whitespace = ' \t\n\r\v\f' def parse(language_header): diff --git a/roundup/cgi/actions.py b/roundup/cgi/actions.py index dd86a84..e3de0de 100755 --- a/roundup/cgi/actions.py +++ b/roundup/cgi/actions.py @@ -1,4 +1,4 @@ -import re, cgi, StringIO, urllib, time, random, csv, codecs +import re, cgi, time, random, csv, codecs from roundup import hyperdb, token, date, password from roundup.actions import Action as BaseAction @@ -6,6 +6,7 @@ from roundup.i18n import _ import roundup.exceptions from roundup.cgi import exceptions, templating from roundup.mailgw import uidFromAddress +from roundup.anypy import io_, urllib_ __all__ = ['Action', 'ShowAction', 'RetireAction', 'SearchAction', 'EditCSVAction', 'EditItemAction', 'PassResetAction', @@ -53,9 +54,9 @@ class Action: if (self.permissionType and not self.hasPermission(self.permissionType)): info = {'action': self.name, 'classname': self.classname} - raise exceptions.Unauthorised, self._( + raise exceptions.Unauthorised(self._( 'You do not have permission to ' - '%(action)s the %(classname)s class.')%info + '%(action)s the %(classname)s class.')%info) _marker = [] def hasPermission(self, permission, classname=_marker, itemid=None, property=None): @@ -79,23 +80,23 @@ class ShowAction(Action): def handle(self): """Show a node of a particular class/id.""" t = n = '' - for key in self.form.keys(): + for key in self.form: if self.typere.match(key): t = self.form[key].value.strip() elif self.numre.match(key): n = self.form[key].value.strip() if not t: - raise ValueError, self._('No type specified') + raise ValueError(self._('No type specified')) if not n: - raise exceptions.SeriousError, self._('No ID entered') + raise exceptions.SeriousError(self._('No ID entered')) try: int(n) except ValueError: d = {'input': n, 'classname': t} - raise exceptions.SeriousError, self._( - '"%(input)s" is not an ID (%(classname)s ID required)')%d + raise exceptions.SeriousError(self._( + '"%(input)s" is not an ID (%(classname)s ID required)')%d) url = '%s%s%s'%(self.base, t, n) - raise exceptions.Redirect, url + raise exceptions.Redirect(url) class RetireAction(Action): name = 'retire' @@ -116,15 +117,15 @@ class RetireAction(Action): # make sure we don't try to retire admin or anonymous if self.classname == 'user' and \ self.db.user.get(itemid, 'username') in ('admin', 'anonymous'): - raise ValueError, self._( - 'You may not retire the admin or anonymous user') + raise ValueError(self._( + 'You may not retire the admin or anonymous user')) # check permission if not self.hasPermission('Retire', classname=self.classname, itemid=itemid): - raise exceptions.Unauthorised, self._( + raise exceptions.Unauthorised(self._( 'You do not have permission to retire %(class)s' - ) % {'class': self.classname} + ) % {'class': self.classname}) # do the retire self.db.getclass(self.classname).retire(itemid) @@ -171,14 +172,14 @@ class SearchAction(Action): try: qid = self.db.query.lookup(old_queryname) if not self.hasPermission('Edit', 'query', itemid=qid): - raise exceptions.Unauthorised, self._( - "You do not have permission to edit queries") + raise exceptions.Unauthorised(self._( + "You do not have permission to edit queries")) self.db.query.set(qid, klass=self.classname, url=url) except KeyError: # create a query if not self.hasPermission('Create', 'query'): - raise exceptions.Unauthorised, self._( - "You do not have permission to store queries") + raise exceptions.Unauthorised(self._( + "You do not have permission to store queries")) qid = self.db.query.create(name=queryname, klass=self.classname, url=url) else: @@ -199,15 +200,15 @@ class SearchAction(Action): if old_queryname != self.db.query.get(qid, 'name'): continue if not self.hasPermission('Edit', 'query', itemid=qid): - raise exceptions.Unauthorised, self._( - "You do not have permission to edit queries") + raise exceptions.Unauthorised(self._( + "You do not have permission to edit queries")) self.db.query.set(qid, klass=self.classname, url=url, name=queryname) else: # create a query if not self.hasPermission('Create', 'query'): - raise exceptions.Unauthorised, self._( - "You do not have permission to store queries") + raise exceptions.Unauthorised(self._( + "You do not have permission to store queries")) qid = self.db.query.create(name=queryname, klass=self.classname, url=url, private_for=uid) @@ -223,7 +224,7 @@ class SearchAction(Action): def fakeFilterVars(self): """Add a faked :filter form variable for each filtering prop.""" cls = self.db.classes[self.classname] - for key in self.form.keys(): + for key in self.form: prop = cls.get_transitive_prop(key) if not prop: continue @@ -264,7 +265,7 @@ class SearchAction(Action): def getFromForm(self, name): for key in ('@' + name, ':' + name): - if self.form.has_key(key): + if key in self.form: return self.form[key].value.strip() return '' @@ -288,7 +289,7 @@ class EditCSVAction(Action): # figure the properties list for the class cl = self.db.classes[self.classname] - props_without_id = cl.getprops(protected=0).keys() + props_without_id = list(cl.getprops(protected=0)) # the incoming CSV data will always have the properties in colums # sorted and starting with the "id" column @@ -296,7 +297,7 @@ class EditCSVAction(Action): props = ['id'] + props_without_id # do the edit - rows = StringIO.StringIO(self.form['rows'].value) + rows = io_.StringIO(self.form['rows'].value) reader = csv.reader(rows) found = {} line = 0 @@ -317,9 +318,9 @@ class EditCSVAction(Action): # check permission to create this item if not self.hasPermission('Create', classname=self.classname): - raise exceptions.Unauthorised, self._( + raise exceptions.Unauthorised(self._( 'You do not have permission to create %(class)s' - ) % {'class': self.classname} + ) % {'class': self.classname}) elif cl.hasnode(itemid) and cl.is_retired(itemid): # If a CSV line just mentions an id and the corresponding # item is retired, then the item is restored. @@ -340,9 +341,9 @@ class EditCSVAction(Action): # check permission to edit this property on this item if exists and not self.hasPermission('Edit', itemid=itemid, classname=self.classname, property=name): - raise exceptions.Unauthorised, self._( + raise exceptions.Unauthorised(self._( 'You do not have permission to edit %(class)s' - ) % {'class': self.classname} + ) % {'class': self.classname}) prop = cl.properties[name] value = value.strip() @@ -379,13 +380,13 @@ class EditCSVAction(Action): # retire the removed entries for itemid in cl.list(): - if not found.has_key(itemid): + if itemid not in found: # check permission to retire this item if not self.hasPermission('Retire', itemid=itemid, classname=self.classname): - raise exceptions.Unauthorised, self._( + raise exceptions.Unauthorised(self._( 'You do not have permission to retire %(class)s' - ) % {'class': self.classname} + ) % {'class': self.classname}) cl.retire(itemid) # all OK @@ -405,12 +406,12 @@ class EditCommon(Action): links = {} for cn, nodeid, propname, vlist in all_links: numeric_id = int (nodeid or 0) - if not (numeric_id > 0 or all_props.has_key((cn, nodeid))): + if not (numeric_id > 0 or (cn, nodeid) in all_props): # link item to link to doesn't (and won't) exist continue for value in vlist: - if not all_props.has_key(value): + if value not in all_props: # link item to link to doesn't (and won't) exist continue deps.setdefault((cn, nodeid), []).append(value) @@ -422,19 +423,19 @@ class EditCommon(Action): # loop detection change = 0 while len(all_props) != len(done): - for needed in all_props.keys(): - if done.has_key(needed): + for needed in all_props: + if needed in done: continue tlist = deps.get(needed, []) for target in tlist: - if not done.has_key(target): + if target not in done: break else: done[needed] = 1 order.append(needed) change = 1 if not change: - raise ValueError, 'linking must not loop!' + raise ValueError('linking must not loop!') # now, edit / create m = [] @@ -448,7 +449,7 @@ class EditCommon(Action): # and some nice feedback for the user if props: - info = ', '.join(map(self._, props.keys())) + info = ', '.join(map(self._, props)) m.append( self._('%(class)s %(id)s %(properties)s edited ok') % {'class':cn, 'id':nodeid, 'properties':info}) @@ -469,12 +470,12 @@ class EditCommon(Action): % {'class':cn, 'id':newid}) # fill in new ids in links - if links.has_key(needed): + if needed in links: for linkcn, linkid, linkprop in links[needed]: props = all_props[(linkcn, linkid)] cl = self.db.classes[linkcn] propdef = cl.getprops()[linkprop] - if not props.has_key(linkprop): + if linkprop not in props: if linkid is None or linkid.startswith('-'): # linking to a new item if isinstance(propdef, hyperdb.Multilink): @@ -496,9 +497,9 @@ class EditCommon(Action): """Change the node based on the contents of the form.""" # check for permission if not self.editItemPermission(props, classname=cn, itemid=nodeid): - raise exceptions.Unauthorised, self._( + raise exceptions.Unauthorised(self._( 'You do not have permission to edit %(class)s' - ) % {'class': cn} + ) % {'class': cn}) # make the changes cl = self.db.classes[cn] @@ -508,9 +509,9 @@ class EditCommon(Action): """Create a node based on the contents of the form.""" # check for permission if not self.newItemPermission(props, classname=cn): - raise exceptions.Unauthorised, self._( + raise exceptions.Unauthorised(self._( 'You do not have permission to create %(class)s' - ) % {'class': cn} + ) % {'class': cn}) # create the node and return its id cl = self.db.classes[cn] @@ -561,9 +562,9 @@ class EditCommon(Action): class EditItemAction(EditCommon): def lastUserActivity(self): - if self.form.has_key(':lastactivity'): + if ':lastactivity' in self.form: d = date.Date(self.form[':lastactivity'].value) - elif self.form.has_key('@lastactivity'): + elif '@lastactivity' in self.form: d = date.Date(self.form['@lastactivity'].value) else: return None @@ -583,7 +584,7 @@ class EditItemAction(EditCommon): props, links = self.client.parsePropsFromForm() key = (self.classname, self.nodeid) # we really only collide for direct prop edit conflicts - return props[key].keys() + return list(props[key]) else: return [] @@ -633,12 +634,12 @@ class EditItemAction(EditCommon): # we will want to include index-page args in this URL too if self.nodeid is not None: url += self.nodeid - url += '?@ok_message=%s&@template=%s'%(urllib.quote(message), - urllib.quote(self.template)) + url += '?@ok_message=%s&@template=%s'%(urllib_.quote(message), + urllib_.quote(self.template)) if self.nodeid is None: req = templating.HTMLRequest(self.client) url += '&' + req.indexargs_url('', {})[1:] - raise exceptions.Redirect, url + raise exceptions.Redirect(url) class NewItemAction(EditCommon): def handle(self): @@ -673,9 +674,9 @@ class NewItemAction(EditCommon): self.db.commit() # redirect to the new item's page - raise exceptions.Redirect, '%s%s%s?@ok_message=%s&@template=%s' % ( - self.base, self.classname, self.nodeid, urllib.quote(messages), - urllib.quote(self.template)) + raise exceptions.Redirect('%s%s%s?@ok_message=%s&@template=%s' % ( + self.base, self.classname, self.nodeid, urllib_.quote(messages), + urllib_.quote(self.template))) class PassResetAction(Action): def handle(self): @@ -686,7 +687,7 @@ class PassResetAction(Action): """ otks = self.db.getOTKManager() - if self.form.has_key('otk'): + if 'otk' in self.form: # pull the rego information out of the otk database otk = self.form['otk'].value uid = otks.get(otk, 'uid', default=None) @@ -738,7 +739,7 @@ Your password is now: %(password)s return # no OTK, so now figure the user - if self.form.has_key('username'): + if 'username' in self.form: name = self.form['username'].value try: uid = self.db.user.lookup(name) @@ -746,7 +747,7 @@ Your password is now: %(password)s self.client.error_message.append(self._('Unknown username')) return address = self.db.user.get(uid, 'address') - elif self.form.has_key('address'): + elif 'address' in self.form: address = self.form['address'].value uid = uidFromAddress(self.db, ('', address), create=0) if not uid: @@ -797,7 +798,7 @@ class RegoCommon(Action): # nice message message = self._('You are now registered, welcome!') url = '%suser%s?@ok_message=%s'%(self.base, self.userid, - urllib.quote(message)) + urllib._quote(message)) # redirect to the user's page (but not 302, as some email clients seem # to want to reload the page, or something) @@ -865,7 +866,7 @@ class RegisterAction(RegoCommon, EditCommon): # generate the one-time-key and store the props for later user_props = props[('user', None)] - for propname, proptype in self.db.user.getprops().items(): + for propname, proptype in self.db.user.getprops().iteritems(): value = user_props.get(propname, None) if value is None: pass @@ -916,15 +917,15 @@ reply's additional "Re:" is ok), self.db.commit() # redirect to the "you're almost there" page - raise exceptions.Redirect, '%suser?@template=rego_progress'%self.base + raise exceptions.Redirect('%suser?@template=rego_progress'%self.base) def newItemPermission(self, props, classname=None): """Just check the "Register" permission. """ # registration isn't allowed to supply roles - if props.has_key('roles'): - raise exceptions.Unauthorised, self._( - "It is not permitted to supply roles at registration.") + if 'roles' in props: + raise exceptions.Unauthorised(self._( + "It is not permitted to supply roles at registration.")) # technically already checked, but here for clarity return self.hasPermission('Register', classname=classname) @@ -957,13 +958,13 @@ class LoginAction(Action): raise roundup.exceptions.Reject(self._('Invalid request')) # we need the username at a minimum - if not self.form.has_key('__login_name'): + if '__login_name' not in self.form: self.client.error_message.append(self._('Username required')) return # get the login info self.client.user = self.form['__login_name'].value - if self.form.has_key('__login_password'): + if '__login_password' in self.form: password = self.form['__login_password'].value else: password = '' @@ -980,29 +981,29 @@ class LoginAction(Action): # save user in session self.client.session_api.set(user=self.client.user) - if self.form.has_key('remember'): + if 'remember' in self.form: self.client.session_api.update(set_cookie=True, expire=24*3600*365) # If we came from someplace, go back there - if self.form.has_key('__came_from'): - raise exceptions.Redirect, self.form['__came_from'].value + if '__came_from' in self.form: + raise exceptions.Redirect(self.form['__came_from'].value) def verifyLogin(self, username, password): # make sure the user exists try: self.client.userid = self.db.user.lookup(username) except KeyError: - raise exceptions.LoginError, self._('Invalid login') + raise exceptions.LoginError(self._('Invalid login')) # verify the password if not self.verifyPassword(self.client.userid, password): - raise exceptions.LoginError, self._('Invalid login') + raise exceptions.LoginError(self._('Invalid login')) # Determine whether the user has permission to log in. # Base behaviour is to check the user has "Web Access". if not self.hasPermission("Web Access"): - raise exceptions.LoginError, self._( - "You do not have permission to login") + raise exceptions.LoginError(self._( + "You do not have permission to login")) def verifyPassword(self, userid, password): '''Verify the password that the user has supplied''' @@ -1060,9 +1061,9 @@ class ExportCSVAction(Action): # check permission to view this property on this item if not self.hasPermission('View', itemid=itemid, classname=request.classname, property=name): - raise exceptions.Unauthorised, self._( + raise exceptions.Unauthorised(self._( 'You do not have permission to view %(class)s' - ) % {'class': request.classname} + ) % {'class': request.classname}) row.append(str(klass.get(itemid, name))) self.client._socket_op(writer.writerow, row) @@ -1095,7 +1096,7 @@ class Bridge(BaseAction): def execute_cgi(self): args = {} - for key in self.form.keys(): + for key in self.form: args[key] = self.form.getvalue(key) self.permission(args) return self.handle(args) diff --git a/roundup/cgi/cgitb.py b/roundup/cgi/cgitb.py index b89cb46..d2b30a1 100644 --- a/roundup/cgi/cgitb.py +++ b/roundup/cgi/cgitb.py @@ -37,9 +37,7 @@ def breaker(): def niceDict(indent, dict): l = [] - keys = dict.keys() - keys.sort() - for k in keys: + for k in sorted(dict): v = dict[k] l.append('%s%s'%(k, cgi.escape(repr(v)))) @@ -59,7 +57,7 @@ def pt_html(context=5, i18n=None): t.reverse() for frame, file, lnum, func, lines, index in t: args, varargs, varkw, locals = inspect.getargvalues(frame) - if locals.has_key('__traceback_info__'): + if '__traceback_info__' in locals: ti = locals['__traceback_info__'] if isinstance(ti, TraversalError): s = [] @@ -72,7 +70,7 @@ def pt_html(context=5, i18n=None): ) % {'name': ti.name, 'path': s}) else: l.append(_('
  • In %s
  • ') % esc(str(ti))) - if locals.has_key('__traceback_supplement__'): + if '__traceback_supplement__' in locals: ts = locals['__traceback_supplement__'] if len(ts) == 2: supp, context = ts @@ -111,8 +109,8 @@ def pt_html(context=5, i18n=None): def html(context=5, i18n=None): _ = get_translator(i18n) - etype, evalue = sys.exc_type, sys.exc_value - if type(etype) is types.ClassType: + etype, evalue = sys.exc_info()[0], sys.exc_info()[1] + if type(etype) is type: etype = etype.__name__ pyver = 'Python ' + string.split(sys.version)[0] + '
    ' + sys.executable head = pydoc.html.heading( @@ -169,13 +167,13 @@ def html(context=5, i18n=None): lvals = [] for name in names: if name in frame.f_code.co_varnames: - if locals.has_key(name): + if name in locals: value = pydoc.html.repr(locals[name]) else: value = _('undefined') name = '%s' % name else: - if frame.f_globals.has_key(name): + if name in frame.f_globals: value = pydoc.html.repr(frame.f_globals[name]) else: value = _('undefined') diff --git a/roundup/cgi/client.py b/roundup/cgi/client.py index 3b10238..793a0d8 100644 --- a/roundup/cgi/client.py +++ b/roundup/cgi/client.py @@ -2,11 +2,9 @@ """ __docformat__ = 'restructuredtext' -import base64, binascii, cgi, codecs, httplib, mimetypes, os -import quopri, random, re, rfc822, stat, sys, time, urllib, urlparse -import Cookie, socket, errno -from Cookie import CookieError, BaseCookie, SimpleCookie -from cStringIO import StringIO +import base64, binascii, cgi, codecs, mimetypes, os +import quopri, random, re, rfc822, stat, sys, time +import socket, errno from roundup import roundupdb, date, hyperdb, password from roundup.cgi import templating, cgitb, TranslationService @@ -18,6 +16,12 @@ from roundup.mailer import Mailer, MessageSendError, encode_quopri from roundup.cgi import accept_language from roundup import xmlrpc +from roundup.anypy.cookie_ import CookieError, BaseCookie, SimpleCookie, \ + get_cookie_date +from roundup.anypy.io_ import StringIO +from roundup.anypy import http_ +from roundup.anypy import urllib_ + def initialiseSecurity(security): '''Create some Permissions and Roles on the security object @@ -43,7 +47,7 @@ def clean_message(message, mc=re.compile(CLEAN_MESSAGE_RE, re.I)): def clean_message_callback(match, ok={'a':1,'i':1,'b':1,'br':1}): """ Strip all non ,, and
    tags from a string """ - if ok.has_key(match.group(3).lower()): + if match.group(3).lower() in ok: return match.group(1) return '<%s>'%match.group(2) @@ -293,7 +297,7 @@ class Client: # this is the "cookie path" for this tracker (ie. the path part of # the "base" url) - self.cookie_path = urlparse.urlparse(self.base)[2] + self.cookie_path = urllib_.urlparse(self.base)[2] # cookies to set in http responce # {(path, name): (value, expire)} self._cookies = {} @@ -501,12 +505,12 @@ class Client: # authorization, send back a response that will cause the # browser to prompt the user again. if self.instance.config.WEB_HTTP_AUTH: - self.response_code = httplib.UNAUTHORIZED + self.response_code = http_.client.UNAUTHORIZED realm = self.instance.config.TRACKER_NAME self.setHeader("WWW-Authenticate", "Basic realm=\"%s\"" % realm) else: - self.response_code = httplib.FORBIDDEN + self.response_code = http_.client.FORBIDDEN self.renderFrontPage(message) except Unauthorised, message: # users may always see the front page @@ -526,15 +530,15 @@ class Client: # we can't map the URL to a class we know about # reraise the NotFound and let roundup_server # handle it - raise NotFound, e + raise NotFound(e) except FormError, e: self.error_message.append(self._('Form Error: ') + str(e)) self.write_html(self.renderContext()) except: # Something has gone badly wrong. Therefore, we should # make sure that the response code indicates failure. - if self.response_code == httplib.OK: - self.response_code = httplib.INTERNAL_SERVER_ERROR + if self.response_code == http_.client.OK: + self.response_code = http_.client.INTERNAL_SERVER_ERROR # Help the administrator work out what went wrong. html = ("

    Traceback

    " + cgitb.html(i18n=self.translator) @@ -583,12 +587,12 @@ class Client: """ # look for client charset charset_parameter = 0 - if self.form.has_key('@charset'): + if '@charset' in self.form: charset = self.form['@charset'].value if charset.lower() == "none": charset = "" charset_parameter = 1 - elif self.cookie.has_key('roundup_charset'): + elif 'roundup_charset' in self.cookie: charset = self.cookie['roundup_charset'].value else: charset = None @@ -625,7 +629,7 @@ class Client: uc = int(num) return unichr(uc) - for field_name in self.form.keys(): + for field_name in self.form: field = self.form[field_name] if (field.type == 'text/plain') and not field.filename: try: @@ -640,12 +644,12 @@ class Client: # look for language parameter # then for language cookie # last for the Accept-Language header - if self.form.has_key("@language"): + if "@language" in self.form: language = self.form["@language"].value if language.lower() == "none": language = "" self.add_cookie("roundup_language", language) - elif self.cookie.has_key("roundup_language"): + elif "roundup_language" in self.cookie: language = self.cookie["roundup_language"].value elif self.instance.config["WEB_USE_BROWSER_LANGUAGE"]: hal = self.env.get('HTTP_ACCEPT_LANGUAGE') @@ -673,7 +677,7 @@ class Client: user = None # first up, try http authorization if enabled if self.instance.config['WEB_HTTP_AUTH']: - if self.env.has_key('REMOTE_USER'): + if 'REMOTE_USER' in self.env: # we have external auth (e.g. by Apache) user = self.env['REMOTE_USER'] elif self.env.get('HTTP_AUTHORIZATION', ''): @@ -729,9 +733,9 @@ class Client: """ # allow Anonymous to use the "login" and "register" actions (noting # that "register" has its own "Register" permission check) - if self.form.has_key(':action'): + if ':action' in self.form: action = self.form[':action'].value.lower() - elif self.form.has_key('@action'): + elif '@action' in self.form: action = self.form['@action'].value.lower() else: action = None @@ -747,8 +751,8 @@ class Client: # otherwise for everything else if self.user == 'anonymous': if not self.db.security.hasPermission('Web Access', self.userid): - raise Unauthorised, self._("Anonymous users are not " - "allowed to use the web interface") + raise Unauthorised(self._("Anonymous users are not " + "allowed to use the web interface")) def opendb(self, username): """Open the database and set the current user. @@ -822,7 +826,7 @@ class Client: # see if a template or messages are specified template_override = ok_message = error_message = None - for key in self.form.keys(): + for key in self.form: if self.FV_TEMPLATE.match(key): template_override = self.form[key].value elif self.FV_OK_MESSAGE.match(key): @@ -847,12 +851,12 @@ class Client: self.template = '' return elif path[0] in ('_file', '@@file'): - raise SendStaticFile, os.path.join(*path[1:]) + raise SendStaticFile(os.path.join(*path[1:])) else: self.classname = path[0] if len(path) > 1: # send the file identified by the designator in path[0] - raise SendFile, path[0] + raise SendFile(path[0]) # see if we got a designator m = dre.match(self.classname) @@ -862,9 +866,9 @@ class Client: try: klass = self.db.getclass(self.classname) except KeyError: - raise NotFound, '%s/%s'%(self.classname, self.nodeid) + raise NotFound('%s/%s'%(self.classname, self.nodeid)) if not klass.hasnode(self.nodeid): - raise NotFound, '%s/%s'%(self.classname, self.nodeid) + raise NotFound('%s/%s'%(self.classname, self.nodeid)) # with a designator, we default to item view self.template = 'item' else: @@ -875,7 +879,7 @@ class Client: try: self.db.getclass(self.classname) except KeyError: - raise NotFound, self.classname + raise NotFound(self.classname) # see if we have a template override if template_override is not None: @@ -886,30 +890,30 @@ class Client: """ m = dre.match(str(designator)) if not m: - raise NotFound, str(designator) + raise NotFound(str(designator)) classname, nodeid = m.group(1), m.group(2) try: klass = self.db.getclass(classname) except KeyError: # The classname was not valid. - raise NotFound, str(designator) + raise NotFound(str(designator)) # perform the Anonymous user access check self.check_anonymous_access() # make sure we have the appropriate properties props = klass.getprops() - if not props.has_key('type'): - raise NotFound, designator - if not props.has_key('content'): - raise NotFound, designator + if 'type' not in props: + raise NotFound(designator) + if 'content' not in props: + raise NotFound(designator) # make sure we have permission if not self.db.security.hasPermission('View', self.userid, classname, 'content', nodeid): - raise Unauthorised, self._("You are not allowed to view " - "this file.") + raise Unauthorised(self._("You are not allowed to view " + "this file.")) mime_type = klass.get(nodeid, 'type') # Can happen for msg class: @@ -962,7 +966,7 @@ class Client: if os.path.isfile(filename) and filename.startswith(prefix): break else: - raise NotFound, file + raise NotFound(file) # last-modified time lmt = os.stat(filename)[stat.ST_MTIME] @@ -991,7 +995,7 @@ class Client: # XXX see which interfaces set this #if hasattr(self.request, 'headers'): #ims = self.request.headers.getheader('if-modified-since') - if self.env.has_key('HTTP_IF_MODIFIED_SINCE'): + if 'HTTP_IF_MODIFIED_SINCE' in self.env: # cgi will put the header in the env var ims = self.env['HTTP_IF_MODIFIED_SINCE'] if ims: @@ -1062,7 +1066,7 @@ class Client: except templating.NoTemplate, message: return '%s'%message except templating.Unauthorised, message: - raise Unauthorised, str(message) + raise Unauthorised(str(message)) except: # everything else if self.instance.config.WEB_DEBUG: @@ -1080,7 +1084,7 @@ class Client: # receive an error message, and the adminstrator will # receive a traceback, albeit with less information # than the one we tried to generate above. - raise exc_info[0], exc_info[1], exc_info[2] + raise exc_info[0](exc_info[1]).with_traceback(exc_info[2]) # these are the actions that are available actions = ( @@ -1110,9 +1114,9 @@ class Client: We explicitly catch Reject and ValueError exceptions and present their messages to the user. """ - if self.form.has_key(':action'): + if ':action' in self.form: action = self.form[':action'].value.lower() - elif self.form.has_key('@action'): + elif '@action' in self.form: action = self.form['@action'].value.lower() else: return None @@ -1132,7 +1136,7 @@ class Client: def get_action_class(self, action_name): if (hasattr(self.instance, 'cgi_actions') and - self.instance.cgi_actions.has_key(action_name)): + action_name in self.instance.cgi_actions): # tracker-defined action action_klass = self.instance.cgi_actions[action_name] else: @@ -1141,7 +1145,7 @@ class Client: if name == action_name: break else: - raise ValueError, 'No such action "%s"'%action_name + raise ValueError('No such action "%s"'%action_name) return action_klass def _socket_op(self, call, *args, **kwargs): @@ -1181,7 +1185,7 @@ class Client: def write_html(self, content): if not self.headers_done: # at this point, we are sure about Content-Type - if not self.additional_headers.has_key('Content-Type'): + if 'Content-Type' not in self.additional_headers: self.additional_headers['Content-Type'] = \ 'text/html; charset=%s' % self.charset self.header() @@ -1343,14 +1347,14 @@ class Client: return None # Return code 416 with a Content-Range header giving the # allowable range. - self.response_code = httplib.REQUESTED_RANGE_NOT_SATISFIABLE + self.response_code = http_.client.REQUESTED_RANGE_NOT_SATISFIABLE self.setHeader("Content-Range", "bytes */%d" % length) return None # RFC 2616 10.2.7: 206 Partial Content # # Tell the client that we are honoring the Range request by # indicating that we are providing partial content. - self.response_code = httplib.PARTIAL_CONTENT + self.response_code = http_.client.PARTIAL_CONTENT # RFC 2616 14.16: Content-Range # # Tell the client what data we are providing. @@ -1404,7 +1408,7 @@ class Client: # If the client doesn't actually want the body, or if we are # indicating an invalid range. if (self.env['REQUEST_METHOD'] == 'HEAD' - or self.response_code == httplib.REQUESTED_RANGE_NOT_SATISFIABLE): + or self.response_code == http_.client.REQUESTED_RANGE_NOT_SATISFIABLE): return # Use the optimized "sendfile" operation, if possible. if hasattr(self.request, "sendfile"): @@ -1439,12 +1443,12 @@ class Client: if headers.get('Content-Type', 'text/html') == 'text/html': headers['Content-Type'] = 'text/html; charset=utf-8' - headers = headers.items() + headers = list(headers.items()) - for ((path, name), (value, expire)) in self._cookies.items(): + for ((path, name), (value, expire)) in self._cookies.iteritems(): cookie = "%s=%s; Path=%s;"%(name, value, path) if expire is not None: - cookie += " expires=%s;"%Cookie._getdate(expire) + cookie += " expires=%s;"%get_cookie_date(expire) headers.append(('Set-Cookie', cookie)) self._socket_op(self.request.start_response, headers, response)