[Python-modules-commits] [paste] 01/02: Py3k fixes

Ondřej Nový onovy-guest at moszumanska.debian.org
Sat Mar 5 22:49:15 UTC 2016


This is an automated email from the git hooks/post-receive script.

onovy-guest pushed a commit to branch master
in repository paste.

commit e7efa9cfa29c8b4abf8dde5a47bcb28a5945b9b1
Author: Ondřej Nový <novy at ondrej.org>
Date:   Sat Mar 5 23:45:57 2016 +0100

    Py3k fixes
    
    Author: Nils Philippsen
    Origin: https://bitbucket.org/ianb/paste/pull-requests/28/py3k-fixes/
    Forwarded: yes
---
 paste/exceptions/collector.py |  2 +-
 paste/exceptions/formatter.py |  4 +--
 paste/fixture.py              |  4 +--
 paste/request.py              | 11 ++++++--
 paste/util/template.py        | 11 ++++----
 paste/wsgiwrappers.py         |  3 ++-
 tests/cgiapp_data/form.cgi    | 59 ++++++++++++++++++++++++++++++++++++++++++-
 tests/test_cgiapp.py          | 23 +++++++++++++++++
 tests/test_doctests.py        |  5 +++-
 tests/test_template.txt       |  4 +--
 tests/test_wsgiwrappers.py    |  2 +-
 11 files changed, 109 insertions(+), 19 deletions(-)

diff --git a/paste/exceptions/collector.py b/paste/exceptions/collector.py
index 8867bf7..632ce06 100644
--- a/paste/exceptions/collector.py
+++ b/paste/exceptions/collector.py
@@ -266,7 +266,7 @@ class ExceptionCollector(object):
         name = co.co_name
         globals = f.f_globals
         locals = f.f_locals
-        if not hasattr(locals, 'has_key'):
+        if not hasattr(locals, 'keys'):
             # Something weird about this frame; it's not a real dict
             warnings.warn(
                 "Frame %s has an invalid locals(): %r" % (
diff --git a/paste/exceptions/formatter.py b/paste/exceptions/formatter.py
index c83ab50..09309de 100644
--- a/paste/exceptions/formatter.py
+++ b/paste/exceptions/formatter.py
@@ -217,7 +217,7 @@ class TextFormatter(AbstractFormatter):
         elif isinstance(value, dict):
             lines = ['\n', title, '-'*len(title)]
             items = value.items()
-            items.sort()
+            items = sorted(items)
             for n, v in items:
                 try:
                     v = repr(v)
@@ -303,7 +303,7 @@ class HTMLFormatter(TextFormatter):
     def zebra_table(self, title, rows, table_class="variables"):
         if isinstance(rows, dict):
             rows = rows.items()
-            rows.sort()
+            rows = sorted(rows)
         table = ['<table class="%s">' % table_class,
                  '<tr class="header"><th colspan="2">%s</th></tr>'
                  % self.quote(title)]
diff --git a/paste/fixture.py b/paste/fixture.py
index df1c75d..363f119 100644
--- a/paste/fixture.py
+++ b/paste/fixture.py
@@ -226,8 +226,8 @@ class TestApp(object):
         if hasattr(params, 'items'):
             # Some other multi-dict like format
             params = urlencode(params.items())
-            if six.PY3:
-                params = params.encode('utf8')
+        if six.PY3 and isinstance(params, six.text_type):
+            params = params.encode('utf8')
         if upload_files:
             params = urlparse.parse_qsl(params, keep_blank_values=True)
             content_type, params = self.encode_multipart(
diff --git a/paste/request.py b/paste/request.py
index f0d91c1..8d5e5c3 100644
--- a/paste/request.py
+++ b/paste/request.py
@@ -140,7 +140,7 @@ def parse_dict_querystring(environ):
     environ['paste.parsed_dict_querystring'] = (multi, source)
     return multi
 
-def parse_formvars(environ, include_get_vars=True):
+def parse_formvars(environ, include_get_vars=True, encoding=None, errors=None):
     """Parses the request, returning a MultiDict of form variables.
 
     If ``include_get_vars`` is true then GET (query string) variables
@@ -182,9 +182,16 @@ def parse_formvars(environ, include_get_vars=True):
         environ['CONTENT_TYPE'] = ''
     else:
         input = environ['wsgi.input']
+    kwparms = {}
+    if six.PY3:
+        if encoding:
+            kwparms['encoding'] = encoding
+        if errors:
+            kwparms['errors'] = errors
     fs = cgi.FieldStorage(fp=input,
                           environ=environ,
-                          keep_blank_values=1)
+                          keep_blank_values=1,
+                          **kwparms)
     environ['QUERY_STRING'] = old_query_string
     if fake_out_cgi:
         environ['CONTENT_TYPE'] = old_content_type
diff --git a/paste/util/template.py b/paste/util/template.py
index f0826af..5a63664 100644
--- a/paste/util/template.py
+++ b/paste/util/template.py
@@ -318,28 +318,27 @@ def html_quote(value):
     if value is None:
         return ''
     if not isinstance(value, six.string_types):
-        if hasattr(value, '__unicode__'):
+        if six.PY2 and hasattr(value, '__unicode__'):
             value = unicode(value)
         else:
             value = str(value)
     value = cgi.escape(value, 1)
-    if isinstance(value, unicode):
+    if six.PY2 and isinstance(value, unicode):
         value = value.encode('ascii', 'xmlcharrefreplace')
     return value
 
 def url(v):
     if not isinstance(v, six.string_types):
-        if hasattr(v, '__unicode__'):
+        if six.PY2 and hasattr(v, '__unicode__'):
             v = unicode(v)
         else:
             v = str(v)
-    if isinstance(v, unicode):
+    if six.PY2 and isinstance(v, unicode):
         v = v.encode('utf8')
     return quote(v)
 
 def attr(**kw):
-    kw = kw.items()
-    kw.sort()
+    kw = sorted(kw.items())
     parts = []
     for name, value in kw:
         if value is None:
diff --git a/paste/wsgiwrappers.py b/paste/wsgiwrappers.py
index 7b8f6de..674054f 100644
--- a/paste/wsgiwrappers.py
+++ b/paste/wsgiwrappers.py
@@ -199,7 +199,8 @@ class WSGIRequest(object):
     GET = property(GET, doc=GET.__doc__)
 
     def _POST(self):
-        return parse_formvars(self.environ, include_get_vars=False)
+        return parse_formvars(self.environ, include_get_vars=False,
+                              encoding=self.charset, errors=self.errors)
 
     def POST(self):
         """Dictionary-like object representing the POST body.
diff --git a/tests/cgiapp_data/form.cgi b/tests/cgiapp_data/form.cgi
index 2181998..c4c562d 100755
--- a/tests/cgiapp_data/form.cgi
+++ b/tests/cgiapp_data/form.cgi
@@ -1,11 +1,68 @@
 #!/usr/bin/env python
 
+from __future__ import print_function
+
 import cgi
+import six
 
 print('Content-type: text/plain')
 print('')
 
-form = cgi.FieldStorage()
+if six.PY3:
+    # Python 3: cgi.FieldStorage keeps some field names as unicode and some as
+    # the repr() of byte strings, duh.
+
+    class FieldStorage(cgi.FieldStorage):
+
+        def _key_candidates(self, key):
+            yield key
+
+            try:
+                # assume bytes, coerce to str
+                try:
+                    yield key.decode(self.encoding)
+                except UnicodeDecodeError:
+                    pass
+            except AttributeError:
+                # assume str, coerce to bytes
+                try:
+                    yield key.encode(self.encoding)
+                except UnicodeEncodeError:
+                    pass
+
+        def __getitem__(self, key):
+
+            superobj = super(FieldStorage, self)
+
+            error = None
+
+            for candidate in self._key_candidates(key):
+                if isinstance(candidate, bytes):
+                    # ouch
+                    candidate = repr(candidate)
+                try:
+                    return superobj.__getitem__(candidate)
+                except KeyError as e:
+                    if error is None:
+                        error = e
+
+            # fall through, re-raise the first KeyError
+            raise error
+
+        def __contains__(self, key):
+            superobj = super(FieldStorage, self)
+
+            for candidate in self._key_candidates(key):
+                if superobj.__contains__(candidate):
+                    return True
+            return False
+
+else: # PY2
+
+    FieldStorage = cgi.FieldStorage
+
+
+form = FieldStorage()
 
 print('Filename: %s' % form['up'].filename)
 print('Name: %s' % form['name'].value)
diff --git a/tests/test_cgiapp.py b/tests/test_cgiapp.py
index 12cb2be..900e83e 100644
--- a/tests/test_cgiapp.py
+++ b/tests/test_cgiapp.py
@@ -8,6 +8,29 @@ data_dir = os.path.join(os.path.dirname(__file__), 'cgiapp_data')
 
 # these CGI scripts can't work on Windows or Jython
 if sys.platform != 'win32' and not sys.platform.startswith('java'):
+
+    # Ensure the CGI scripts are called with the same python interpreter. Put a
+    # symlink to the interpreter executable into the path...
+    def setup_module():
+        global oldpath, pyexelink
+        oldpath = os.environ.get('PATH', None)
+        os.environ['PATH'] = data_dir + os.path.pathsep + oldpath
+        pyexelink = os.path.join(data_dir, "python")
+        try:
+            os.unlink(pyexelink)
+        except OSError:
+            pass
+        os.symlink(sys.executable, pyexelink)
+
+    # ... and clean up again.
+    def teardown_module():
+        global oldpath, pyexelink
+        os.unlink(pyexelink)
+        if oldpath is not None:
+            os.environ['PATH'] = oldpath
+        else:
+            del os.environ['PATH']
+
     def test_ok():
         app = TestApp(CGIApplication({}, script='ok.cgi', path=[data_dir]))
         res = app.get('')
diff --git a/tests/test_doctests.py b/tests/test_doctests.py
index 875fbc2..d59d666 100644
--- a/tests/test_doctests.py
+++ b/tests/test_doctests.py
@@ -1,3 +1,4 @@
+import six
 import doctest
 from paste.util.import_string import simple_import
 import os
@@ -25,7 +26,9 @@ modules = [
     'paste.request',
     ]
 
-options = doctest.ELLIPSIS|doctest.REPORT_ONLY_FIRST_FAILURE
+options = doctest.ELLIPSIS | doctest.REPORT_ONLY_FIRST_FAILURE
+if six.PY3:
+    options |= doctest.IGNORE_EXCEPTION_DETAIL
 
 def test_doctests():
     for filename in filenames:
diff --git a/tests/test_template.txt b/tests/test_template.txt
index 45a85e2..f3466f2 100644
--- a/tests/test_template.txt
+++ b/tests/test_template.txt
@@ -97,8 +97,8 @@ in Python, but it's more useful in templates generally)::
     ...     elif item == 'orange':
     ...         assert loop.last
     ...     if loop.first_group(lambda i: i[0].upper()):
-    ...         print '%s:' % item[0].upper()
-    ...     print loop.number, item
+    ...         print('%s:' % item[0].upper())
+    ...     print("%s %s" % (loop.number, item))
     A:
     1 apple
     2 asparagus
diff --git a/tests/test_wsgiwrappers.py b/tests/test_wsgiwrappers.py
index 8719693..75d03ed 100644
--- a/tests/test_wsgiwrappers.py
+++ b/tests/test_wsgiwrappers.py
@@ -13,7 +13,7 @@ class AssertApp(object):
     def __call__(self, environ, start_response):
         start_response('200 OK', [('Content-type','text/plain')])
         self.assertfunc(environ)
-        return ['Passed']
+        return [b'Passed']
 
 no_encoding = object()
 def valid_name(name, encoding=no_encoding, post=False):

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/paste.git



More information about the Python-modules-commits mailing list