diff options
-rw-r--r-- | paste/exceptions/collector.py | 2 | ||||
-rw-r--r-- | paste/exceptions/formatter.py | 4 | ||||
-rw-r--r-- | paste/fixture.py | 4 | ||||
-rw-r--r-- | paste/request.py | 11 | ||||
-rw-r--r-- | paste/util/template.py | 11 | ||||
-rw-r--r-- | paste/wsgiwrappers.py | 3 | ||||
-rwxr-xr-x | tests/cgiapp_data/form.cgi | 59 | ||||
-rw-r--r-- | tests/test_cgiapp.py | 23 | ||||
-rw-r--r-- | tests/test_doctests.py | 5 | ||||
-rw-r--r-- | tests/test_template.txt | 4 | ||||
-rw-r--r-- | 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): |