Code

more modernisation
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Fri, 26 Feb 2010 00:38:53 +0000 (00:38 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Fri, 26 Feb 2010 00:38:53 +0000 (00:38 +0000)
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/roundup/trunk@4468 57a73879-2fb5-44c3-a270-3262357dd7e2

12 files changed:
2to3-done.txt
roundup/anypy/cookie_.py [new file with mode: 0644]
roundup/anypy/http_.py [new file with mode: 0644]
roundup/anypy/io_.py [new file with mode: 0644]
roundup/anypy/urllib_.py [new file with mode: 0644]
roundup/backends/indexer_dbm.py
roundup/backends/sessions_dbm.py
roundup/backends/sessions_rdbms.py
roundup/cgi/accept_language.py
roundup/cgi/actions.py
roundup/cgi/cgitb.py
roundup/cgi/client.py

index b9cac19f325994c08c53c2922f8288695e935cb8..5aeb5fa0cb5ff50f212b86dccd14926a07baa0e1 100644 (file)
@@ -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 (file)
index 0000000..44bf93a
--- /dev/null
@@ -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 (file)
index 0000000..a7f5238
--- /dev/null
@@ -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 (file)
index 0000000..86f8023
--- /dev/null
@@ -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 (file)
index 0000000..d1a8a4b
--- /dev/null
@@ -0,0 +1,6 @@
+
+try:
+    from urllib.parse import quote, urlparse
+except:
+    from urllib import quote
+    from urlparse import urlparse
index 0b8562c6b7353bc8a2bff145cc97aae44d6994f8..11ed64f4efa33c928126f360cdb4acc301cd0d16 100644 (file)
@@ -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:
index 1087967b6096a6d8d0e8e311238c19c378a488e0..27b6c52363fc369b7956ca8b38a5ce5097a9bc24 100644 (file)
@@ -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()
index 43702522ae4389d2d914357a3cb99fa6c9847a03..c5dc1893624497d199ec2ecaecdee04871c46a5b 100644 (file)
@@ -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):
index d3d73281ec7e9cedf4967788e44cf9aba6d6f57a..09c06cf9ae3024699edc09616944b02a56a8d384 100755 (executable)
@@ -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):
index dd86a84da6f56fce0227f9855bc6010912d20675..e3de0dea5c9458e60943845c47c5f2baaad6267a 100755 (executable)
@@ -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.Unauthorisedself._(
+            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.SeriousErrorself._(
-                '"%(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 ValueErrorself._(
-                '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.Unauthorisedself._(
+            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.Unauthorisedself._(
-                            "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.Unauthorisedself._(
-                            "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.Unauthorisedself._(
-                            "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.Unauthorisedself._(
-                            "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.Unauthorisedself._(
+                    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.Unauthorisedself._(
+                    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.Unauthorisedself._(
+                    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.Unauthorisedself._(
+            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.Unauthorisedself._(
+            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.Unauthorisedself._(
-                "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.LoginErrorself._(
-                "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.Unauthorisedself._(
+                    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)
index b89cb467bde0ba025fcf3c66a1a23053f98a492f..d2b30a1f5e55797032b3c55f387a20a91a184acc 100644 (file)
@@ -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('<tr><td><strong>%s</strong></td><td>%s</td></tr>'%(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(_('<li>In %s</li>') % 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] + '<br>' + 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 = _('<em>undefined</em>')
                 name = '<strong>%s</strong>' % 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 = _('<em>undefined</em>')
index 3b1023806a5bd4b20c7c3040c0cb6bd8378a7406..793a0d8472b32b4f183910948e953e83e2c005a4 100644 (file)
@@ -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 <a>,<i>,<b> and <br> tags from a string
     """
-    if ok.has_key(match.group(3).lower()):
+    if match.group(3).lower() in ok:
         return match.group(1)
     return '&lt;%s&gt;'%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 = ("<h1>Traceback</h1>"
                     + 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 Unauthorisedself._("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 Unauthorisedself._("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 '<strong>%s</strong>'%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)