]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Get all the tests passing under py3 without 2to3
authorBen Darnell <ben@bendarnell.com>
Mon, 14 Jan 2013 02:31:55 +0000 (21:31 -0500)
committerBen Darnell <ben@bendarnell.com>
Mon, 14 Jan 2013 02:31:55 +0000 (21:31 -0500)
23 files changed:
setup.py
tornado/auth.py
tornado/escape.py
tornado/httputil.py
tornado/ioloop.py
tornado/iostream.py
tornado/locale.py
tornado/netutil.py
tornado/options.py
tornado/process.py
tornado/template.py
tornado/test/auth_test.py
tornado/test/escape_test.py
tornado/test/gen_test.py
tornado/test/httpserver_test.py
tornado/test/iostream_test.py
tornado/test/locale_test.py
tornado/test/log_test.py
tornado/test/template_test.py
tornado/test/web_test.py
tornado/testing.py
tornado/web.py
tornado/wsgi.py

index 7bfc903e18ebcfce0f6fe62b92257e116864bfac..efa27ac0015abffe44eae05627997c8b9291a8f9 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -35,10 +35,6 @@ if "linux" in sys.platform.lower() and not python_26:
 
 version = "2.4.post2"
 
-if major >= 3:
-    import setuptools  # setuptools is required for use_2to3
-    kwargs["use_2to3"] = True
-
 distutils.core.setup(
     name="tornado",
     version=version,
index d1ddbc52aec9e0a0a1f81dd867d9d32633a655d0..e25889fcbaef4e28794ec887f821bc6c5a718c7e 100644 (file)
@@ -58,13 +58,18 @@ from tornado import httpclient
 from tornado import escape
 from tornado.httputil import url_concat
 from tornado.log import gen_log
-from tornado.util import bytes_type, b, u
+from tornado.util import bytes_type, b, u, unicode_type
 
 try:
     import urlparse  # py2
 except ImportError:
     import urllib.parse as urlparse  # py3
 
+try:
+    import urllib.parse as urllib_parse  # py3
+except ImportError:
+    import urllib as urllib_parse  # py2
+
 
 class OpenIdMixin(object):
     """Abstract implementation of OpenID and Attribute Exchange.
@@ -85,7 +90,7 @@ class OpenIdMixin(object):
         """
         callback_uri = callback_uri or self.request.uri
         args = self._openid_args(callback_uri, ax_attrs=ax_attrs)
-        self.redirect(self._OPENID_ENDPOINT + "?" + urllib.urlencode(args))
+        self.redirect(self._OPENID_ENDPOINT + "?" + urllib_parse.urlencode(args))
 
     def get_authenticated_user(self, callback, http_client=None):
         """Fetches the authenticated user data upon redirect.
@@ -95,14 +100,14 @@ class OpenIdMixin(object):
         methods.
         """
         # Verify the OpenID response via direct request to the OP
-        args = dict((k, v[-1]) for k, v in self.request.arguments.iteritems())
+        args = dict((k, v[-1]) for k, v in self.request.arguments.items())
         args["openid.mode"] = u("check_authentication")
         url = self._OPENID_ENDPOINT
         if http_client is None:
             http_client = self.get_auth_http_client()
         http_client.fetch(url, self.async_callback(
             self._on_authentication_verified, callback),
-            method="POST", body=urllib.urlencode(args))
+            method="POST", body=urllib_parse.urlencode(args))
 
     def _openid_args(self, callback_uri, ax_attrs=[], oauth_scope=None):
         url = urlparse.urljoin(self.request.full_url(), callback_uri)
@@ -161,7 +166,7 @@ class OpenIdMixin(object):
 
         # Make sure we got back at least an email from attribute exchange
         ax_ns = None
-        for name in self.request.arguments.iterkeys():
+        for name in self.request.arguments.keys():
             if name.startswith("openid.ns.") and \
                self.get_argument(name) == u("http://openid.net/srv/ax/1.0"):
                 ax_ns = name[10:]
@@ -172,7 +177,7 @@ class OpenIdMixin(object):
                 return u("")
             prefix = "openid." + ax_ns + ".type."
             ax_name = None
-            for name in self.request.arguments.iterkeys():
+            for name in self.request.arguments.keys():
                 if self.get_argument(name) == uri and name.startswith(prefix):
                     part = name[len(prefix):]
                     ax_name = "openid." + ax_ns + ".value." + part
@@ -316,7 +321,7 @@ class OAuthMixin(object):
             signature = _oauth_signature(consumer_token, "GET", url, args)
 
         args["oauth_signature"] = signature
-        return url + "?" + urllib.urlencode(args)
+        return url + "?" + urllib_parse.urlencode(args)
 
     def _on_request_token(self, authorize_url, callback_uri, response):
         if response.error:
@@ -327,12 +332,12 @@ class OAuthMixin(object):
         self.set_cookie("_oauth_request_token", data)
         args = dict(oauth_token=request_token["key"])
         if callback_uri == "oob":
-            self.finish(authorize_url + "?" + urllib.urlencode(args))
+            self.finish(authorize_url + "?" + urllib_parse.urlencode(args))
             return
         elif callback_uri:
             args["oauth_callback"] = urlparse.urljoin(
                 self.request.full_url(), callback_uri)
-        self.redirect(authorize_url + "?" + urllib.urlencode(args))
+        self.redirect(authorize_url + "?" + urllib_parse.urlencode(args))
 
     def _oauth_access_token_url(self, request_token):
         consumer_token = self._oauth_consumer_token()
@@ -356,7 +361,7 @@ class OAuthMixin(object):
                                          request_token)
 
         args["oauth_signature"] = signature
-        return url + "?" + urllib.urlencode(args)
+        return url + "?" + urllib_parse.urlencode(args)
 
     def _on_access_token(self, callback, response):
         if response.error:
@@ -557,11 +562,11 @@ class TwitterMixin(OAuthMixin):
                 url, access_token, all_args, method=method)
             args.update(oauth)
         if args:
-            url += "?" + urllib.urlencode(args)
+            url += "?" + urllib_parse.urlencode(args)
         callback = self.async_callback(self._on_twitter_request, callback)
         http = self.get_auth_http_client()
         if post_args is not None:
-            http.fetch(url, method="POST", body=urllib.urlencode(post_args),
+            http.fetch(url, method="POST", body=urllib_parse.urlencode(post_args),
                        callback=callback)
         else:
             http.fetch(url, callback=callback)
@@ -679,11 +684,11 @@ class FriendFeedMixin(OAuthMixin):
                 url, access_token, all_args, method=method)
             args.update(oauth)
         if args:
-            url += "?" + urllib.urlencode(args)
+            url += "?" + urllib_parse.urlencode(args)
         callback = self.async_callback(self._on_friendfeed_request, callback)
         http = self.get_auth_http_client()
         if post_args is not None:
-            http.fetch(url, method="POST", body=urllib.urlencode(post_args),
+            http.fetch(url, method="POST", body=urllib_parse.urlencode(post_args),
                        callback=callback)
         else:
             http.fetch(url, callback=callback)
@@ -759,7 +764,7 @@ class GoogleMixin(OpenIdMixin, OAuthMixin):
         callback_uri = callback_uri or self.request.uri
         args = self._openid_args(callback_uri, ax_attrs=ax_attrs,
                                  oauth_scope=oauth_scope)
-        self.redirect(self._OPENID_ENDPOINT + "?" + urllib.urlencode(args))
+        self.redirect(self._OPENID_ENDPOINT + "?" + urllib_parse.urlencode(args))
 
     def get_authenticated_user(self, callback):
         """Fetches the authenticated user data upon redirect."""
@@ -841,11 +846,11 @@ class FacebookMixin(object):
             args["cancel_url"] = urlparse.urljoin(
                 self.request.full_url(), cancel_uri)
         if extended_permissions:
-            if isinstance(extended_permissions, (unicode, bytes_type)):
+            if isinstance(extended_permissions, (unicode_type, bytes_type)):
                 extended_permissions = [extended_permissions]
             args["req_perms"] = ",".join(extended_permissions)
         self.redirect("http://www.facebook.com/login.php?" +
-                      urllib.urlencode(args))
+                      urllib_parse.urlencode(args))
 
     def authorize_redirect(self, extended_permissions, callback_uri=None,
                            cancel_uri=None):
@@ -927,7 +932,7 @@ class FacebookMixin(object):
         args["format"] = "json"
         args["sig"] = self._signature(args)
         url = "http://api.facebook.com/restserver.php?" + \
-            urllib.urlencode(args)
+            urllib_parse.urlencode(args)
         http = self.get_auth_http_client()
         http.fetch(url, callback=self.async_callback(
             self._parse_response, callback))
@@ -970,7 +975,7 @@ class FacebookMixin(object):
     def _signature(self, args):
         parts = ["%s=%s" % (n, args[n]) for n in sorted(args.keys())]
         body = "".join(parts) + self.settings["facebook_secret"]
-        if isinstance(body, unicode):
+        if isinstance(body, unicode_type):
             body = body.encode("utf-8")
         return hashlib.md5(body).hexdigest()
 
@@ -1108,11 +1113,11 @@ class FacebookGraphMixin(OAuth2Mixin):
             all_args.update(args)
 
         if all_args:
-            url += "?" + urllib.urlencode(all_args)
+            url += "?" + urllib_parse.urlencode(all_args)
         callback = self.async_callback(self._on_facebook_request, callback)
         http = self.get_auth_http_client()
         if post_args is not None:
-            http.fetch(url, method="POST", body=urllib.urlencode(post_args),
+            http.fetch(url, method="POST", body=urllib_parse.urlencode(post_args),
                        callback=callback)
         else:
             http.fetch(url, callback=callback)
@@ -1174,8 +1179,8 @@ def _oauth10a_signature(consumer_token, method, url, parameters={}, token=None):
                                for k, v in sorted(parameters.items())))
 
     base_string = "&".join(_oauth_escape(e) for e in base_elems)
-    key_elems = [escape.utf8(urllib.quote(consumer_token["secret"], safe='~'))]
-    key_elems.append(escape.utf8(urllib.quote(token["secret"], safe='~') if token else ""))
+    key_elems = [escape.utf8(urllib_parse.quote(consumer_token["secret"], safe='~'))]
+    key_elems.append(escape.utf8(urllib_parse.quote(token["secret"], safe='~') if token else ""))
     key = b("&").join(key_elems)
 
     hash = hmac.new(key, escape.utf8(base_string), hashlib.sha1)
@@ -1183,9 +1188,9 @@ def _oauth10a_signature(consumer_token, method, url, parameters={}, token=None):
 
 
 def _oauth_escape(val):
-    if isinstance(val, unicode):
+    if isinstance(val, unicode_type):
         val = val.encode("utf-8")
-    return urllib.quote(val, safe="~")
+    return urllib_parse.quote(val, safe="~")
 
 
 def _oauth_parse_response(body):
index 4b94e95b0a36a980961635b0a37936ded0fed8d6..6a2cbbb01d2e1552e0e6022ee438d56f3a8261a9 100644 (file)
@@ -24,20 +24,27 @@ from __future__ import absolute_import, division, print_function, with_statement
 
 import re
 import sys
-import urllib
 
 from tornado.util import bytes_type, unicode_type, basestring_type, u
 
 try:
-    from urlparse import parse_qs  # Python 2.6+
+    from urllib.parse import parse_qs  # py3
 except ImportError:
-    from cgi import parse_qs
+    try:
+        from urlparse import parse_qs  # Python 2.6+
+    except ImportError:
+        from cgi import parse_qs
 
 try:
     import htmlentitydefs  # py2
 except ImportError:
     import html.entities as htmlentitydefs  # py3
 
+try:
+    import urllib.parse as urllib_parse  # py3
+except ImportError:
+    import urllib as urllib_parse  # py2
+
 # json module is in the standard library as of python 2.6; fall back to
 # simplejson if present for older versions.
 try:
@@ -106,7 +113,7 @@ def squeeze(value):
 
 def url_escape(value):
     """Returns a valid URL-encoded version of the given value."""
-    return urllib.quote_plus(utf8(value))
+    return urllib_parse.quote_plus(utf8(value))
 
 # python 3 changed things around enough that we need two separate
 # implementations of url_unescape.  We also need our own implementation
@@ -121,9 +128,9 @@ if sys.version_info[0] < 3:
         the result is a unicode string in the specified encoding.
         """
         if encoding is None:
-            return urllib.unquote_plus(utf8(value))
+            return urllib_parse.unquote_plus(utf8(value))
         else:
-            return unicode_type(urllib.unquote_plus(utf8(value)), encoding)
+            return unicode_type(urllib_parse.unquote_plus(utf8(value)), encoding)
 
     parse_qs_bytes = parse_qs
 else:
@@ -136,9 +143,9 @@ else:
         the result is a unicode string in the specified encoding.
         """
         if encoding is None:
-            return urllib.parse.unquote_to_bytes(value)
+            return urllib_parse.unquote_to_bytes(value)
         else:
-            return urllib.unquote_plus(to_basestring(value), encoding=encoding)
+            return urllib_parse.unquote_plus(to_basestring(value), encoding=encoding)
 
     def parse_qs_bytes(qs, keep_blank_values=False, strict_parsing=False):
         """Parses a query string like urlparse.parse_qs, but returns the
@@ -153,7 +160,7 @@ else:
         result = parse_qs(qs, keep_blank_values, strict_parsing,
                           encoding='latin1', errors='strict')
         encoded = {}
-        for k, v in result.iteritems():
+        for k, v in result.items():
             encoded[k] = [i.encode('latin1') for i in v]
         return encoded
 
@@ -221,7 +228,7 @@ def recursive_unicode(obj):
     Supports lists, tuples, and dictionaries.
     """
     if isinstance(obj, dict):
-        return dict((recursive_unicode(k), recursive_unicode(v)) for (k, v) in obj.iteritems())
+        return dict((recursive_unicode(k), recursive_unicode(v)) for (k, v) in obj.items())
     elif isinstance(obj, list):
         return list(recursive_unicode(i) for i in obj)
     elif isinstance(obj, tuple):
index 8c7f684fa86c039f9fb1cf585dc4e40edc311895..1aea2082269608a6608d07ce6ed3ecb09189d868 100644 (file)
@@ -30,6 +30,11 @@ try:
 except ImportError:
     from http.client import responses  # py3
 
+try:
+    from urllib import urlencode  # py2
+except ImportError:
+    from urllib.parse import urlencode  # py3
+
 class HTTPHeaders(dict):
     """A dictionary that maintains Http-Header-Case for all keys.
 
@@ -38,7 +43,7 @@ class HTTPHeaders(dict):
     value per key, with multiple values joined by a comma.
 
     >>> h = HTTPHeaders({"content-type": "text/html"})
-    >>> h.keys()
+    >>> list(h.keys())
     ['Content-Type']
     >>> h["Content-Type"]
     'text/html'
@@ -96,7 +101,7 @@ class HTTPHeaders(dict):
         If a header has multiple values, multiple pairs will be
         returned with the same name.
         """
-        for name, list in self._as_list.iteritems():
+        for name, list in self._as_list.items():
             for value in list:
                 yield (name, value)
 
@@ -123,7 +128,7 @@ class HTTPHeaders(dict):
         """Returns a dictionary from HTTP header text.
 
         >>> h = HTTPHeaders.parse("Content-Type: text/html\\r\\nContent-Length: 42\\r\\n")
-        >>> sorted(h.iteritems())
+        >>> sorted(h.items())
         [('Content-Length', '42'), ('Content-Type', 'text/html')]
         """
         h = cls()
@@ -156,7 +161,7 @@ class HTTPHeaders(dict):
 
     def update(self, *args, **kwargs):
         # dict.update bypasses our __setitem__
-        for k, v in dict(*args, **kwargs).iteritems():
+        for k, v in dict(*args, **kwargs).items():
             self[k] = v
 
     def copy(self):
@@ -195,7 +200,7 @@ def url_concat(url, args):
         return url
     if url[-1] not in ('?', '&'):
         url += '&' if ('?' in url) else '?'
-    return url + urllib.urlencode(args)
+    return url + urlencode(args)
 
 
 class HTTPFile(ObjectDict):
@@ -220,7 +225,7 @@ def parse_body_arguments(content_type, body, arguments, files):
     """
     if content_type.startswith("application/x-www-form-urlencoded"):
         uri_arguments = parse_qs_bytes(native_str(body))
-        for name, values in uri_arguments.iteritems():
+        for name, values in uri_arguments.items():
             values = [v for v in values if v]
             if values:
                 arguments.setdefault(name, []).extend(values)
@@ -304,7 +309,7 @@ def _parse_header(line):
 
     """
     parts = _parseparam(';' + line)
-    key = parts.next()
+    key = next(parts)
     pdict = {}
     for p in parts:
         i = p.find('=')
index 3b6f2769602a83b3d1c83ca64f457580fef475ff..9154d11beb3d9d00c5f4a0c4da2da5e94e795d25 100644 (file)
@@ -426,7 +426,7 @@ class PollIOLoop(IOLoop):
             self._closing = True
         self.remove_handler(self._waker.fileno())
         if all_fds:
-            for fd in self._handlers.keys()[:]:
+            for fd in self._handlers.keys():
                 try:
                     os.close(fd)
                 except Exception:
index 9bc1269f57ae7193fd422a4a15c8f15bb816fb5a..3059dd3091a282a6885361eabb38b91a834e86ff 100644 (file)
@@ -28,6 +28,7 @@ from __future__ import absolute_import, division, print_function, with_statement
 
 import collections
 import errno
+import numbers
 import os
 import socket
 import sys
@@ -146,7 +147,7 @@ class BaseIOStream(object):
         ``callback`` will be empty.
         """
         self._set_read_callback(callback)
-        assert isinstance(num_bytes, (int, long))
+        assert isinstance(num_bytes, numbers.Integral)
         self._read_bytes = num_bytes
         self._streaming_callback = stack_context.wrap(streaming_callback)
         self._try_inline_read()
index b4abd5fe9cd5a5afef41c9ed1776c34ef9eb554d..c6d3a8bb5f7569ee5c09199939e7516aae6c7f55 100644 (file)
@@ -81,7 +81,7 @@ def set_default_locale(code):
     global _default_locale
     global _supported_locales
     _default_locale = code
-    _supported_locales = frozenset(_translations.keys() + [_default_locale])
+    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])
 
 
 def load_translations(directory):
@@ -148,7 +148,7 @@ def load_translations(directory):
                 continue
             _translations[locale].setdefault(plural, {})[english] = translation
         f.close()
-    _supported_locales = frozenset(_translations.keys() + [_default_locale])
+    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])
     gen_log.debug("Supported locales: %s", sorted(_supported_locales))
 
 
@@ -187,7 +187,7 @@ def load_gettext_translations(directory, domain):
         except Exception as e:
             gen_log.error("Cannot load translation for '%s': %s", lang, str(e))
             continue
-    _supported_locales = frozenset(_translations.keys() + [_default_locale])
+    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])
     _use_gettext = True
     gen_log.debug("Supported locales: %s", sorted(_supported_locales))
 
index 6321013f32d93da64f4f2c37be043a1b15466088..ed768cc9604d6b569e894cd31ce094eb7282f7f0 100644 (file)
@@ -202,7 +202,7 @@ class TCPServer(object):
         Requests currently in progress may still continue after the
         server is stopped.
         """
-        for fd, sock in self._sockets.iteritems():
+        for fd, sock in self._sockets.items():
             self.io_loop.remove_handler(fd)
             sock.close()
 
index 102a55467245f7850af31b5bb3cd16deaa959e8e..11b2864724e045d69fc86fbba90ad26319d3b5a1 100644 (file)
@@ -222,7 +222,7 @@ class OptionParser(object):
         print("Usage: %s [OPTIONS]" % sys.argv[0], file=file)
         print("\nOptions:\n", file=file)
         by_group = {}
-        for option in self._options.itervalues():
+        for option in self._options.values():
             by_group.setdefault(option.group_name, []).append(option)
 
         for filename, o in sorted(by_group.items()):
index 229a0d8791a1fb77f8ced867bb38522757c0e3a5..90294b4c3b0a62e9ed9ab152741133a61600ea7d 100644 (file)
@@ -38,6 +38,10 @@ try:
 except ImportError:
     multiprocessing = None
 
+try:
+    long  # py2
+except NameError:
+    long = int  # py3
 
 def cpu_count():
     """Returns the number of processors on this machine."""
@@ -253,7 +257,7 @@ class Subprocess(object):
 
     @classmethod
     def _cleanup(cls):
-        for pid in cls._waiting.keys():
+        for pid in list(cls._waiting.keys()):  # make a copy
             cls._try_cleanup_process(pid)
 
     @classmethod
index 78a5239240439348a71f0ffe8476b9274c212162..1c30e4579fc721a0a5809dbb886c29493ff2e895 100644 (file)
@@ -190,7 +190,7 @@ import threading
 
 from tornado import escape
 from tornado.log import app_log
-from tornado.util import bytes_type, ObjectDict, exec_in
+from tornado.util import bytes_type, ObjectDict, exec_in, unicode_type
 
 try:
     from cStringIO import StringIO  # py2
@@ -250,7 +250,7 @@ class Template(object):
             "linkify": escape.linkify,
             "datetime": datetime,
             "_utf8": escape.utf8,  # for internal use
-            "_string_types": (unicode, bytes_type),
+            "_string_types": (unicode_type, bytes_type),
             # __name__ and __loader__ allow the traceback mechanism to find
             # the generated source code.
             "__name__": self.name.replace('.', '_'),
index 138684d46be99241309748a6e7dbaddade4fa18d..26249cffeceeb53418d8f15a6d37b54d0819084f 100644 (file)
@@ -78,8 +78,6 @@ class OAuth1ClientRequestParametersHandler(RequestHandler, OAuthMixin):
             'http://www.example.com/api/asdf',
             dict(key='uiop', secret='5678'),
             parameters=dict(foo='bar'))
-        import urllib
-        urllib.urlencode(params)
         self.write(params)
 
 
index 71a4fa1ba06096643e5f358443a76aa6e1d7869c..410d1c5f19e8b82dad2460c753abe65309a9602c 100644 (file)
@@ -5,7 +5,7 @@ from __future__ import absolute_import, division, print_function, with_statement
 import tornado.escape
 
 from tornado.escape import utf8, xhtml_escape, xhtml_unescape, url_escape, url_unescape, to_unicode, json_decode, json_encode
-from tornado.util import b, u
+from tornado.util import b, u, unicode_type
 from tornado.test.util import unittest
 
 linkify_tests = [
@@ -180,7 +180,7 @@ class EscapeTestCase(unittest.TestCase):
         # On python2 the escape methods should generally return the same
         # type as their argument
         self.assertEqual(type(xhtml_escape("foo")), str)
-        self.assertEqual(type(xhtml_escape(u("foo"))), unicode)
+        self.assertEqual(type(xhtml_escape(u("foo"))), unicode_type)
 
     def test_json_decode(self):
         # json_decode accepts both bytes and unicode, but strings it returns
index 0c547fc464de5f5c28ebad2bc5c0c3dc47d57bf7..4e270002cb0e93a1d2b860f94e9a106c1cb0b54f 100644 (file)
@@ -262,7 +262,7 @@ class GenTest(AsyncTestCase):
 
         @gen.engine
         def outer():
-            for i in xrange(10):
+            for i in range(10):
                 yield gen.Task(inner)
             stack_increase = len(stack_context._state.contexts) - initial_stack_depth
             self.assertTrue(stack_increase <= 2)
@@ -281,7 +281,7 @@ class GenTest(AsyncTestCase):
 
         @gen.engine
         def outer():
-            for i in xrange(10):
+            for i in range(10):
                 try:
                     yield gen.Task(inner)
                 except ZeroDivisionError:
index fde10684b61f7d855ac92131fd03a1b24a7fa3ce..8587bfd97f20a96ec3b160bebb2f137daf062fd7 100644 (file)
@@ -270,15 +270,15 @@ class TypeCheckHandler(RequestHandler):
         for field, expected_type in fields:
             self.check_type(field, getattr(self.request, field), expected_type)
 
-        self.check_type('header_key', self.request.headers.keys()[0], str)
-        self.check_type('header_value', self.request.headers.values()[0], str)
+        self.check_type('header_key', list(self.request.headers.keys())[0], str)
+        self.check_type('header_value', list(self.request.headers.values())[0], str)
 
-        self.check_type('cookie_key', self.request.cookies.keys()[0], str)
-        self.check_type('cookie_value', self.request.cookies.values()[0].value, str)
+        self.check_type('cookie_key', list(self.request.cookies.keys())[0], str)
+        self.check_type('cookie_value', list(self.request.cookies.values())[0].value, str)
         # secure cookies
 
-        self.check_type('arg_key', self.request.arguments.keys()[0], str)
-        self.check_type('arg_value', self.request.arguments.values()[0][0], bytes_type)
+        self.check_type('arg_key', list(self.request.arguments.keys())[0], str)
+        self.check_type('arg_value', list(self.request.arguments.values())[0][0], bytes_type)
 
     def post(self):
         self.check_type('body', self.request.body, bytes_type)
@@ -441,7 +441,7 @@ class KeepAliveTest(AsyncHTTPTestCase):
             def get(self):
                 # 512KB should be bigger than the socket buffers so it will
                 # be written out in chunks.
-                self.write(''.join(chr(i % 256) * 1024 for i in xrange(512)))
+                self.write(''.join(chr(i % 256) * 1024 for i in range(512)))
 
         class FinishOnCloseHandler(RequestHandler):
             @asynchronous
index 13bb5917a1df82d7ac02c5686c97b718211df820..e2b98513301fb703b2afe4ce7b260dc9dc8b5f38 100644 (file)
@@ -375,7 +375,7 @@ class TestIOStreamMixin(object):
                 # but there was no pypy for 2.5
                 pass
             NUM_KB = 4096
-            for i in xrange(NUM_KB):
+            for i in range(NUM_KB):
                 client.write(b("A") * 1024)
             client.write(b("\r\n"))
             server.read_until(b("\r\n"), self.stop)
index 5527a63b4a99dc464f5dac27c47c1867368ee4a0..8e7f6e019a448d1fcd5c90610bdb48486402a58e 100644 (file)
@@ -4,7 +4,7 @@ import os
 import tornado.locale
 from tornado.escape import utf8
 from tornado.test.util import unittest
-from tornado.util import b, u
+from tornado.util import b, u, unicode_type
 
 
 class TranslationLoaderTest(unittest.TestCase):
@@ -45,6 +45,6 @@ class TranslationLoaderTest(unittest.TestCase):
 class LocaleDataTest(unittest.TestCase):
     def test_non_ascii_name(self):
         name = tornado.locale.LOCALE_NAMES['es_LA']['name']
-        self.assertTrue(isinstance(name, unicode))
+        self.assertTrue(isinstance(name, unicode_type))
         self.assertEqual(name, u('Espa\u00f1ol'))
         self.assertEqual(utf8(name), b('Espa\xc3\xb1ol'))
index 3bcf4a1a8732fa1763336bc33ab291f2731fcde2..7100807ea9e2f1e91658e7b9bf1fd55cd7dfad05 100644 (file)
@@ -27,7 +27,7 @@ from tornado.escape import utf8
 from tornado.log import LogFormatter, define_logging_options, enable_pretty_logging
 from tornado.options import OptionParser
 from tornado.test.util import unittest
-from tornado.util import b, u, bytes_type
+from tornado.util import b, u, bytes_type, basestring_type
 
 @contextlib.contextmanager
 def ignore_bytes_warning():
@@ -97,7 +97,7 @@ class LogFormatterTest(unittest.TestCase):
 
     def test_utf8_logging(self):
         self.logger.error(u("\u00e9").encode("utf8"))
-        if issubclass(bytes_type, basestring):
+        if issubclass(bytes_type, basestring_type):
             # on python 2, utf8 byte strings (and by extension ascii byte
             # strings) are passed through as-is.
             self.assertEqual(self.get_output(), utf8(u("\u00e9")))
index 2ad9876a980e898a477f9aad96fa341890c26bd4..f2cd1be959649765a3f4bfe4ff8492bd8b966f7b 100644 (file)
@@ -7,7 +7,7 @@ from tornado.escape import utf8, native_str, to_unicode
 from tornado.template import Template, DictLoader, ParseError, Loader
 from tornado.testing import ExpectLog
 from tornado.test.util import unittest
-from tornado.util import b, u, bytes_type, ObjectDict
+from tornado.util import b, u, bytes_type, ObjectDict, unicode_type
 
 
 class TemplateTest(unittest.TestCase):
@@ -79,7 +79,7 @@ class TemplateTest(unittest.TestCase):
         # test simulates unicode characters appearing directly in the
         # template file (with utf8 encoding), i.e. \u escapes would not
         # be used in the template file itself.
-        if str is unicode:
+        if str is unicode_type:
             # python 3 needs a different version of this test since
             # 2to3 doesn't run on template internals
             template = Template(utf8(u('{{ "\u00e9" }}')))
index 5a3ebd1bb38f55e73c0ea485227cc041cb341488..aaf71e8faf283328fe9bb77004a9eef255e05eb4 100644 (file)
@@ -7,7 +7,7 @@ from tornado.simple_httpclient import SimpleAsyncHTTPClient
 from tornado.template import DictLoader
 from tornado.testing import AsyncHTTPTestCase, ExpectLog
 from tornado.test.util import unittest
-from tornado.util import b, u, bytes_type, ObjectDict
+from tornado.util import b, u, bytes_type, ObjectDict, unicode_type
 from tornado.web import RequestHandler, authenticated, Application, asynchronous, url, HTTPError, StaticFileHandler, _create_signature, create_signed_value, ErrorHandler
 
 import binascii
@@ -278,11 +278,11 @@ class EchoHandler(RequestHandler):
                     raise Exception("incorrect type for value: %r" %
                                     type(value))
             for value in self.get_arguments(key):
-                if type(value) != unicode:
+                if type(value) != unicode_type:
                     raise Exception("incorrect type for value: %r" %
                                     type(value))
         for arg in path_args:
-            if type(arg) != unicode:
+            if type(arg) != unicode_type:
                 raise Exception("incorrect type for path arg: %r" % type(arg))
         self.write(dict(path=self.request.path,
                         path_args=path_args,
@@ -333,13 +333,13 @@ class TypeCheckHandler(RequestHandler):
 
         # get_argument is an exception from the general rule of using
         # type str for non-body data mainly for historical reasons.
-        self.check_type('argument', self.get_argument('foo'), unicode)
-        self.check_type('cookie_key', self.cookies.keys()[0], str)
-        self.check_type('cookie_value', self.cookies.values()[0].value, str)
+        self.check_type('argument', self.get_argument('foo'), unicode_type)
+        self.check_type('cookie_key', list(self.cookies.keys())[0], str)
+        self.check_type('cookie_value', list(self.cookies.values())[0].value, str)
 
         # Secure cookies return bytes because they can contain arbitrary
         # data, but regular cookies are native strings.
-        if self.cookies.keys() != ['asdf']:
+        if list(self.cookies.keys()) != ['asdf']:
             raise Exception("unexpected values for cookie keys: %r" %
                             self.cookies.keys())
         self.check_type('get_secure_cookie', self.get_secure_cookie('asdf'), bytes_type)
@@ -355,11 +355,11 @@ class TypeCheckHandler(RequestHandler):
     def get(self, path_component):
         # path_component uses type unicode instead of str for consistency
         # with get_argument()
-        self.check_type('path_component', path_component, unicode)
+        self.check_type('path_component', path_component, unicode_type)
         self.write(self.errors)
 
     def post(self, path_component):
-        self.check_type('path_component', path_component, unicode)
+        self.check_type('path_component', path_component, unicode_type)
         self.write(self.errors)
 
     def check_type(self, name, obj, expected_type):
@@ -383,7 +383,7 @@ class DecodeArgHandler(RequestHandler):
         def describe(s):
             if type(s) == bytes_type:
                 return ["bytes", native_str(binascii.b2a_hex(s))]
-            elif type(s) == unicode:
+            elif type(s) == unicode_type:
                 return ["unicode", s]
             raise Exception("unknown type")
         self.write({'path': describe(arg),
index 63ececf94e4eae093c4d003a4cc73381f729f1fd..0e3db883ac990b3e948e349aea16fa6884ee93e7 100644 (file)
@@ -36,7 +36,7 @@ except ImportError:
     SimpleAsyncHTTPClient = None
 from tornado.log import gen_log
 from tornado.stack_context import ExceptionStackContext
-from tornado.util import raise_exc_info
+from tornado.util import raise_exc_info, basestring_type
 import logging
 import os
 import re
@@ -414,7 +414,7 @@ class ExpectLog(logging.Filter):
         :param required: If true, an exeption will be raised if the end of
             the ``with`` statement is reached without matching any log entries.
         """
-        if isinstance(logger, basestring):
+        if isinstance(logger, basestring_type):
             logger = logging.getLogger(logger)
         self.logger = logger
         self.regex = re.compile(regex)
index bc6d944f427fd6ab5e24b6d6a885c15196756c2e..fbc7e2dfa508b5b7a8df4512ab4e89f5c0f50e86 100644 (file)
@@ -62,6 +62,7 @@ import hashlib
 import hmac
 import itertools
 import mimetypes
+import numbers
 import os.path
 import re
 import stat
@@ -71,7 +72,6 @@ import time
 import tornado
 import traceback
 import types
-import urllib
 import uuid
 
 from tornado import escape
@@ -81,7 +81,7 @@ from tornado.log import access_log, app_log, gen_log
 from tornado import stack_context
 from tornado import template
 from tornado.escape import utf8, _unicode
-from tornado.util import b, bytes_type, import_object, ObjectDict, raise_exc_info
+from tornado.util import b, bytes_type, import_object, ObjectDict, raise_exc_info, unicode_type
 
 try:
     from io import BytesIO  # python 3
@@ -98,6 +98,11 @@ try:
 except ImportError:
     import urllib.parse as urlparse  # py3
 
+try:
+    from urllib import urlencode  # py2
+except ImportError:
+    from urllib.parse import urlencode  # py3
+
 class RequestHandler(object):
     """Subclass this class and define get() or post() to make a handler.
 
@@ -123,14 +128,14 @@ class RequestHandler(object):
         self.path_args = None
         self.path_kwargs = None
         self.ui = ObjectDict((n, self._ui_method(m)) for n, m in
-                     application.ui_methods.iteritems())
+                     application.ui_methods.items())
         # UIModules are available as both `modules` and `_modules` in the
         # template namespace.  Historically only `modules` was available
         # but could be clobbered by user additions to the namespace.
         # The template {% module %} directive looks in `_modules` to avoid
         # possible conflicts.
         self.ui["_modules"] = ObjectDict((n, self._ui_module(n, m)) for n, m in
-                                 application.ui_modules.iteritems())
+                                 application.ui_modules.items())
         self.ui["modules"] = self.ui["_modules"]
         self.clear()
         # Check since connection is not available in WSGI
@@ -302,9 +307,9 @@ class RequestHandler(object):
     def _convert_header_value(self, value):
         if isinstance(value, bytes_type):
             pass
-        elif isinstance(value, unicode):
+        elif isinstance(value, unicode_type):
             value = value.encode('utf-8')
-        elif isinstance(value, (int, long)):
+        elif isinstance(value, numbers.Integral):
             # return immediately since we know the converted value will be safe
             return str(value)
         elif isinstance(value, datetime.datetime):
@@ -349,7 +354,7 @@ class RequestHandler(object):
         values = []
         for v in self.request.arguments.get(name, []):
             v = self.decode_argument(v, name=name)
-            if isinstance(v, unicode):
+            if isinstance(v, unicode_type):
                 # Get rid of any weird control chars (unless decoding gave
                 # us bytes, in which case leave it alone)
                 v = re.sub(r"[\x00-\x08\x0e-\x1f]", " ", v)
@@ -415,7 +420,7 @@ class RequestHandler(object):
                 timestamp, localtime=False, usegmt=True)
         if path:
             morsel["path"] = path
-        for k, v in kwargs.iteritems():
+        for k, v in kwargs.items():
             if k == 'max_age':
                 k = 'max-age'
             morsel[k] = v
@@ -530,13 +535,13 @@ class RequestHandler(object):
         css_files = []
         html_heads = []
         html_bodies = []
-        for module in getattr(self, "_active_modules", {}).itervalues():
+        for module in getattr(self, "_active_modules", {}).values():
             embed_part = module.embedded_javascript()
             if embed_part:
                 js_embed.append(utf8(embed_part))
             file_part = module.javascript_files()
             if file_part:
-                if isinstance(file_part, (unicode, bytes_type)):
+                if isinstance(file_part, (unicode_type, bytes_type)):
                     js_files.append(file_part)
                 else:
                     js_files.extend(file_part)
@@ -545,7 +550,7 @@ class RequestHandler(object):
                 css_embed.append(utf8(embed_part))
             file_part = module.css_files()
             if file_part:
-                if isinstance(file_part, (unicode, bytes_type)):
+                if isinstance(file_part, (unicode_type, bytes_type)):
                     css_files.append(file_part)
                 else:
                     css_files.extend(file_part)
@@ -1062,7 +1067,7 @@ class RequestHandler(object):
                 raise HTTPError(405)
             self.path_args = [self.decode_argument(arg) for arg in args]
             self.path_kwargs = dict((k, self.decode_argument(v, name=k))
-                                    for (k, v) in kwargs.iteritems())
+                                    for (k, v) in kwargs.items())
             # If XSRF cookies are turned on, reject form submissions without
             # the proper cookie
             if self.request.method not in ("GET", "HEAD", "OPTIONS") and \
@@ -1083,7 +1088,7 @@ class RequestHandler(object):
                       str(self._status_code) +
                       " " + reason)]
         lines.extend([(utf8(n) + b(": ") + utf8(v)) for n, v in
-                      itertools.chain(self._headers.iteritems(), self._list_headers)])
+                      itertools.chain(self._headers.items(), self._list_headers)])
         if hasattr(self, "_new_cookie"):
             for cookie in self._new_cookie.values():
                 lines.append(utf8("Set-Cookie: " + cookie.OutputString(None)))
@@ -1389,7 +1394,7 @@ class Application(object):
             for m in methods:
                 self._load_ui_methods(m)
         else:
-            for name, fn in methods.iteritems():
+            for name, fn in methods.items():
                 if not name.startswith("_") and hasattr(fn, "__call__") \
                    and name[0].lower() == name[0]:
                     self.ui_methods[name] = fn
@@ -1403,7 +1408,7 @@ class Application(object):
                 self._load_ui_modules(m)
         else:
             assert isinstance(modules, dict)
-            for name, cls in modules.iteritems():
+            for name, cls in modules.items():
                 try:
                     if issubclass(cls, UIModule):
                         self.ui_modules[name] = cls
@@ -1441,7 +1446,7 @@ class Application(object):
                         if spec.regex.groupindex:
                             kwargs = dict(
                                 (str(k), unquote(v))
-                                for (k, v) in match.groupdict().iteritems())
+                                for (k, v) in match.groupdict().items())
                         else:
                             args = [unquote(s) for s in match.groups()]
                     break
@@ -1853,7 +1858,7 @@ def authenticated(method):
                         next_url = self.request.full_url()
                     else:
                         next_url = self.request.uri
-                    url += "?" + urllib.urlencode(dict(next=next_url))
+                    url += "?" + urlencode(dict(next=next_url))
                 self.redirect(url)
                 return
             raise HTTPError(403)
@@ -1961,7 +1966,7 @@ class TemplateModule(UIModule):
     def javascript_files(self):
         result = []
         for f in self._get_resources("javascript_files"):
-            if isinstance(f, (unicode, bytes_type)):
+            if isinstance(f, (unicode_type, bytes_type)):
                 result.append(f)
             else:
                 result.extend(f)
@@ -1973,7 +1978,7 @@ class TemplateModule(UIModule):
     def css_files(self):
         result = []
         for f in self._get_resources("css_files"):
-            if isinstance(f, (unicode, bytes_type)):
+            if isinstance(f, (unicode_type, bytes_type)):
                 result.append(f)
             else:
                 result.extend(f)
@@ -2058,7 +2063,7 @@ class URLSpec(object):
             return self._path
         converted_args = []
         for a in args:
-            if not isinstance(a, (unicode, bytes_type)):
+            if not isinstance(a, (unicode_type, bytes_type)):
                 a = str(a)
             converted_args.append(escape.url_escape(utf8(a)))
         return self._path % tuple(converted_args)
index 3f38f67a3370ab19e593fdc8b98dffe4e39ec943..e64d4813868b0bb416f9263882a2c5a72bdb88a7 100644 (file)
@@ -53,6 +53,11 @@ try:
 except ImportError:
     import http.cookies as Cookie  # py3
 
+try:
+    import urllib.parse as urllib_parse  # py3
+except ImportError:
+    import urllib as urllib_parse
+
 # PEP 3333 specifies that WSGI on python 3 generally deals with byte strings
 # that are smuggled inside objects of type unicode (via the latin1 encoding).
 # These functions are like those in the tornado.escape module, but defined
@@ -118,7 +123,7 @@ class WSGIApplication(web.Application):
         assert handler._finished
         reason = handler._reason
         status = str(handler._status_code) + " " + reason
-        headers = handler._headers.items() + handler._list_headers
+        headers = list(handler._headers.items()) + handler._list_headers
         if hasattr(handler, "_new_cookie"):
             for cookie in handler._new_cookie.values():
                 headers.append(("Set-Cookie", cookie.OutputString(None)))
@@ -132,8 +137,8 @@ class HTTPRequest(object):
     def __init__(self, environ):
         """Parses the given WSGI environ to construct the request."""
         self.method = environ["REQUEST_METHOD"]
-        self.path = urllib.quote(from_wsgi_str(environ.get("SCRIPT_NAME", "")))
-        self.path += urllib.quote(from_wsgi_str(environ.get("PATH_INFO", "")))
+        self.path = urllib_parse.quote(from_wsgi_str(environ.get("SCRIPT_NAME", "")))
+        self.path += urllib_parse.quote(from_wsgi_str(environ.get("PATH_INFO", "")))
         self.uri = self.path
         self.arguments = {}
         self.query = environ.get("QUERY_STRING", "")
@@ -296,7 +301,7 @@ class WSGIContainer(object):
             environ["CONTENT_TYPE"] = request.headers.pop("Content-Type")
         if "Content-Length" in request.headers:
             environ["CONTENT_LENGTH"] = request.headers.pop("Content-Length")
-        for key, value in request.headers.iteritems():
+        for key, value in request.headers.items():
             environ["HTTP_" + key.replace("-", "_").upper()] = value
         return environ