diff --git a/example/appengine_oauth.py b/example/appengine_oauth.py index 814f9b6f..c14da764 100644 --- a/example/appengine_oauth.py +++ b/example/appengine_oauth.py @@ -86,7 +86,7 @@ def is_valid(self): request = self.get_oauth_request() client = self.get_client(request) params = self._server.verify_request(request, client, None) - except Exception, e: + except Exception as e: raise e return client @@ -95,7 +95,7 @@ class SampleHandler(OAuthHandler): def get(self): try: client = self.is_valid() - except Exception, e: + except Exception as e: self.error(500) self.response.out.write(e) diff --git a/example/client.py b/example/client.py index 34f7dcb9..a55bb4ac 100644 --- a/example/client.py +++ b/example/client.py @@ -26,7 +26,7 @@ or find one that works with your web framework. """ -import httplib +import http.client import time import oauth.oauth as oauth @@ -48,13 +48,13 @@ # example client using httplib with headers class SimpleOAuthClient(oauth.OAuthClient): - def __init__(self, server, port=httplib.HTTP_PORT, request_token_url='', access_token_url='', authorization_url=''): + def __init__(self, server, port=http.client.HTTP_PORT, request_token_url='', access_token_url='', authorization_url=''): self.server = server self.port = port self.request_token_url = request_token_url self.access_token_url = access_token_url self.authorization_url = authorization_url - self.connection = httplib.HTTPConnection("%s:%d" % (self.server, self.port)) + self.connection = http.client.HTTPConnection("%s:%d" % (self.server, self.port)) def fetch_request_token(self, oauth_request): # via headers @@ -88,7 +88,7 @@ def access_resource(self, oauth_request): def run_example(): # setup - print '** OAuth Python Library Example **' + print('** OAuth Python Library Example **') client = SimpleOAuthClient(SERVER, PORT, REQUEST_TOKEN_URL, ACCESS_TOKEN_URL, AUTHORIZATION_URL) consumer = oauth.OAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET) signature_method_plaintext = oauth.OAuthSignatureMethod_PLAINTEXT() @@ -96,70 +96,70 @@ def run_example(): pause() # get request token - print '* Obtain a request token ...' + print('* Obtain a request token ...') pause() oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, callback=CALLBACK_URL, http_url=client.request_token_url) oauth_request.sign_request(signature_method_plaintext, consumer, None) - print 'REQUEST (via headers)' - print 'parameters: %s' % str(oauth_request.parameters) + print('REQUEST (via headers)') + print('parameters: %s' % str(oauth_request.parameters)) pause() token = client.fetch_request_token(oauth_request) - print 'GOT' - print 'key: %s' % str(token.key) - print 'secret: %s' % str(token.secret) - print 'callback confirmed? %s' % str(token.callback_confirmed) + print('GOT') + print('key: %s' % str(token.key)) + print('secret: %s' % str(token.secret)) + print('callback confirmed? %s' % str(token.callback_confirmed)) pause() - print '* Authorize the request token ...' + print('* Authorize the request token ...') pause() oauth_request = oauth.OAuthRequest.from_token_and_callback(token=token, http_url=client.authorization_url) - print 'REQUEST (via url query string)' - print 'parameters: %s' % str(oauth_request.parameters) + print('REQUEST (via url query string)') + print('parameters: %s' % str(oauth_request.parameters)) pause() # this will actually occur only on some callback response = client.authorize_token(oauth_request) - print 'GOT' - print response + print('GOT') + print(response) # sad way to get the verifier - import urlparse, cgi - query = urlparse.urlparse(response)[4] + import urllib.parse, cgi + query = urllib.parse.urlparse(response)[4] params = cgi.parse_qs(query, keep_blank_values=False) verifier = params['oauth_verifier'][0] - print 'verifier: %s' % verifier + print('verifier: %s' % verifier) pause() # get access token - print '* Obtain an access token ...' + print('* Obtain an access token ...') pause() oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, token=token, verifier=verifier, http_url=client.access_token_url) oauth_request.sign_request(signature_method_plaintext, consumer, token) - print 'REQUEST (via headers)' - print 'parameters: %s' % str(oauth_request.parameters) + print('REQUEST (via headers)') + print('parameters: %s' % str(oauth_request.parameters)) pause() token = client.fetch_access_token(oauth_request) - print 'GOT' - print 'key: %s' % str(token.key) - print 'secret: %s' % str(token.secret) + print('GOT') + print('key: %s' % str(token.key)) + print('secret: %s' % str(token.secret)) pause() # access some protected resources - print '* Access protected resources ...' + print('* Access protected resources ...') pause() parameters = {'file': 'vacation.jpg', 'size': 'original'} # resource specific params oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, token=token, http_method='POST', http_url=RESOURCE_URL, parameters=parameters) oauth_request.sign_request(signature_method_hmac_sha1, consumer, token) - print 'REQUEST (via post body)' - print 'parameters: %s' % str(oauth_request.parameters) + print('REQUEST (via post body)') + print('parameters: %s' % str(oauth_request.parameters)) pause() params = client.access_resource(oauth_request) - print 'GOT' - print 'non-oauth parameters: %s' % params + print('GOT') + print('non-oauth parameters: %s' % params) pause() def pause(): - print '' + print('') time.sleep(1) if __name__ == '__main__': run_example() - print 'Done.' \ No newline at end of file + print('Done.') \ No newline at end of file diff --git a/example/server.py b/example/server.py index 5986b0e2..c6bca64f 100644 --- a/example/server.py +++ b/example/server.py @@ -22,8 +22,8 @@ THE SOFTWARE. """ -from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer -import urllib +from http.server import BaseHTTPRequestHandler, HTTPServer +import urllib.request, urllib.parse, urllib.error import oauth.oauth as oauth @@ -101,7 +101,7 @@ def send_oauth_error(self, err=None): self.send_error(401, str(err.message)) # return the authenticate header header = oauth.build_authenticate_header(realm=REALM) - for k, v in header.iteritems(): + for k, v in header.items(): self.send_header(k, v) def do_GET(self): @@ -131,7 +131,7 @@ def do_GET(self): self.end_headers() # return the token self.wfile.write(token.to_string()) - except oauth.OAuthError, err: + except oauth.OAuthError as err: self.send_oauth_error(err) return @@ -148,7 +148,7 @@ def do_GET(self): self.end_headers() # return the callback url (to show server has it) self.wfile.write(token.get_callback_url()) - except oauth.OAuthError, err: + except oauth.OAuthError as err: self.send_oauth_error(err) return @@ -162,7 +162,7 @@ def do_GET(self): self.end_headers() # return the token self.wfile.write(token.to_string()) - except oauth.OAuthError, err: + except oauth.OAuthError as err: self.send_oauth_error(err) return @@ -176,7 +176,7 @@ def do_GET(self): self.end_headers() # return the extra parameters - just for something to return self.wfile.write(str(params)) - except oauth.OAuthError, err: + except oauth.OAuthError as err: self.send_oauth_error(err) return @@ -186,7 +186,7 @@ def do_POST(self): def main(): try: server = HTTPServer(('', 8080), RequestHandler) - print 'Test server running...' + print('Test server running...') server.serve_forever() except KeyboardInterrupt: server.socket.close() diff --git a/oauth2/__init__.py b/oauth2/__init__.py index e5bd03de..2e13aeee 100644 --- a/oauth2/__init__.py +++ b/oauth2/__init__.py @@ -23,16 +23,15 @@ """ import base64 -import urllib +import urllib.request, urllib.parse, urllib.error import time import random -import urlparse import hmac import binascii import httplib2 try: - from urlparse import parse_qs + from urllib.parse import parse_qs parse_qs # placate pyflakes except ImportError: # fall back for Python 2.5 @@ -45,7 +44,7 @@ # hashlib was added in Python 2.5 import sha -import _version +from . import _version __version__ = _version.__version__ @@ -87,7 +86,7 @@ def build_xoauth_string(url, consumer, token=None): request.sign_request(signing_method, consumer, token) params = [] - for k, v in sorted(request.iteritems()): + for k, v in sorted(request.items()): if v is not None: params.append('%s="%s"' % (k, escape(v))) @@ -97,12 +96,12 @@ def build_xoauth_string(url, consumer, token=None): def to_unicode(s): """ Convert to unicode, raise exception with instructive error message if s is not unicode, ascii, or utf-8. """ - if not isinstance(s, unicode): - if not isinstance(s, str): + if not isinstance(s, str): + if not isinstance(s, bytes): raise TypeError('You are required to pass either unicode or string here, not: %r (%s)' % (type(s), s)) try: s = s.decode('utf-8') - except UnicodeDecodeError, le: + except UnicodeDecodeError as le: raise TypeError('You are required to pass either a unicode object or a utf-8 string here. You passed a Python string object which contained non-utf-8: %r. The UnicodeDecodeError that resulted from attempting to interpret it as utf-8 was: %s' % (s, le,)) return s @@ -110,13 +109,13 @@ def to_utf8(s): return to_unicode(s).encode('utf-8') def to_unicode_if_string(s): - if isinstance(s, basestring): + if isinstance(s, str) or isinstance(s, bytes): return to_unicode(s) else: return s def to_utf8_if_string(s): - if isinstance(s, basestring): + if isinstance(s, str) or isinstance(s, bytes): return to_utf8(s) else: return s @@ -126,12 +125,12 @@ def to_unicode_optional_iterator(x): Raise TypeError if x is a str containing non-utf8 bytes or if x is an iterable which contains such a str. """ - if isinstance(x, basestring): + if isinstance(x, str) or isinstance(x, bytes): return to_unicode(x) try: l = list(x) - except TypeError, e: + except TypeError as e: assert 'is not iterable' in str(e) return x else: @@ -140,7 +139,7 @@ def to_unicode_optional_iterator(x): def escape(s): """Escape a URL including any /.""" s = to_unicode(s) - return urllib.quote(s.encode('utf-8'), safe='~') + return urllib.parse.quote(s.encode('utf-8'), safe='~') def generate_timestamp(): """Get seconds since epoch (UTC).""" @@ -191,7 +190,7 @@ def __str__(self): data = {'oauth_consumer_key': self.key, 'oauth_consumer_secret': self.secret} - return urllib.urlencode(data) + return urllib.parse.urlencode(data) class Token(object): @@ -235,13 +234,13 @@ def set_verifier(self, verifier=None): def get_callback_url(self): if self.callback and self.verifier: # Append the oauth_verifier. - parts = urlparse.urlparse(self.callback) + parts = urllib.parse.urlparse(self.callback) scheme, netloc, path, params, query, fragment = parts[:6] if query: query = '%s&oauth_verifier=%s' % (query, self.verifier) else: query = 'oauth_verifier=%s' % self.verifier - return urlparse.urlunparse((scheme, netloc, path, params, + return urllib.parse.urlunparse((scheme, netloc, path, params, query, fragment)) return self.callback @@ -259,7 +258,7 @@ def to_string(self): if self.callback_confirmed is not None: data['oauth_callback_confirmed'] = self.callback_confirmed - return urllib.urlencode(data) + return urllib.parse.urlencode(data) @staticmethod def from_string(s): @@ -330,7 +329,7 @@ def __init__(self, method=HTTP_METHOD, url=None, parameters=None, self.url = to_unicode(url) self.method = method if parameters is not None: - for k, v in parameters.iteritems(): + for k, v in parameters.items(): k = to_unicode(k) v = to_unicode_optional_iterator(v) self[k] = v @@ -342,7 +341,7 @@ def __init__(self, method=HTTP_METHOD, url=None, parameters=None, def url(self, value): self.__dict__['url'] = value if value is not None: - scheme, netloc, path, params, query, fragment = urlparse.urlparse(value) + scheme, netloc, path, params, query, fragment = urllib.parse.urlparse(value) # Exclude default port numbers. if scheme == 'http' and netloc[-3:] == ':80': @@ -353,7 +352,7 @@ def url(self, value): raise ValueError("Unsupported URL %s (%s)." % (value, scheme)) # Normalized URL excludes params, query, and fragment. - self.normalized_url = urlparse.urlunparse((scheme, netloc, path, None, None, None)) + self.normalized_url = urllib.parse.urlunparse((scheme, netloc, path, None, None, None)) else: self.normalized_url = None self.__dict__['url'] = None @@ -367,12 +366,12 @@ def _get_timestamp_nonce(self): def get_nonoauth_parameters(self): """Get any non-OAuth parameters.""" - return dict([(k, v) for k, v in self.iteritems() + return dict([(k, v) for k, v in self.items() if not k.startswith('oauth_')]) def to_header(self, realm=''): """Serialize as a header for an HTTPAuth request.""" - oauth_params = ((k, v) for k, v in self.items() + oauth_params = ((k, v) for k, v in list(self.items()) if k.startswith('oauth_')) stringy_params = ((k, escape(str(v))) for k, v in oauth_params) header_params = ('%s="%s"' % (k, v) for k, v in stringy_params) @@ -389,18 +388,18 @@ def to_postdata(self): # tell urlencode to deal with sequence values and map them correctly # to resulting querystring. for example self["k"] = ["v1", "v2"] will # result in 'k=v1&k=v2' and not k=%5B%27v1%27%2C+%27v2%27%5D - return urllib.urlencode(self, True).replace('+', '%20') + return urllib.parse.urlencode(self, True).replace('+', '%20') def to_url(self): """Serialize as a URL for a GET request.""" - base_url = urlparse.urlparse(self.url) + base_url = urllib.parse.urlparse(self.url) try: query = base_url.query except AttributeError: # must be python <2.5 query = base_url[4] query = parse_qs(query) - for k, v in self.items(): + for k, v in list(self.items()): query.setdefault(k, []).append(v) try: @@ -418,8 +417,8 @@ def to_url(self): fragment = base_url[5] url = (scheme, netloc, path, params, - urllib.urlencode(query, True), fragment) - return urlparse.urlunparse(url) + urllib.parse.urlencode(query, True), fragment) + return urllib.parse.urlunparse(url) def get_parameter(self, parameter): ret = self.get(parameter) @@ -431,31 +430,31 @@ def get_parameter(self, parameter): def get_normalized_parameters(self): """Return a string that contains the parameters that must be signed.""" items = [] - for key, value in self.iteritems(): + for key, value in self.items(): if key == 'oauth_signature': continue # 1.0a/9.1.1 states that kvp must be sorted by key, then by value, # so we unpack sequence values into multiple items for sorting. - if isinstance(value, basestring): + if isinstance(value, str) or isinstance(value, bytes): items.append((to_utf8_if_string(key), to_utf8(value))) else: try: value = list(value) - except TypeError, e: + except TypeError as e: assert 'is not iterable' in str(e) items.append((to_utf8_if_string(key), to_utf8_if_string(value))) else: items.extend((to_utf8_if_string(key), to_utf8_if_string(item)) for item in value) # Include any query string parameters from the provided URL - query = urlparse.urlparse(self.url)[4] + query = urllib.parse.urlparse(self.url)[4] - url_items = self._split_url_string(query).items() + url_items = list(self._split_url_string(query).items()) url_items = [(to_utf8(k), to_utf8(v)) for k, v in url_items if k != 'oauth_signature' ] items.extend(url_items) items.sort() - encoded_str = urllib.urlencode(items) + encoded_str = urllib.parse.urlencode(items) # Encode signature parameters per Oauth Core 1.0 protocol # spec draft 7, section 3.6 # (http://tools.ietf.org/html/draft-hammer-oauth-07#section-3.6) @@ -471,7 +470,7 @@ def sign_request(self, signature_method, consumer, token): # section 4.1.1 "OAuth Consumers MUST NOT include an # oauth_body_hash parameter on requests with form-encoded # request bodies." - self['oauth_body_hash'] = base64.b64encode(sha(self.body).digest()) + self['oauth_body_hash'] = base64.b64encode(sha(self.body.encode('utf8')).digest()).decode('utf-8') if 'oauth_consumer_key' not in self: self['oauth_consumer_key'] = consumer.key @@ -480,7 +479,7 @@ def sign_request(self, signature_method, consumer, token): self['oauth_token'] = token.key self['oauth_signature_method'] = signature_method.name - self['oauth_signature'] = signature_method.sign(self, consumer, token) + self['oauth_signature'] = signature_method.sign(self, consumer, token).decode('utf-8') @classmethod def make_timestamp(cls): @@ -519,7 +518,7 @@ def from_request(cls, http_method, http_url, headers=None, parameters=None, parameters.update(query_params) # URL parameters. - param_str = urlparse.urlparse(http_url)[4] # query + param_str = urllib.parse.urlparse(http_url)[4] # query url_params = cls._split_url_string(param_str) parameters.update(url_params) @@ -581,15 +580,15 @@ def _split_header(header): # Split key-value. param_parts = param.split('=', 1) # Remove quotes and unescape the value. - params[param_parts[0]] = urllib.unquote(param_parts[1].strip('\"')) + params[param_parts[0]] = urllib.parse.unquote(param_parts[1].strip('\"')) return params @staticmethod def _split_url_string(param_str): """Turn URL string into parameters.""" - parameters = parse_qs(param_str.encode('utf-8'), keep_blank_values=True) - for k, v in parameters.iteritems(): - parameters[k] = urllib.unquote(v[0]) + parameters = parse_qs(param_str, keep_blank_values=True) + for k, v in parameters.items(): + parameters[k] = urllib.parse.unquote(v[0]) return parameters @@ -642,12 +641,12 @@ def request(self, uri, method="GET", body='', headers=None, req.sign_request(self.method, self.consumer, self.token) - schema, rest = urllib.splittype(uri) + schema, rest = urllib.parse.splittype(uri) if rest.startswith('//'): hierpart = '//' else: hierpart = '' - host, rest = urllib.splithost(rest) + host, rest = urllib.parse.splithost(rest) realm = schema + ':' + hierpart + host @@ -721,7 +720,7 @@ def _get_signature_method(self, request): # Get the signature method object. signature_method = self.signature_methods[signature_method] except: - signature_method_names = ', '.join(self.signature_methods.keys()) + signature_method_names = ', '.join(list(self.signature_methods.keys())) raise Error('Signature method %s not supported try one of the following: %s' % (signature_method, signature_method_names)) return signature_method @@ -818,7 +817,7 @@ def sign(self, request, consumer, token): """Builds the base signature string.""" key, raw = self.signing_base(request, consumer, token) - hashed = hmac.new(key, raw, sha) + hashed = hmac.new(key.encode('utf-8'), raw.encode('utf-8'), sha) # Calculate the digest base 64. return binascii.b2a_base64(hashed.digest())[:-1] diff --git a/setup.py b/setup.py index acc41e17..234e9533 100755 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ if mo: mverstr = mo.group(1) else: - print "unable to find version in %s" % (VERSIONFILE,) + print("unable to find version in %s" % (VERSIONFILE,)) raise RuntimeError("if %s.py exists, it must be well-formed" % (VERSIONFILE,)) AVSRE = r"^auto_build_num *= *['\"]([^'\"]*)['\"]" mo = re.search(AVSRE, verstrline, re.M) diff --git a/tests/test_oauth.py b/tests/test_oauth.py index f95d59d5..642c294f 100644 --- a/tests/test_oauth.py +++ b/tests/test_oauth.py @@ -29,15 +29,14 @@ import oauth2 as oauth import random import time -import urllib -import urlparse -from types import ListType +import urllib.request, urllib.parse, urllib.error +import urllib.parse import mock import httplib2 # Fix for python2.5 compatibility try: - from urlparse import parse_qs, parse_qsl + from urllib.parse import parse_qs, parse_qsl except ImportError: from cgi import parse_qs, parse_qsl @@ -49,19 +48,19 @@ class TestError(unittest.TestCase): def test_message(self): try: raise oauth.Error - except oauth.Error, e: + except oauth.Error as e: self.assertEqual(e.message, 'OAuth error occurred.') msg = 'OMG THINGS BROKE!!!!' try: raise oauth.Error(msg) - except oauth.Error, e: + except oauth.Error as e: self.assertEqual(e.message, msg) def test_str(self): try: raise oauth.Error - except oauth.Error, e: + except oauth.Error as e: self.assertEquals(str(e), 'OAuth error occurred.') class TestGenerateFunctions(unittest.TestCase): @@ -257,15 +256,15 @@ def failUnlessReallyEqual(self, a, b, msg=None): class TestFuncs(unittest.TestCase): def test_to_unicode(self): - self.failUnlessRaises(TypeError, oauth.to_unicode, '\xae') - self.failUnlessRaises(TypeError, oauth.to_unicode_optional_iterator, '\xae') - self.failUnlessRaises(TypeError, oauth.to_unicode_optional_iterator, ['\xae']) + self.failUnlessRaises(TypeError, oauth.to_unicode, b'\xae') + self.failUnlessRaises(TypeError, oauth.to_unicode_optional_iterator, b'\xae') + self.failUnlessRaises(TypeError, oauth.to_unicode_optional_iterator, [b'\xae']) - self.failUnlessEqual(oauth.to_unicode(':-)'), u':-)') - self.failUnlessEqual(oauth.to_unicode(u'\u00ae'), u'\u00ae') - self.failUnlessEqual(oauth.to_unicode('\xc2\xae'), u'\u00ae') - self.failUnlessEqual(oauth.to_unicode_optional_iterator([':-)']), [u':-)']) - self.failUnlessEqual(oauth.to_unicode_optional_iterator([u'\u00ae']), [u'\u00ae']) + self.failUnlessEqual(oauth.to_unicode(b':-)'), ':-)') + self.failUnlessEqual(oauth.to_unicode('\u00ae'), '\u00ae') + self.failUnlessEqual(oauth.to_unicode(b'\xc2\xae'), '\u00ae') + self.failUnlessEqual(oauth.to_unicode_optional_iterator([b':-)']), [':-)']) + self.failUnlessEqual(oauth.to_unicode_optional_iterator(['\u00ae']), ['\u00ae']) class TestRequest(unittest.TestCase, ReallyEqualMixin): def test_setter(self): @@ -286,7 +285,7 @@ def test_deleter(self): self.fail("AttributeError should have been raised on empty url.") except AttributeError: pass - except Exception, e: + except Exception as e: self.fail(str(e)) def test_url(self): @@ -338,7 +337,7 @@ def test_no_url_set(self): def test_url_query(self): url = "https://www.google.com/m8/feeds/contacts/default/full/?alt=json&max-contacts=10" - normalized_url = urlparse.urlunparse(urlparse.urlparse(url)[:3] + (None, None, None)) + normalized_url = urllib.parse.urlunparse(urllib.parse.urlparse(url)[:3] + (None, None, None)) method = "GET" req = oauth.Request(method, url) @@ -361,12 +360,12 @@ def test_get_nonoauth_parameters(self): } other_params = { - u'foo': u'baz', - u'bar': u'foo', - u'multi': [u'FOO',u'BAR'], - u'uni_utf8': u'\xae', - u'uni_unicode': u'\u00ae', - u'uni_unicode_2': u'åÅøØ', + 'foo': 'baz', + 'bar': 'foo', + 'multi': ['FOO','BAR'], + 'uni_utf8': '\xae', + 'uni_unicode': '\u00ae', + 'uni_unicode_2': 'åÅøØ', } params = oauth_params @@ -389,7 +388,7 @@ def test_to_header(self): } req = oauth.Request("GET", realm, params) - header, value = req.to_header(realm).items()[0] + header, value = list(req.to_header(realm).items())[0] parts = value.split('OAuth ') vars = parts[1].split(', ') @@ -398,14 +397,14 @@ def test_to_header(self): res = {} for v in vars: var, val = v.split('=') - res[var] = urllib.unquote(val.strip('"')) + res[var] = urllib.parse.unquote(val.strip('"')) self.assertEquals(realm, res['realm']) del res['realm'] self.assertTrue(len(res), len(params)) - for key, val in res.items(): + for key, val in list(res.items()): self.assertEquals(val, params.get(key)) def test_to_postdata(self): @@ -426,7 +425,7 @@ def test_to_postdata(self): flat = [('multi','FOO'),('multi','BAR')] del params['multi'] - flat.extend(params.items()) + flat.extend(list(params.items())) kf = lambda x: x[0] self.assertEquals(sorted(flat, key=kf), sorted(parse_qsl(req.to_postdata()), key=kf)) @@ -444,8 +443,8 @@ def test_to_url(self): } req = oauth.Request("GET", url, params) - exp = urlparse.urlparse("%s?%s" % (url, urllib.urlencode(params))) - res = urlparse.urlparse(req.to_url()) + exp = urllib.parse.urlparse("%s?%s" % (url, urllib.parse.urlencode(params))) + res = urllib.parse.urlparse(req.to_url()) self.assertEquals(exp.scheme, res.scheme) self.assertEquals(exp.netloc, res.netloc) self.assertEquals(exp.path, res.path) @@ -469,8 +468,8 @@ def test_to_url_with_query(self): req = oauth.Request("GET", url, params) # Note: the url above already has query parameters, so append new ones with & - exp = urlparse.urlparse("%s&%s" % (url, urllib.urlencode(params))) - res = urlparse.urlparse(req.to_url()) + exp = urllib.parse.urlparse("%s&%s" % (url, urllib.parse.urlencode(params))) + res = urllib.parse.urlparse(req.to_url()) self.assertEquals(exp.scheme, res.scheme) self.assertEquals(exp.netloc, res.netloc) self.assertEquals(exp.path, res.path) @@ -486,29 +485,29 @@ def test_to_url_with_query(self): def test_signature_base_string_nonascii_nonutf8(self): consumer = oauth.Consumer('consumer_token', 'consumer_secret') - url = u'http://api.simplegeo.com:80/1.0/places/address.json?q=monkeys&category=animal&address=41+Decatur+St,+San+Francisc\u2766,+CA' + url = 'http://api.simplegeo.com:80/1.0/places/address.json?q=monkeys&category=animal&address=41+Decatur+St,+San+Francisc\u2766,+CA' req = oauth.Request("GET", url) - self.failUnlessReallyEqual(req.normalized_url, u'http://api.simplegeo.com/1.0/places/address.json') + self.failUnlessReallyEqual(req.normalized_url, 'http://api.simplegeo.com/1.0/places/address.json') req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, None) - self.failUnlessReallyEqual(req['oauth_signature'], 'WhufgeZKyYpKsI70GZaiDaYwl6g=') + self.failUnlessReallyEqual(req['oauth_signature'], b'WhufgeZKyYpKsI70GZaiDaYwl6g=') - url = 'http://api.simplegeo.com:80/1.0/places/address.json?q=monkeys&category=animal&address=41+Decatur+St,+San+Francisc\xe2\x9d\xa6,+CA' + url = b'http://api.simplegeo.com:80/1.0/places/address.json?q=monkeys&category=animal&address=41+Decatur+St,+San+Francisc\xe2\x9d\xa6,+CA' req = oauth.Request("GET", url) - self.failUnlessReallyEqual(req.normalized_url, u'http://api.simplegeo.com/1.0/places/address.json') + self.failUnlessReallyEqual(req.normalized_url, 'http://api.simplegeo.com/1.0/places/address.json') req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, None) - self.failUnlessReallyEqual(req['oauth_signature'], 'WhufgeZKyYpKsI70GZaiDaYwl6g=') + self.failUnlessReallyEqual(req['oauth_signature'], b'WhufgeZKyYpKsI70GZaiDaYwl6g=') url = 'http://api.simplegeo.com:80/1.0/places/address.json?q=monkeys&category=animal&address=41+Decatur+St,+San+Francisc%E2%9D%A6,+CA' req = oauth.Request("GET", url) - self.failUnlessReallyEqual(req.normalized_url, u'http://api.simplegeo.com/1.0/places/address.json') + self.failUnlessReallyEqual(req.normalized_url, 'http://api.simplegeo.com/1.0/places/address.json') req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, None) - self.failUnlessReallyEqual(req['oauth_signature'], 'WhufgeZKyYpKsI70GZaiDaYwl6g=') + self.failUnlessReallyEqual(req['oauth_signature'], b'WhufgeZKyYpKsI70GZaiDaYwl6g=') - url = u'http://api.simplegeo.com:80/1.0/places/address.json?q=monkeys&category=animal&address=41+Decatur+St,+San+Francisc%E2%9D%A6,+CA' + url = 'http://api.simplegeo.com:80/1.0/places/address.json?q=monkeys&category=animal&address=41+Decatur+St,+San+Francisc%E2%9D%A6,+CA' req = oauth.Request("GET", url) - self.failUnlessReallyEqual(req.normalized_url, u'http://api.simplegeo.com/1.0/places/address.json') + self.failUnlessReallyEqual(req.normalized_url, 'http://api.simplegeo.com/1.0/places/address.json') req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, None) - self.failUnlessReallyEqual(req['oauth_signature'], 'WhufgeZKyYpKsI70GZaiDaYwl6g=') + self.failUnlessReallyEqual(req['oauth_signature'], b'WhufgeZKyYpKsI70GZaiDaYwl6g=') def test_signature_base_string_with_query(self): url = "https://www.google.com/m8/feeds/contacts/default/full/?alt=json&max-contacts=10" @@ -527,7 +526,7 @@ def test_signature_base_string_with_query(self): normalized_params = parse_qsl(req.get_normalized_parameters()) self.assertTrue(len(normalized_params), len(params) + 2) normalized_params = dict(normalized_params) - for key, value in params.iteritems(): + for key, value in params.items(): if key == 'oauth_signature': continue self.assertEquals(value, normalized_params[key]) @@ -598,10 +597,10 @@ def test_get_normalized_parameters(self): 'oauth_consumer_key': "0685bd9184jfhq22", 'oauth_signature_method': "HMAC-SHA1", 'oauth_token': "ad180jjd733klru7", - 'multi': ['FOO','BAR', u'\u00ae', '\xc2\xae'], + 'multi': ['FOO','BAR', '\u00ae', b'\xc2\xae'], 'multi_same': ['FOO','FOO'], - 'uni_utf8_bytes': '\xc2\xae', - 'uni_unicode_object': u'\u00ae' + 'uni_utf8_bytes': b'\xc2\xae', + 'uni_unicode_object': '\u00ae' } req = oauth.Request("GET", url, params) @@ -629,11 +628,11 @@ def test_get_normalized_parameters_ignores_auth_signature(self): res = req.get_normalized_parameters() - self.assertNotEquals(urllib.urlencode(sorted(params.items())), res) + self.assertNotEquals(urllib.parse.urlencode(sorted(params.items())), res) foo = params.copy() del foo["oauth_signature"] - self.assertEqual(urllib.urlencode(sorted(foo.items())), res) + self.assertEqual(urllib.parse.urlencode(sorted(foo.items())), res) def test_set_signature_method(self): consumer = oauth.Consumer('key', 'secret') @@ -661,7 +660,7 @@ def test_get_normalized_string_escapes_spaces_properly(self): req = oauth.Request("GET", url, params) res = req.get_normalized_parameters() - expected = urllib.urlencode(sorted(params.items())).replace('+', '%20') + expected = urllib.parse.urlencode(sorted(params.items())).replace('+', '%20') self.assertEqual(expected, res) @mock.patch('oauth2.Request.make_timestamp') @@ -682,46 +681,46 @@ def test_request_nonutf8_bytes(self, mock_make_nonce, mock_make_timestamp): # If someone passes a sequence of bytes which is not ascii for # url, we'll raise an exception as early as possible. - url = "http://sp.example.com/\x92" # It's actually cp1252-encoding... + url = b"http://sp.example.com/\x92" # It's actually cp1252-encoding... self.assertRaises(TypeError, oauth.Request, method="GET", url=url, parameters=params) # And if they pass an unicode, then we'll use it. - url = u'http://sp.example.com/\u2019' + url = 'http://sp.example.com/\u2019' req = oauth.Request(method="GET", url=url, parameters=params) req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), con, None) - self.failUnlessReallyEqual(req['oauth_signature'], 'cMzvCkhvLL57+sTIxLITTHfkqZk=') + self.failUnlessReallyEqual(req['oauth_signature'], b'cMzvCkhvLL57+sTIxLITTHfkqZk=') # And if it is a utf-8-encoded-then-percent-encoded non-ascii # thing, we'll decode it and use it. url = "http://sp.example.com/%E2%80%99" req = oauth.Request(method="GET", url=url, parameters=params) req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), con, None) - self.failUnlessReallyEqual(req['oauth_signature'], 'yMLKOyNKC/DkyhUOb8DLSvceEWE=') + self.failUnlessReallyEqual(req['oauth_signature'], b'yMLKOyNKC/DkyhUOb8DLSvceEWE=') # Same thing with the params. url = "http://sp.example.com/" # If someone passes a sequence of bytes which is not ascii in # params, we'll raise an exception as early as possible. - params['non_oauth_thing'] = '\xae', # It's actually cp1252-encoding... + params['non_oauth_thing'] = b'\xae', # It's actually cp1252-encoding... self.assertRaises(TypeError, oauth.Request, method="GET", url=url, parameters=params) # And if they pass a unicode, then we'll use it. - params['non_oauth_thing'] = u'\u2019' + params['non_oauth_thing'] = '\u2019' req = oauth.Request(method="GET", url=url, parameters=params) req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), con, None) - self.failUnlessReallyEqual(req['oauth_signature'], '0GU50m0v60CVDB5JnoBXnvvvKx4=') + self.failUnlessReallyEqual(req['oauth_signature'], b'0GU50m0v60CVDB5JnoBXnvvvKx4=') # And if it is a utf-8-encoded non-ascii thing, we'll decode # it and use it. - params['non_oauth_thing'] = '\xc2\xae' + params['non_oauth_thing'] = b'\xc2\xae' req = oauth.Request(method="GET", url=url, parameters=params) req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), con, None) - self.failUnlessReallyEqual(req['oauth_signature'], 'pqOCu4qvRTiGiXB8Z61Jsey0pMM=') + self.failUnlessReallyEqual(req['oauth_signature'], b'pqOCu4qvRTiGiXB8Z61Jsey0pMM=') # Also if there are non-utf8 bytes in the query args. - url = "http://sp.example.com/?q=\x92" # cp1252 + url = b"http://sp.example.com/?q=\x92" # cp1252 self.assertRaises(TypeError, oauth.Request, method="GET", url=url, parameters=params) def test_request_hash_of_body(self): @@ -740,11 +739,11 @@ def test_request_hash_of_body(self): 'oauth_consumer_key': con.key } - url = u"http://www.example.com/resource" + url = "http://www.example.com/resource" req = oauth.Request(method="PUT", url=url, parameters=params, body="Hello World!", is_form_encoded=False) req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), con, None) - self.failUnlessReallyEqual(req['oauth_body_hash'], 'Lve95gjOVATpfV8EL5X4nxwjKHE=') - self.failUnlessReallyEqual(req['oauth_signature'], 't+MX8l/0S8hdbVQL99nD0X1fPnM=') + self.failUnlessReallyEqual(req['oauth_body_hash'], b'Lve95gjOVATpfV8EL5X4nxwjKHE=') + self.failUnlessReallyEqual(req['oauth_signature'], b't+MX8l/0S8hdbVQL99nD0X1fPnM=') # oauth-bodyhash.html A.1 has # '08bUFF%2Fjmp59mWB7cSgCYBUpJ0U%3D', but I don't see how that # is possible. @@ -760,8 +759,8 @@ def test_request_hash_of_body(self): req = oauth.Request(method="PUT", url=url, parameters=params, body="Hello World!", is_form_encoded=False) req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), con, None) - self.failUnlessReallyEqual(req['oauth_body_hash'], 'Lve95gjOVATpfV8EL5X4nxwjKHE=') - self.failUnlessReallyEqual(req['oauth_signature'], 'CTFmrqJIGT7NsWJ42OrujahTtTc=') + self.failUnlessReallyEqual(req['oauth_body_hash'], b'Lve95gjOVATpfV8EL5X4nxwjKHE=') + self.failUnlessReallyEqual(req['oauth_signature'], b'CTFmrqJIGT7NsWJ42OrujahTtTc=') # Appendix A.2 params = { @@ -774,8 +773,8 @@ def test_request_hash_of_body(self): req = oauth.Request(method="GET", url=url, parameters=params, is_form_encoded=False) req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), con, None) - self.failUnlessReallyEqual(req['oauth_body_hash'], '2jmj7l5rSw0yVb/vlWAYkK/YBwk=') - self.failUnlessReallyEqual(req['oauth_signature'], 'Zhl++aWSP0O3/hYQ0CuBc7jv38I=') + self.failUnlessReallyEqual(req['oauth_body_hash'], b'2jmj7l5rSw0yVb/vlWAYkK/YBwk=') + self.failUnlessReallyEqual(req['oauth_signature'], b'Zhl++aWSP0O3/hYQ0CuBc7jv38I=') def test_sign_request(self): @@ -795,36 +794,36 @@ def test_sign_request(self): req = oauth.Request(method="GET", url=url, parameters=params) methods = { - 'DX01TdHws7OninCLK9VztNTH1M4=': oauth.SignatureMethod_HMAC_SHA1(), + b'DX01TdHws7OninCLK9VztNTH1M4=': oauth.SignatureMethod_HMAC_SHA1(), 'con-test-secret&tok-test-secret': oauth.SignatureMethod_PLAINTEXT() } - for exp, method in methods.items(): + for exp, method in list(methods.items()): req.sign_request(method, con, tok) self.assertEquals(req['oauth_signature_method'], method.name) self.assertEquals(req['oauth_signature'], exp) # Also if there are non-ascii chars in the URL. - url = "http://sp.example.com/\xe2\x80\x99" # utf-8 bytes + url = b"http://sp.example.com/\xe2\x80\x99" # utf-8 bytes req = oauth.Request(method="GET", url=url, parameters=params) req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), con, tok) - self.assertEquals(req['oauth_signature'], 'loFvp5xC7YbOgd9exIO6TxB7H4s=') + self.assertEquals(req['oauth_signature'], b'loFvp5xC7YbOgd9exIO6TxB7H4s=') - url = u'http://sp.example.com/\u2019' # Python unicode object + url = 'http://sp.example.com/\u2019' # Python unicode object req = oauth.Request(method="GET", url=url, parameters=params) req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), con, tok) - self.assertEquals(req['oauth_signature'], 'loFvp5xC7YbOgd9exIO6TxB7H4s=') + self.assertEquals(req['oauth_signature'], b'loFvp5xC7YbOgd9exIO6TxB7H4s=') # Also if there are non-ascii chars in the query args. - url = "http://sp.example.com/?q=\xe2\x80\x99" # utf-8 bytes + url = b"http://sp.example.com/?q=\xe2\x80\x99" # utf-8 bytes req = oauth.Request(method="GET", url=url, parameters=params) req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), con, tok) - self.assertEquals(req['oauth_signature'], 'IBw5mfvoCsDjgpcsVKbyvsDqQaU=') + self.assertEquals(req['oauth_signature'], b'IBw5mfvoCsDjgpcsVKbyvsDqQaU=') - url = u'http://sp.example.com/?q=\u2019' # Python unicode object + url = 'http://sp.example.com/?q=\u2019' # Python unicode object req = oauth.Request(method="GET", url=url, parameters=params) req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), con, tok) - self.assertEquals(req['oauth_signature'], 'IBw5mfvoCsDjgpcsVKbyvsDqQaU=') + self.assertEquals(req['oauth_signature'], b'IBw5mfvoCsDjgpcsVKbyvsDqQaU=') def test_from_request(self): url = "http://sp.example.com/" @@ -858,12 +857,12 @@ def test_from_request(self): url, bad_headers) # Test getting from query string - qs = urllib.urlencode(params) + qs = urllib.parse.urlencode(params) req = oauth.Request.from_request("GET", url, query_string=qs) exp = parse_qs(qs, keep_blank_values=False) - for k, v in exp.iteritems(): - exp[k] = urllib.unquote(v[0]) + for k, v in exp.items(): + exp[k] = urllib.parse.unquote(v[0]) self.assertEquals(exp, req.copy()) @@ -1147,7 +1146,7 @@ def create_simple_multipart_data(self, data): boundary = '---Boundary-%d' % random.randint(1,1000) crlf = '\r\n' items = [] - for key, value in data.iteritems(): + for key, value in data.items(): items += [ '--'+boundary, 'Content-Disposition: form-data; name="%s"'%str(key), @@ -1189,7 +1188,7 @@ def test_access_token_post(self): self.assertEquals(int(resp['status']), 200) - res = dict(parse_qsl(content)) + res = dict(parse_qsl(content.decode('utf-8'))) self.assertTrue('oauth_token' in res) self.assertTrue('oauth_token_secret' in res) @@ -1197,7 +1196,7 @@ def _two_legged(self, method): client = oauth.Client(self.consumer, None) return client.request(self._uri('two_legged'), method, - body=urllib.urlencode(self.body)) + body=urllib.parse.urlencode(self.body)) def test_two_legged_post(self): """A test of a two-legged OAuth POST request.""" @@ -1225,7 +1224,7 @@ def test_multipart_post_does_not_alter_body(self, mockHttpRequest): def mockrequest(cl, ur, **kw): self.failUnless(cl is client) self.failUnless(ur is uri) - self.failUnlessEqual(frozenset(kw.keys()), frozenset(['method', 'body', 'redirections', 'connection_type', 'headers'])) + self.failUnlessEqual(frozenset(list(kw.keys())), frozenset(['method', 'body', 'redirections', 'connection_type', 'headers'])) self.failUnlessEqual(kw['body'], body) self.failUnlessEqual(kw['connection_type'], None) self.failUnlessEqual(kw['method'], 'POST') @@ -1247,7 +1246,7 @@ def test_url_with_query_string(self, mockHttpRequest): def mockrequest(cl, ur, **kw): self.failUnless(cl is client) - self.failUnlessEqual(frozenset(kw.keys()), frozenset(['method', 'body', 'redirections', 'connection_type', 'headers'])) + self.failUnlessEqual(frozenset(list(kw.keys())), frozenset(['method', 'body', 'redirections', 'connection_type', 'headers'])) self.failUnlessEqual(kw['body'], '') self.failUnlessEqual(kw['connection_type'], None) self.failUnlessEqual(kw['method'], 'GET') @@ -1257,8 +1256,8 @@ def mockrequest(cl, ur, **kw): req = oauth.Request.from_consumer_and_token(self.consumer, None, http_method='GET', http_url=uri, parameters={}) req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), self.consumer, None) - expected = parse_qsl(urlparse.urlparse(req.to_url()).query) - actual = parse_qsl(urlparse.urlparse(ur).query) + expected = parse_qsl(urllib.parse.urlparse(req.to_url()).query) + actual = parse_qsl(urllib.parse.urlparse(ur).query) self.failUnlessEqual(len(expected), len(actual)) actual = dict(actual) for key, value in expected: