diff --git a/setup.py b/setup.py index 12a6671b3..915c8997f 100644 --- a/setup.py +++ b/setup.py @@ -17,6 +17,8 @@ install_requires = [] +install_requires.append('six') + if sys.version_info < (2, 6): warnings.warn( 'Python 2.5 is no longer officially supported by Stripe. ' @@ -61,7 +63,6 @@ install_requires=install_requires, test_suite='stripe.test.all', tests_require=['unittest2', 'mock'], - use_2to3=True, classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", diff --git a/stripe/api_requestor.py b/stripe/api_requestor.py index 0caac71f1..0ce36bf31 100644 --- a/stripe/api_requestor.py +++ b/stripe/api_requestor.py @@ -2,10 +2,11 @@ import datetime import platform import time -import urllib -import urlparse import warnings +import six +from six.moves.urllib.parse import urlencode, urlsplit, urlunsplit + import stripe from stripe import error, oauth_error, http_client, version, util from stripe.multipart_data_generator import MultipartDataGenerator @@ -22,13 +23,13 @@ def _encode_datetime(dttime): def _encode_nested_dict(key, data, fmt='%s[%s]'): d = {} - for subkey, subvalue in data.iteritems(): + for subkey, subvalue in six.iteritems(data): d[fmt % (key, subkey)] = subvalue return d def _api_encode(data): - for key, value in data.iteritems(): + for key, value in six.iteritems(data): key = util.utf8(key) if value is None: continue @@ -53,12 +54,12 @@ def _api_encode(data): def _build_api_url(url, query): - scheme, netloc, path, base_query, fragment = urlparse.urlsplit(url) + scheme, netloc, path, base_query, fragment = urlsplit(url) if base_query: query = '%s&%s' % (base_query, query) - return urlparse.urlunsplit((scheme, netloc, path, query, fragment)) + return urlunsplit((scheme, netloc, path, query, fragment)) class APIRequestor(object): @@ -124,7 +125,7 @@ def encode(cls, d): 'If you need public access to this function, please email us ' 'at support@stripe.com.', DeprecationWarning) - return urllib.urlencode(list(_api_encode(d))) + return urlencode(list(_api_encode(d))) @classmethod def build_url(cls, url, params): @@ -165,7 +166,7 @@ def handle_error_response(self, rbody, rcode, resp, rheaders): # OAuth errors are a JSON object where `error` is a string. In # contrast, in API errors, `error` is a hash with sub-keys. We use # this property to distinguish between OAuth and API errors. - if isinstance(error_data, basestring): + if isinstance(error_data, six.string_types): err = self.specific_oauth_error( rbody, rcode, resp, rheaders, error_data) @@ -300,7 +301,7 @@ def request_raw(self, method, url, params=None, supplied_headers=None): abs_url = '%s%s' % (self.api_base, url) - encoded_params = urllib.urlencode(list(_api_encode(params or {}))) + encoded_params = urlencode(list(_api_encode(params or {}))) if method == 'get' or method == 'delete': if params: @@ -326,7 +327,7 @@ def request_raw(self, method, url, params=None, supplied_headers=None): headers = self.request_headers(my_api_key, method) if supplied_headers is not None: - for key, value in supplied_headers.items(): + for key, value in six.iteritems(supplied_headers): headers[key] = value util.log_info('Request to Stripe api', method=method, path=abs_url) diff --git a/stripe/api_resources/abstract/api_resource.py b/stripe/api_resources/abstract/api_resource.py index 0bf71ba66..49ca78bd3 100644 --- a/stripe/api_resources/abstract/api_resource.py +++ b/stripe/api_resources/abstract/api_resource.py @@ -1,4 +1,5 @@ -import urllib +import six +from six.moves.urllib.parse import quote_plus from stripe import error, util from stripe.stripe_object import StripeObject @@ -22,7 +23,7 @@ def class_name(cls): raise NotImplementedError( 'APIResource is an abstract class. You should perform ' 'actions on its subclasses (e.g. Charge, Customer)') - return str(urllib.quote_plus(cls.__name__.lower())) + return str(quote_plus(cls.__name__.lower())) @classmethod def class_url(cls): @@ -32,7 +33,7 @@ def class_url(cls): def instance_url(self): id = self.get('id') - if not isinstance(id, basestring): + if not isinstance(id, six.string_types): raise error.InvalidRequestError( 'Could not determine which URL to request: %s instance ' 'has invalid ID: %r, %s. ID should be of type `str` (or' @@ -40,5 +41,5 @@ def instance_url(self): id = util.utf8(id) base = self.class_url() - extn = urllib.quote_plus(id) + extn = quote_plus(id) return "%s/%s" % (base, extn) diff --git a/stripe/api_resources/abstract/nested_resource_class_methods.py b/stripe/api_resources/abstract/nested_resource_class_methods.py index 8048143bc..4bed69840 100644 --- a/stripe/api_resources/abstract/nested_resource_class_methods.py +++ b/stripe/api_resources/abstract/nested_resource_class_methods.py @@ -1,4 +1,4 @@ -import urllib +from six.moves.urllib.parse import quote_plus from stripe import api_requestor, util @@ -11,10 +11,10 @@ def nested_resource_class_methods(resource, path=None, operations=None): def wrapper(cls): def nested_resource_url(cls, id, nested_id=None): - url = "%s/%s/%s" % (cls.class_url(), urllib.quote_plus(id), - urllib.quote_plus(path)) + url = "%s/%s/%s" % (cls.class_url(), quote_plus(id), + quote_plus(path)) if nested_id is not None: - url += "/%s" % urllib.quote_plus(nested_id) + url += "/%s" % quote_plus(nested_id) return url resource_url_method = "%ss_url" % resource setattr(cls, resource_url_method, classmethod(nested_resource_url)) diff --git a/stripe/api_resources/abstract/updateable_api_resource.py b/stripe/api_resources/abstract/updateable_api_resource.py index 159b0a672..adc2bb7c1 100644 --- a/stripe/api_resources/abstract/updateable_api_resource.py +++ b/stripe/api_resources/abstract/updateable_api_resource.py @@ -1,4 +1,4 @@ -import urllib +from six.moves.urllib.parse import quote_plus from stripe import api_requestor, util from stripe.api_resources.abstract.api_resource import APIResource @@ -19,7 +19,7 @@ def _modify(cls, url, api_key=None, idempotency_key=None, @classmethod def modify(cls, sid, **params): - url = "%s/%s" % (cls.class_url(), urllib.quote_plus(util.utf8(sid))) + url = "%s/%s" % (cls.class_url(), quote_plus(util.utf8(sid))) return cls._modify(url, **params) def save(self, idempotency_key=None): diff --git a/stripe/api_resources/account.py b/stripe/api_resources/account.py index a5bdd1e94..ae38f3631 100644 --- a/stripe/api_resources/account.py +++ b/stripe/api_resources/account.py @@ -1,4 +1,4 @@ -import urllib +from six.moves.urllib.parse import quote_plus from stripe import oauth, util from stripe.api_resources.abstract import CreateableAPIResource @@ -33,7 +33,7 @@ def _build_instance_url(cls, sid): return "/v1/account" sid = util.utf8(sid) base = cls.class_url() - extn = urllib.quote_plus(sid) + extn = quote_plus(sid) return "%s/%s" % (base, extn) def instance_url(self): diff --git a/stripe/api_resources/alipay_account.py b/stripe/api_resources/alipay_account.py index 6b2624258..14b08e200 100644 --- a/stripe/api_resources/alipay_account.py +++ b/stripe/api_resources/alipay_account.py @@ -1,4 +1,4 @@ -import urllib +from six.moves.urllib.parse import quote_plus from stripe import util from stripe.api_resources.customer import Customer @@ -12,11 +12,11 @@ class AlipayAccount(UpdateableAPIResource, DeletableAPIResource): @classmethod def _build_instance_url(cls, customer, sid): token = util.utf8(sid) - extn = urllib.quote_plus(token) + extn = quote_plus(token) customer = util.utf8(customer) base = Customer.class_url() - owner_extn = urllib.quote_plus(customer) + owner_extn = quote_plus(customer) return "%s/%s/sources/%s" % (base, owner_extn, extn) diff --git a/stripe/api_resources/application_fee_refund.py b/stripe/api_resources/application_fee_refund.py index ef8748be4..d2d48a580 100644 --- a/stripe/api_resources/application_fee_refund.py +++ b/stripe/api_resources/application_fee_refund.py @@ -1,4 +1,4 @@ -import urllib +from six.moves.urllib.parse import quote_plus from stripe import util from stripe.api_resources import ApplicationFee @@ -13,8 +13,8 @@ def _build_instance_url(cls, fee, sid): fee = util.utf8(fee) sid = util.utf8(sid) base = ApplicationFee.class_url() - cust_extn = urllib.quote_plus(fee) - extn = urllib.quote_plus(sid) + cust_extn = quote_plus(fee) + extn = quote_plus(sid) return "%s/%s/refunds/%s" % (base, cust_extn, extn) @classmethod diff --git a/stripe/api_resources/bank_account.py b/stripe/api_resources/bank_account.py index 0cc435b14..fa6afaa94 100644 --- a/stripe/api_resources/bank_account.py +++ b/stripe/api_resources/bank_account.py @@ -1,4 +1,4 @@ -import urllib +from six.moves.urllib.parse import quote_plus from stripe import error, util from stripe.api_resources.account import Account @@ -13,19 +13,19 @@ class BankAccount(UpdateableAPIResource, DeletableAPIResource, VerifyMixin): def instance_url(self): token = util.utf8(self.id) - extn = urllib.quote_plus(token) + extn = quote_plus(token) if hasattr(self, 'customer'): customer = util.utf8(self.customer) base = Customer.class_url() - owner_extn = urllib.quote_plus(customer) + owner_extn = quote_plus(customer) class_base = "sources" elif hasattr(self, 'account'): account = util.utf8(self.account) base = Account.class_url() - owner_extn = urllib.quote_plus(account) + owner_extn = quote_plus(account) class_base = "external_accounts" else: diff --git a/stripe/api_resources/bitcoin_receiver.py b/stripe/api_resources/bitcoin_receiver.py index 78de6424e..5cef7edc1 100644 --- a/stripe/api_resources/bitcoin_receiver.py +++ b/stripe/api_resources/bitcoin_receiver.py @@ -1,4 +1,4 @@ -import urllib +from six.moves.urllib.parse import quote_plus from stripe import util from stripe.api_resources.customer import Customer @@ -14,12 +14,12 @@ class BitcoinReceiver(CreateableAPIResource, UpdateableAPIResource, def instance_url(self): token = util.utf8(self.id) - extn = urllib.quote_plus(token) + extn = quote_plus(token) if hasattr(self, 'customer'): customer = util.utf8(self.customer) base = Customer.class_url() - cust_extn = urllib.quote_plus(customer) + cust_extn = quote_plus(customer) return "%s/%s/sources/%s" % (base, cust_extn, extn) else: base = BitcoinReceiver.class_url() diff --git a/stripe/api_resources/card.py b/stripe/api_resources/card.py index 76e86297e..4150204b4 100644 --- a/stripe/api_resources/card.py +++ b/stripe/api_resources/card.py @@ -1,4 +1,4 @@ -import urllib +from six.moves.urllib.parse import quote_plus from stripe import error, util from stripe.api_resources.account import Account @@ -13,26 +13,26 @@ class Card(UpdateableAPIResource, DeletableAPIResource): def instance_url(self): token = util.utf8(self.id) - extn = urllib.quote_plus(token) + extn = quote_plus(token) if hasattr(self, 'customer'): customer = util.utf8(self.customer) base = Customer.class_url() - owner_extn = urllib.quote_plus(customer) + owner_extn = quote_plus(customer) class_base = "sources" elif hasattr(self, 'recipient'): recipient = util.utf8(self.recipient) base = Recipient.class_url() - owner_extn = urllib.quote_plus(recipient) + owner_extn = quote_plus(recipient) class_base = "cards" elif hasattr(self, 'account'): account = util.utf8(self.account) base = Account.class_url() - owner_extn = urllib.quote_plus(account) + owner_extn = quote_plus(account) class_base = "external_accounts" else: diff --git a/stripe/api_resources/list_object.py b/stripe/api_resources/list_object.py index 1672ab3cd..a9afb5793 100644 --- a/stripe/api_resources/list_object.py +++ b/stripe/api_resources/list_object.py @@ -1,6 +1,7 @@ -import urllib import warnings +from six.moves.urllib.parse import quote_plus + from stripe import util from stripe.stripe_object import StripeObject @@ -41,7 +42,7 @@ def create(self, idempotency_key=None, **params): def retrieve(self, id, **params): base = self.get('url') id = util.utf8(id) - extn = urllib.quote_plus(id) + extn = quote_plus(id) url = "%s/%s" % (base, extn) return self.request('get', url, params) diff --git a/stripe/api_resources/reversal.py b/stripe/api_resources/reversal.py index 61cbf4d49..f267fb9bd 100644 --- a/stripe/api_resources/reversal.py +++ b/stripe/api_resources/reversal.py @@ -1,4 +1,4 @@ -import urllib +from six.moves.urllib.parse import quote_plus from stripe import util from stripe.api_resources.transfer import Transfer @@ -12,8 +12,8 @@ def instance_url(self): token = util.utf8(self.id) transfer = util.utf8(self.transfer) base = Transfer.class_url() - cust_extn = urllib.quote_plus(transfer) - extn = urllib.quote_plus(token) + cust_extn = quote_plus(transfer) + extn = quote_plus(token) return "%s/%s/reversals/%s" % (base, cust_extn, extn) @classmethod diff --git a/stripe/api_resources/source.py b/stripe/api_resources/source.py index 11ac7ba3b..5cecedbdf 100644 --- a/stripe/api_resources/source.py +++ b/stripe/api_resources/source.py @@ -1,6 +1,7 @@ -import urllib import warnings +from six.moves.urllib.parse import quote_plus + from stripe import util from stripe.api_resources import Customer from stripe.api_resources.abstract import CreateableAPIResource @@ -13,10 +14,10 @@ class Source(CreateableAPIResource, UpdateableAPIResource, VerifyMixin): def detach(self, **params): if hasattr(self, 'customer') and self.customer: - extn = urllib.quote_plus(util.utf8(self.id)) + extn = quote_plus(util.utf8(self.id)) customer = util.utf8(self.customer) base = Customer.class_url() - owner_extn = urllib.quote_plus(customer) + owner_extn = quote_plus(customer) url = "%s/%s/sources/%s" % (base, owner_extn, extn) self.refresh_from(self.request('delete', url, params)) diff --git a/stripe/error.py b/stripe/error.py index 748c51e52..4a6194db7 100644 --- a/stripe/error.py +++ b/stripe/error.py @@ -1,5 +1,5 @@ # Exceptions -import sys +import six class StripeError(Exception): @@ -29,7 +29,7 @@ def __unicode__(self): else: return self._message - if sys.version_info > (3, 0): + if six.PY3: def __str__(self): return self.__unicode__() else: diff --git a/stripe/http_client.py b/stripe/http_client.py index 3b6f4d0e6..c929fafa5 100644 --- a/stripe/http_client.py +++ b/stripe/http_client.py @@ -4,6 +4,8 @@ import warnings import email +import six + from stripe import error, util # - Requests is the preferred HTTP library @@ -11,7 +13,7 @@ # - Use Pycurl if it's there (at least it verifies SSL certs) # - Fall back to urllib2 with a warning if needed try: - import urllib2 + from six.moves import urllib except ImportError: # Try to load in urllib2, but don't sweat it if it's not available. pass @@ -52,7 +54,7 @@ urlfetch = None # proxy support for the pycurl client -from urlparse import urlparse +from six.moves.urllib.parse import urlparse def new_default_http_client(*args, **kwargs): @@ -240,7 +242,7 @@ def parse_headers(self, data): return {} raw_headers = data.split('\r\n', 1)[1] headers = email.message_from_string(raw_headers) - return dict((k.lower(), v) for k, v in dict(headers).iteritems()) + return dict((k.lower(), v) for k, v in six.iteritems(dict(headers))) def request(self, method, url, headers, post_data=None): b = util.io.BytesIO() @@ -281,8 +283,10 @@ def request(self, method, url, headers, post_data=None): self._curl.setopt(pycurl.NOSIGNAL, 1) self._curl.setopt(pycurl.CONNECTTIMEOUT, 30) self._curl.setopt(pycurl.TIMEOUT, 80) - self._curl.setopt(pycurl.HTTPHEADER, ['%s: %s' % (k, v) - for k, v in headers.iteritems()]) + self._curl.setopt( + pycurl.HTTPHEADER, + ['%s: %s' % (k, v) for k, v in six.iteritems(dict(headers))] + ) if self._verify_ssl_certs: self._curl.setopt(pycurl.CAINFO, os.path.join( os.path.dirname(__file__), 'data/ca-certificates.crt')) @@ -335,10 +339,7 @@ def _get_proxy(self, url): class Urllib2Client(HTTPClient): - if sys.version_info >= (3, 0): - name = 'urllib.request' - else: - name = 'urllib2' + name = 'urllib.request' def __init__(self, verify_ssl_certs=True, proxy=None): super(Urllib2Client, self).__init__( @@ -346,14 +347,14 @@ def __init__(self, verify_ssl_certs=True, proxy=None): # prepare and cache proxy tied opener here self._opener = None if self._proxy: - proxy = urllib2.ProxyHandler(self._proxy) - self._opener = urllib2.build_opener(proxy) + proxy = urllib.request.ProxyHandler(self._proxy) + self._opener = urllib.request.build_opener(proxy) def request(self, method, url, headers, post_data=None): - if sys.version_info >= (3, 0) and isinstance(post_data, basestring): + if six.PY3 and isinstance(post_data, six.string_types): post_data = post_data.encode('utf-8') - req = urllib2.Request(url, post_data, headers) + req = urllib.request.Request(url, post_data, headers) if method not in ('get', 'post'): req.get_method = lambda: method.upper() @@ -363,17 +364,17 @@ def request(self, method, url, headers, post_data=None): # otherwise, fall to the default urllib opener. response = self._opener.open(req) \ if self._opener \ - else urllib2.urlopen(req) + else urllib.request.urlopen(req) rbody = response.read() rcode = response.code headers = dict(response.info()) - except urllib2.HTTPError as e: + except urllib.error.HTTPError as e: rcode = e.code rbody = e.read() headers = dict(e.info()) - except (urllib2.URLError, ValueError) as e: + except (urllib.error.URLError, ValueError) as e: self._handle_request_error(e) - lh = dict((k.lower(), v) for k, v in dict(headers).iteritems()) + lh = dict((k.lower(), v) for k, v in six.iteritems(dict(headers))) return rbody, rcode, lh def _handle_request_error(self, e): diff --git a/stripe/multipart_data_generator.py b/stripe/multipart_data_generator.py index d07d5d4ab..46fe108e5 100644 --- a/stripe/multipart_data_generator.py +++ b/stripe/multipart_data_generator.py @@ -1,7 +1,8 @@ import random -import sys import io +import six + class MultipartDataGenerator(object): def __init__(self, chunk_size=1028): @@ -11,7 +12,7 @@ def __init__(self, chunk_size=1028): self.chunk_size = chunk_size def add_params(self, params): - for key, value in params.iteritems(): + for key, value in six.iteritems(params): if value is None: continue @@ -50,7 +51,7 @@ def get_post_data(self): return self.data.getvalue() def _write(self, value): - if sys.version_info < (3,): + if six.PY2: binary_type = str text_type = unicode else: diff --git a/stripe/oauth.py b/stripe/oauth.py index 0e63fd7d6..9d9ad4332 100644 --- a/stripe/oauth.py +++ b/stripe/oauth.py @@ -1,4 +1,4 @@ -import urllib +from six.moves.urllib.parse import urlencode from stripe import api_requestor, connect_api_base, error @@ -30,7 +30,7 @@ def authorize_url(**params): OAuth._set_client_id(params) if 'response_type' not in params: params['response_type'] = 'code' - query = urllib.urlencode(list(api_requestor._api_encode(params))) + query = urlencode(list(api_requestor._api_encode(params))) url = connect_api_base + path + '?' + query return url diff --git a/stripe/stripe_object.py b/stripe/stripe_object.py index b86435369..b43c8b6e7 100644 --- a/stripe/stripe_object.py +++ b/stripe/stripe_object.py @@ -1,7 +1,8 @@ -import sys import warnings from copy import deepcopy +import six + import stripe from stripe import api_requestor, util @@ -104,7 +105,7 @@ def __getitem__(self, k): "the result returned by Stripe's API, probably as a " "result of a save(). The attributes currently " "available on this object are: %s" % - (k, k, ', '.join(self.keys()))) + (k, k, ', '.join(list(self.keys())))) else: raise err @@ -169,7 +170,7 @@ def refresh_from(self, values, api_key=None, partial=False, self._transient_values = self._transient_values - set(values) - for k, v in values.iteritems(): + for k, v in six.iteritems(values): super(StripeObject, self).__setitem__( k, util.convert_to_stripe_object(v, api_key, stripe_version, stripe_account)) @@ -195,16 +196,16 @@ def request(self, method, url, params=None, headers=None): def __repr__(self): ident_parts = [type(self).__name__] - if isinstance(self.get('object'), basestring): + if isinstance(self.get('object'), six.string_types): ident_parts.append(self.get('object')) - if isinstance(self.get('id'), basestring): + if isinstance(self.get('id'), six.string_types): ident_parts.append('id=%s' % (self.get('id'),)) unicode_repr = '<%s at %s> JSON: %s' % ( ' '.join(ident_parts), hex(id(self)), str(self)) - if sys.version_info[0] < 3: + if six.PY2: return unicode_repr.encode('utf-8') else: return unicode_repr @@ -230,7 +231,7 @@ def serialize(self, previous): unsaved_keys = self._unsaved_values or set() previous = previous or self._previous or {} - for k, v in self.items(): + for k, v in six.iteritems(self): if k == 'id' or (isinstance(k, str) and k.startswith('_')): continue elif isinstance(v, stripe.api_resources.abstract.APIResource): @@ -256,7 +257,7 @@ def __copy__(self): copied._retrieve_params = self._retrieve_params - for k, v in self.items(): + for k, v in six.iteritems(self): # Call parent's __setitem__ to avoid checks that we've added in the # overridden version that can throw exceptions. super(StripeObject, copied).__setitem__(k, v) @@ -272,7 +273,7 @@ def __deepcopy__(self, memo): copied = self.__copy__() memo[id(self)] = copied - for k, v in self.items(): + for k, v in six.iteritems(self): # Call parent's __setitem__ to avoid checks that we've added in the # overridden version that can throw exceptions. super(StripeObject, copied).__setitem__(k, deepcopy(v, memo)) diff --git a/stripe/test/helper.py b/stripe/test/helper.py index c28495803..b6e3222a0 100644 --- a/stripe/test/helper.py +++ b/stripe/test/helper.py @@ -2,9 +2,10 @@ import os import random import string -import sys import unittest2 +import six + from mock import patch, Mock import stripe @@ -54,12 +55,7 @@ def tearDown(self): class StripeUnitTestCase(StripeTestCase): - REQUEST_LIBRARIES = ['urlfetch', 'requests', 'pycurl'] - - if sys.version_info >= (3, 0): - REQUEST_LIBRARIES.append('urllib.request') - else: - REQUEST_LIBRARIES.append('urllib2') + REQUEST_LIBRARIES = ['urlfetch', 'requests', 'pycurl', 'urllib.request'] def setUp(self): super(StripeUnitTestCase, self).setUp() @@ -75,7 +71,7 @@ def setUp(self): def tearDown(self): super(StripeUnitTestCase, self).tearDown() - for patcher in self.request_patchers.itervalues(): + for patcher in six.itervalues(self.request_patchers): patcher.stop() diff --git a/stripe/test/test_api_requestor.py b/stripe/test/test_api_requestor.py index b699b842d..053474eb9 100644 --- a/stripe/test/test_api_requestor.py +++ b/stripe/test/test_api_requestor.py @@ -1,6 +1,10 @@ +from __future__ import print_function + import datetime import unittest2 -import urlparse + +import six +from six.moves.urllib.parse import urlsplit from mock import Mock, ANY @@ -49,7 +53,7 @@ def __eq__(self, other): self._extra_match(other)) def _keys_match(self, other): - expected_keys = list(set(self.EXP_KEYS + self.extra.keys())) + expected_keys = list(set(self.EXP_KEYS + list(self.extra.keys()))) if self.request_method is not None and self.request_method in \ self.METHOD_EXTRA_KEYS: expected_keys.extend(self.METHOD_EXTRA_KEYS[self.request_method]) @@ -74,7 +78,7 @@ def _x_stripe_ua_contains_app_info(self, other): return True def _extra_match(self, other): - for k, v in self.extra.iteritems(): + for k, v in six.iteritems(self.extra): if other[k] != v: return False @@ -87,7 +91,7 @@ def __init__(self, expected): self.expected = sorted(expected) def __eq__(self, other): - query = urlparse.urlsplit(other).query or other + query = urlsplit(other).query or other parsed = stripe.util.parse_qsl(query) return self.expected == sorted(parsed) @@ -96,17 +100,17 @@ def __eq__(self, other): class UrlMatcher(object): def __init__(self, expected): - self.exp_parts = urlparse.urlsplit(expected) + self.exp_parts = urlsplit(expected) def __eq__(self, other): - other_parts = urlparse.urlsplit(other) + other_parts = urlsplit(other) for part in ('scheme', 'netloc', 'path', 'fragment'): expected = getattr(self.exp_parts, part) actual = getattr(other_parts, part) if expected != actual: - print 'Expected %s "%s" but got "%s"' % ( - part, expected, actual) + print('Expected %s "%s" but got "%s"' % ( + part, expected, actual)) return False q_matcher = QueryMatcher(stripe.util.parse_qsl(self.exp_parts.query)) @@ -222,7 +226,7 @@ def test_param_encoding(self): self.requestor.request('get', '', self.ENCODE_INPUTS) expectation = [] - for type_, values in self.ENCODE_EXPECTATIONS.iteritems(): + for type_, values in six.iteritems(self.ENCODE_EXPECTATIONS): expectation.extend([(k % (type_,), str(v)) for k, v in values]) self.check_call('get', QueryMatcher(expectation)) diff --git a/stripe/test/test_error.py b/stripe/test/test_error.py index 200bfe6a7..5fe502196 100644 --- a/stripe/test/test_error.py +++ b/stripe/test/test_error.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -import sys - import unittest2 +import six + from stripe import StripeError from stripe.test.helper import StripeUnitTestCase @@ -11,7 +11,7 @@ class StripeErrorTests(StripeUnitTestCase): def test_formatting(self): err = StripeError(u'öre') - if sys.version_info > (3, 0): + if six.PY3: assert str(err) == u'öre' else: assert str(err) == '\xc3\xb6re' @@ -19,7 +19,7 @@ def test_formatting(self): def test_formatting_with_request_id(self): err = StripeError(u'öre', headers={'request-id': '123'}) - if sys.version_info > (3, 0): + if six.PY3: assert str(err) == u'Request 123: öre' else: assert str(err) == 'Request 123: \xc3\xb6re' @@ -27,7 +27,7 @@ def test_formatting_with_request_id(self): def test_formatting_with_none(self): err = StripeError(None, headers={'request-id': '123'}) - if sys.version_info > (3, 0): + if six.PY3: assert str(err) == u'Request 123: ' else: assert str(err) == 'Request 123: ' diff --git a/stripe/test/test_http_client.py b/stripe/test/test_http_client.py index 2cc5be4ca..d9180d40c 100644 --- a/stripe/test/test_http_client.py +++ b/stripe/test/test_http_client.py @@ -1,8 +1,9 @@ -import sys import unittest2 from mock import MagicMock, Mock, patch +import six + import stripe from stripe.test.helper import StripeUnitTestCase @@ -219,7 +220,7 @@ def mock_error(self, mock): mock.build_opener.reset_mock() def check_call(self, mock, meth, url, post_data, headers): - if sys.version_info >= (3, 0) and isinstance(post_data, basestring): + if six.PY3 and isinstance(post_data, six.string_types): post_data = post_data.encode('utf-8') mock.Request.assert_called_with(url, post_data, headers) diff --git a/stripe/test/test_integration.py b/stripe/test/test_integration.py index ca1dc720f..58fc09f5b 100644 --- a/stripe/test/test_integration.py +++ b/stripe/test/test_integration.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- import os -import sys import unittest2 import stripe +import six + from mock import patch from stripe.test.helper import (StripeTestCase, DUMMY_CHARGE) @@ -106,7 +107,7 @@ class PycurlFunctionalTests(FunctionalTests): def setUp(self): if not os.environ.get('STRIPE_TEST_PYCURL'): self.skipTest('Pycurl skipped as STRIPE_TEST_PYCURL is not set') - if sys.version_info >= (3, 0): + if six.PY3: self.skipTest('Pycurl is not supported in Python 3') else: super(PycurlFunctionalTests, self).setUp() @@ -123,7 +124,7 @@ def test_invalid_credentials(self): stripe.Customer.create() except stripe.error.AuthenticationError as e: self.assertEqual(401, e.http_status) - self.assertTrue(isinstance(e.http_body, basestring)) + self.assertTrue(isinstance(e.http_body, six.string_types)) self.assertTrue(isinstance(e.json_body, dict)) # Note that an invalid API key bypasses many of the standard # facilities in the API server so currently no Request ID is @@ -140,7 +141,7 @@ def test_declined_card_props(self): source='tok_chargeDeclinedExpiredCard') except stripe.error.CardError as e: self.assertEqual(402, e.http_status) - self.assertTrue(isinstance(e.http_body, basestring)) + self.assertTrue(isinstance(e.http_body, six.string_types)) self.assertTrue(isinstance(e.json_body, dict)) self.assertTrue(e.request_id.startswith('req_')) @@ -152,7 +153,7 @@ def test_nonexistent_object(self): stripe.Charge.retrieve('invalid') except stripe.error.InvalidRequestError as e: self.assertEqual(404, e.http_status) - self.assertTrue(isinstance(e.http_body, basestring)) + self.assertTrue(isinstance(e.http_body, six.string_types)) self.assertTrue(isinstance(e.json_body, dict)) self.assertTrue(e.request_id.startswith('req_')) @@ -161,7 +162,7 @@ def test_invalid_data(self): stripe.Charge.create() except stripe.error.InvalidRequestError as e: self.assertEqual(400, e.http_status) - self.assertTrue(isinstance(e.http_body, basestring)) + self.assertTrue(isinstance(e.http_body, six.string_types)) self.assertTrue(isinstance(e.json_body, dict)) self.assertTrue(e.request_id.startswith('req_')) diff --git a/stripe/test/test_multipart_data_generator.py b/stripe/test/test_multipart_data_generator.py index 94a909e2f..a2488df43 100644 --- a/stripe/test/test_multipart_data_generator.py +++ b/stripe/test/test_multipart_data_generator.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- import re -import sys -import StringIO + +import six from stripe.multipart_data_generator import MultipartDataGenerator from stripe.test.helper import StripeTestCase @@ -20,7 +20,7 @@ def run_test_multipart_data_with_file(self, test_file): generator.add_params(params) http_body = generator.get_post_data() - if sys.version_info >= (3,): + if six.PY3: http_body = http_body.decode('utf-8') self.assertTrue(re.search( @@ -39,7 +39,7 @@ def run_test_multipart_data_with_file(self, test_file): test_file.seek(0) file_contents = test_file.read() - if sys.version_info >= (3,) and isinstance(file_contents, bytes): + if six.PY3 and isinstance(file_contents, bytes): file_contents = file_contents.decode('utf-8') self.assertNotEqual(-1, http_body.find(file_contents)) @@ -53,5 +53,5 @@ def test_multipart_data_file_binary(self): self.run_test_multipart_data_with_file(test_file) def test_multipart_data_stringio(self): - string = StringIO.StringIO("foo") + string = six.StringIO("foo") self.run_test_multipart_data_with_file(string) diff --git a/stripe/test/test_oauth.py b/stripe/test/test_oauth.py index 6175118e9..d69846022 100644 --- a/stripe/test/test_oauth.py +++ b/stripe/test/test_oauth.py @@ -1,4 +1,4 @@ -import urlparse +from six.moves.urllib.parse import parse_qs, urlparse import stripe from stripe.test.helper import StripeApiTestCase @@ -26,8 +26,8 @@ def test_authorize_url(self): 'country': 'US', }) - o = urlparse.urlparse(url) - params = urlparse.parse_qs(o.query) + o = urlparse(url) + params = parse_qs(o.query) self.assertEqual('https', o.scheme) self.assertEqual('connect.stripe.com', o.netloc) diff --git a/stripe/test/test_stripe_object.py b/stripe/test/test_stripe_object.py index c60aca631..679324b6c 100644 --- a/stripe/test/test_stripe_object.py +++ b/stripe/test/test_stripe_object.py @@ -1,7 +1,8 @@ import pickle -import sys from copy import copy, deepcopy +import six + import stripe from stripe import util from stripe.test.helper import StripeUnitTestCase @@ -160,8 +161,8 @@ def test_to_json(self): def check_invoice_data(self, data): # Check rough structure - self.assertEqual(20, len(data.keys())) - self.assertEqual(3, len(data['lines'].keys())) + self.assertEqual(20, len(list(data.keys()))) + self.assertEqual(3, len(list(data['lines'].keys()))) self.assertEqual(0, len(data['lines']['invoiceitems'])) self.assertEqual(1, len(data['lines']['subscriptions'])) @@ -180,7 +181,7 @@ def test_repr(self): res = repr(obj) - if sys.version_info[0] < 3: + if six.PY2: res = unicode(repr(obj), 'utf-8') self.assertTrue(u'