Permalink
Browse files

Fix str/bytes problems in the auth module on python 3.

In some cases signatures were being computed on str(byte object),
which is incorrect.  Enable python -bb flag to catch this class of
errors and fix up a few more instances.

Fixes #581.
  • Loading branch information...
1 parent 6385cfa commit ec4981691141b198b5e7eedb8aa89e4992681100 @bdarnell bdarnell committed Aug 12, 2012
Showing with 43 additions and 16 deletions.
  1. +9 −9 tornado/auth.py
  2. +18 −4 tornado/test/options_test.py
  3. +10 −1 tornado/test/runtests.py
  4. +3 −2 tornado/test/web_test.py
  5. +3 −0 tox.ini
View
18 tornado/auth.py
@@ -282,10 +282,10 @@ def _oauth_request_token_url(self, callback_uri=None, extra_params=None):
consumer_token = self._oauth_consumer_token()
url = self._OAUTH_REQUEST_TOKEN_URL
args = dict(
- oauth_consumer_key=consumer_token["key"],
+ oauth_consumer_key=escape.to_basestring(consumer_token["key"]),
oauth_signature_method="HMAC-SHA1",
oauth_timestamp=str(int(time.time())),
- oauth_nonce=binascii.b2a_hex(uuid.uuid4().bytes),
+ oauth_nonce=escape.to_basestring(binascii.b2a_hex(uuid.uuid4().bytes)),
oauth_version=getattr(self, "_OAUTH_VERSION", "1.0a"),
)
if getattr(self, "_OAUTH_VERSION", "1.0a") == "1.0a":
@@ -312,7 +312,7 @@ def _on_request_token(self, authorize_url, callback_uri, response):
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.urlencode(args))
return
elif callback_uri:
args["oauth_callback"] = urlparse.urljoin(
@@ -323,11 +323,11 @@ def _oauth_access_token_url(self, request_token):
consumer_token = self._oauth_consumer_token()
url = self._OAUTH_ACCESS_TOKEN_URL
args = dict(
- oauth_consumer_key=consumer_token["key"],
- oauth_token=request_token["key"],
+ oauth_consumer_key=escape.to_basestring(consumer_token["key"]),
+ oauth_token=escape.to_basestring(request_token["key"]),
oauth_signature_method="HMAC-SHA1",
oauth_timestamp=str(int(time.time())),
- oauth_nonce=binascii.b2a_hex(uuid.uuid4().bytes),
+ oauth_nonce=escape.to_basestring(binascii.b2a_hex(uuid.uuid4().bytes)),
oauth_version=getattr(self, "_OAUTH_VERSION", "1.0a"),
)
if "verifier" in request_token:
@@ -372,11 +372,11 @@ def _oauth_request_parameters(self, url, access_token, parameters={},
"""
consumer_token = self._oauth_consumer_token()
base_args = dict(
- oauth_consumer_key=consumer_token["key"],
- oauth_token=access_token["key"],
+ oauth_consumer_key=escape.to_basestring(consumer_token["key"]),
+ oauth_token=escape.to_basestring(access_token["key"]),
oauth_signature_method="HMAC-SHA1",
oauth_timestamp=str(int(time.time())),
- oauth_nonce=binascii.b2a_hex(uuid.uuid4().bytes),
+ oauth_nonce=escape.to_basestring(binascii.b2a_hex(uuid.uuid4().bytes)),
oauth_version=getattr(self, "_OAUTH_VERSION", "1.0a"),
)
args = {}
View
22 tornado/test/options_test.py
@@ -1,14 +1,27 @@
from __future__ import absolute_import, division, with_statement
+import contextlib
import logging
import os
import re
import tempfile
import unittest
+import warnings
from tornado.escape import utf8
from tornado.options import _Options, _LogFormatter
from tornado.util import b, bytes_type
+@contextlib.contextmanager
+def ignore_bytes_warning():
+ if not hasattr(warnings, 'catch_warnings'):
+ # python 2.5 doesn't have catch_warnings, but it doesn't have
+ # BytesWarning either so there's nothing to catch.
+ yield
+ return
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', category=BytesWarning)
+ yield
+
class OptionsTest(unittest.TestCase):
def setUp(self):
@@ -56,7 +69,7 @@ def make_handler(self, filename):
# Base case: default setup without explicit encoding.
# In python 2, supports arbitrary byte strings and unicode objects
# that contain only ascii. In python 3, supports ascii-only unicode
- # strings (but byte strings will be repr'd automatically.
+ # strings (but byte strings will be repr'd automatically).
return logging.FileHandler(filename)
def get_output(self):
@@ -73,9 +86,10 @@ def test_basic_logging(self):
self.assertEqual(self.get_output(), b("foo"))
def test_bytes_logging(self):
- self.logger.error(b("\xe9"))
- # This will be "\xe9" on python 2 or "b'\xe9'" on python 3
- self.assertEqual(self.get_output(), utf8(repr(b("\xe9"))))
+ with ignore_bytes_warning():
+ # This will be "\xe9" on python 2 or "b'\xe9'" on python 3
+ self.logger.error(b("\xe9"))
+ self.assertEqual(self.get_output(), utf8(repr(b("\xe9"))))
def test_utf8_logging(self):
self.logger.error(u"\u00e9".encode("utf8"))
View
11 tornado/test/runtests.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python
from __future__ import absolute_import, division, with_statement
+import sys
import unittest
TEST_MODULES = [
@@ -53,4 +54,12 @@ def all():
module=r"tornado\..*")
import tornado.testing
- tornado.testing.main()
+ kwargs = {}
+ if sys.version_info >= (3,2):
+ # HACK: unittest.main will make its own changes to the warning
+ # configuration, which may conflict with the settings above
+ # or command-line flags like -bb. Passing warnings=False
+ # suppresses this behavior, although this looks like an implementation
+ # detail. http://bugs.python.org/issue15626
+ kwargs['warnings'] = False
+ tornado.testing.main(**kwargs)
View
5 tornado/test/web_test.py
@@ -1,6 +1,6 @@
from __future__ import absolute_import, division, with_statement
from tornado import gen
-from tornado.escape import json_decode, utf8, to_unicode, recursive_unicode, native_str
+from tornado.escape import json_decode, utf8, to_unicode, recursive_unicode, native_str, to_basestring
from tornado.iostream import IOStream
from tornado.template import DictLoader
from tornado.testing import LogTrapTestCase, AsyncHTTPTestCase
@@ -66,7 +66,8 @@ def test_cookie_tampering_future_timestamp(self):
'foo', '1234', b('5678') + timestamp),
sig)
# tamper with the cookie
- handler._cookies['foo'] = utf8('1234|5678%s|%s' % (timestamp, sig))
+ handler._cookies['foo'] = utf8('1234|5678%s|%s' % (
+ to_basestring(timestamp), to_basestring(sig)))
# it gets rejected
self.assertTrue(handler.get_secure_cookie('foo') is None)
View
3 tox.ini
@@ -83,6 +83,9 @@ deps =
[testenv:py32]
basepython = python3.2
setenv = LANG=C
+# -b turns on an extra warning when calling str(bytes), and -bb makes
+# it an error.
+commands = python -bb -m tornado.test.runtests {posargs:}
[testenv:py32-utf8]
basepython = python3.2

0 comments on commit ec49816

Please sign in to comment.