diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5dbc62248..433517a23 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -74,7 +74,6 @@ jobs: "3.8", "3.9", "3.10", - "pypy-2.7", "pypy-3.7", "pypy-3.8", ] diff --git a/README.md b/README.md index 036b1e2ac..e01f6bb0a 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,14 @@ python setup.py install ### Requirements -- Python 2.7+ or Python 3.6+ (PyPy supported) +- Python 3.6+ (PyPy supported) + +#### Python 2.7 deprecation + +[The Python Software Foundation (PSF)](https://www.python.org/psf-landing/) community [announced the end of support of Python 2](https://www.python.org/doc/sunset-python-2/) on 01 January 2020. +Starting with version 6.0.0 Stripe SDK Python packages will no longer support Python 2.7. To continue to get new features and security updates, please make sure to update your Python runtime to Python 3.6+. + +The last version of the Stripe SDK that supports Python 2.7 is 5.5.0. ## Usage @@ -162,7 +169,7 @@ There are a few options for enabling it: ### Accessing response code and headers -You can access the HTTP response code and headers using the `last_response` property of the returned resource. +You can access the HTTP response code and headers using the `last_response` property of the returned resource. ```python customer = stripe.Customer.retrieve( diff --git a/setup.py b/setup.py index 2f07e5741..c3b74bfc3 100644 --- a/setup.py +++ b/setup.py @@ -32,9 +32,8 @@ zip_safe=False, install_requires=[ 'requests >= 2.20; python_version >= "3.0"', - 'requests[security] >= 2.20; python_version < "3.0"', ], - python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", + python_requires=">=3.6", project_urls={ "Bug Tracker": "https://github.com/stripe/stripe-python/issues", "Changes": "https://github.com/stripe/stripe-python/blob/master/CHANGELOG.md", @@ -47,8 +46,6 @@ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", diff --git a/stripe/__init__.py b/stripe/__init__.py index d6ae0912b..ac6cf74d7 100644 --- a/stripe/__init__.py +++ b/stripe/__init__.py @@ -10,13 +10,14 @@ # Andrew Metcalf # Configuration variables +from stripe.api_version import _ApiVersion api_key = None client_id = None api_base = "https://api.stripe.com" connect_api_base = "https://connect.stripe.com" upload_api_base = "https://files.stripe.com" -api_version = None +api_version = _ApiVersion.CURRENT verify_ssl_certs = True proxy = None default_http_client = None diff --git a/stripe/api_requestor.py b/stripe/api_requestor.py index 32f295d2e..2e9e9e904 100644 --- a/stripe/api_requestor.py +++ b/stripe/api_requestor.py @@ -10,9 +10,9 @@ from collections import OrderedDict import stripe -from stripe import error, oauth_error, http_client, version, util, six +from stripe import error, oauth_error, http_client, version, util from stripe.multipart_data_generator import MultipartDataGenerator -from stripe.six.moves.urllib.parse import urlencode, urlsplit, urlunsplit +from urllib.parse import urlencode, urlsplit, urlunsplit from stripe.stripe_response import StripeResponse, StripeStreamResponse @@ -27,14 +27,13 @@ def _encode_datetime(dttime): def _encode_nested_dict(key, data, fmt="%s[%s]"): d = OrderedDict() - for subkey, subvalue in six.iteritems(data): + for subkey, subvalue in data.items(): d[fmt % (key, subkey)] = subvalue return d def _api_encode(data): - for key, value in six.iteritems(data): - key = util.utf8(key) + for key, value in data.items(): if value is None: continue elif hasattr(value, "stripe_id"): @@ -46,7 +45,7 @@ def _api_encode(data): for k, v in _api_encode(subdict): yield (k, v) else: - yield ("%s[%d]" % (key, i), util.utf8(sv)) + yield ("%s[%d]" % (key, i), sv) elif isinstance(value, dict): subdict = _encode_nested_dict(key, value) for subkey, subvalue in _api_encode(subdict): @@ -54,7 +53,7 @@ def _api_encode(data): elif isinstance(value, datetime.datetime): yield (key, _encode_datetime(value)) else: - yield (key, util.utf8(value)) + yield (key, value) def _build_api_url(url, query): @@ -146,7 +145,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, six.string_types): + if isinstance(error_data, str): err = self.specific_oauth_error( rbody, rcode, resp, rheaders, error_data ) @@ -344,7 +343,7 @@ def request_raw( headers = self.request_headers(my_api_key, method) if supplied_headers is not None: - for key, value in six.iteritems(supplied_headers): + for key, value in supplied_headers.items(): headers[key] = value util.log_info("Request to Stripe api", method=method, path=abs_url) diff --git a/stripe/api_resources/abstract/__init__.py b/stripe/api_resources/abstract/__init__.py index 047694ae1..7f333cf28 100644 --- a/stripe/api_resources/abstract/__init__.py +++ b/stripe/api_resources/abstract/__init__.py @@ -27,7 +27,6 @@ from stripe.api_resources.abstract.custom_method import custom_method from stripe.api_resources.abstract.test_helpers import ( - test_helpers, APIResourceTestHelpers, ) diff --git a/stripe/api_resources/abstract/api_resource.py b/stripe/api_resources/abstract/api_resource.py index c2bcd8c61..55780420e 100644 --- a/stripe/api_resources/abstract/api_resource.py +++ b/stripe/api_resources/abstract/api_resource.py @@ -1,8 +1,8 @@ from __future__ import absolute_import, division, print_function -from stripe import api_requestor, error, util, six +from stripe import api_requestor, error, util from stripe.stripe_object import StripeObject -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class APIResource(StripeObject): @@ -30,7 +30,7 @@ def class_url(cls): def instance_url(self): id = self.get("id") - if not isinstance(id, six.string_types): + if not isinstance(id, str): raise error.InvalidRequestError( "Could not determine which URL to request: %s instance " "has invalid ID: %r, %s. ID should be of type `str` (or" @@ -38,7 +38,6 @@ def instance_url(self): "id", ) - id = util.utf8(id) base = self.class_url() extn = quote_plus(id) return "%s/%s" % (base, extn) diff --git a/stripe/api_resources/abstract/custom_method.py b/stripe/api_resources/abstract/custom_method.py index 67be6e2f7..3983bbc66 100644 --- a/stripe/api_resources/abstract/custom_method.py +++ b/stripe/api_resources/abstract/custom_method.py @@ -1,7 +1,7 @@ from __future__ import absolute_import, division, print_function from stripe import util -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus def custom_method(name, http_verb, http_path=None, is_streaming=False): @@ -17,7 +17,7 @@ def wrapper(cls): def custom_method_request(cls, sid, **params): url = "%s/%s/%s" % ( cls.class_url(), - quote_plus(util.utf8(sid)), + quote_plus(sid), http_path, ) obj = cls._static_request(http_verb, url, params=params) @@ -32,7 +32,7 @@ def custom_method_request(cls, sid, **params): def custom_method_request_stream(cls, sid, **params): url = "%s/%s/%s" % ( cls.class_url(), - quote_plus(util.utf8(sid)), + quote_plus(sid), http_path, ) return cls._static_request_stream(http_verb, url, params=params) diff --git a/stripe/api_resources/abstract/deletable_api_resource.py b/stripe/api_resources/abstract/deletable_api_resource.py index fe9473df1..955738711 100644 --- a/stripe/api_resources/abstract/deletable_api_resource.py +++ b/stripe/api_resources/abstract/deletable_api_resource.py @@ -2,13 +2,13 @@ from stripe import util from stripe.api_resources.abstract.api_resource import APIResource -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class DeletableAPIResource(APIResource): @classmethod def _cls_delete(cls, sid, **params): - url = "%s/%s" % (cls.class_url(), quote_plus(util.utf8(sid))) + url = "%s/%s" % (cls.class_url(), quote_plus(sid)) return cls._static_request("delete", url, params=params) @util.class_method_variant("_cls_delete") diff --git a/stripe/api_resources/abstract/nested_resource_class_methods.py b/stripe/api_resources/abstract/nested_resource_class_methods.py index 2065c1ce5..a0b2bc412 100644 --- a/stripe/api_resources/abstract/nested_resource_class_methods.py +++ b/stripe/api_resources/abstract/nested_resource_class_methods.py @@ -1,6 +1,6 @@ from __future__ import absolute_import, division, print_function -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus from stripe.api_resources.abstract import APIResource diff --git a/stripe/api_resources/abstract/test_helpers.py b/stripe/api_resources/abstract/test_helpers.py index 735c30887..8696586b1 100644 --- a/stripe/api_resources/abstract/test_helpers.py +++ b/stripe/api_resources/abstract/test_helpers.py @@ -1,8 +1,7 @@ from __future__ import absolute_import, division, print_function -from stripe import error, util, six -from stripe.six.moves.urllib.parse import quote_plus -from stripe.api_resources.abstract import APIResource +from stripe import error +from urllib.parse import quote_plus class APIResourceTestHelpers: @@ -42,7 +41,7 @@ def class_url(cls): def instance_url(self): id = self.resource.get("id") - if not isinstance(id, six.string_types): + if not isinstance(id, str): raise error.InvalidRequestError( "Could not determine which URL to request: %s instance " "has invalid ID: %r, %s. ID should be of type `str` (or" @@ -50,31 +49,6 @@ def instance_url(self): "id", ) - id = util.utf8(id) base = self.class_url() extn = quote_plus(id) return "%s/%s" % (base, extn) - - -# TODO (next major) -def test_helpers(cls): - """ - The test_helpers decorator is deprecated and will be removed in a future version - of the library. - """ - - def test_helpers_getter(self): - return self.TestHelpers(self) - - if not issubclass(cls, APIResource): - raise ValueError( - "Could not apply @test_helpers decorator to %r." - " The class should a subclass of APIResource." % cls - ) - - cls.TestHelpers._resource_cls = cls - cls.TestHelpers._static_request = cls._static_request - cls.TestHelpers._static_request_stream = cls._static_request_stream - - cls.test_helpers = property(test_helpers_getter) - return cls diff --git a/stripe/api_resources/abstract/updateable_api_resource.py b/stripe/api_resources/abstract/updateable_api_resource.py index 7959fefb2..2a485a311 100644 --- a/stripe/api_resources/abstract/updateable_api_resource.py +++ b/stripe/api_resources/abstract/updateable_api_resource.py @@ -2,13 +2,13 @@ from stripe import util from stripe.api_resources.abstract.api_resource import APIResource -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class UpdateableAPIResource(APIResource): @classmethod def modify(cls, sid, **params): - url = "%s/%s" % (cls.class_url(), quote_plus(util.utf8(sid))) + url = "%s/%s" % (cls.class_url(), quote_plus(sid)) return cls._static_request("post", url, params=params) def save(self, idempotency_key=None): diff --git a/stripe/api_resources/account.py b/stripe/api_resources/account.py index 09d0659f5..0d960a5f1 100644 --- a/stripe/api_resources/account.py +++ b/stripe/api_resources/account.py @@ -2,15 +2,15 @@ # File generated from our OpenAPI spec from __future__ import absolute_import, division, print_function -import stripe -from stripe import oauth, six +from stripe import api_resources +from stripe import oauth from stripe import util from stripe.api_resources.abstract import CreateableAPIResource from stripe.api_resources.abstract import DeletableAPIResource from stripe.api_resources.abstract import ListableAPIResource from stripe.api_resources.abstract import UpdateableAPIResource from stripe.api_resources.abstract import nested_resource_class_methods -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus @nested_resource_class_methods( @@ -129,7 +129,6 @@ def modify(cls, id=None, **params): def _build_instance_url(cls, sid): if not sid: return "/v1/account" - sid = util.utf8(sid) base = cls.class_url() extn = quote_plus(sid) return "%s/%s" % (base, extn) @@ -145,10 +144,10 @@ def serialize(self, previous): params = super(Account, self).serialize(previous) previous = previous or self._previous or {} - for k, v in six.iteritems(self): + for k, v in iter(self.items()): if ( k == "individual" - and isinstance(v, stripe.api_resources.Person) + and isinstance(v, api_resources.Person) and k not in params ): params[k] = v.serialize(previous.get(k, None)) diff --git a/stripe/api_resources/application_fee_refund.py b/stripe/api_resources/application_fee_refund.py index 92aefa113..ac3053873 100644 --- a/stripe/api_resources/application_fee_refund.py +++ b/stripe/api_resources/application_fee_refund.py @@ -2,10 +2,9 @@ # File generated from our OpenAPI spec from __future__ import absolute_import, division, print_function -from stripe import util from stripe.api_resources import ApplicationFee from stripe.api_resources.abstract import UpdateableAPIResource -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class ApplicationFeeRefund(UpdateableAPIResource): @@ -21,8 +20,6 @@ class ApplicationFeeRefund(UpdateableAPIResource): @classmethod def _build_instance_url(cls, fee, sid): - fee = util.utf8(fee) - sid = util.utf8(sid) base = ApplicationFee.class_url() cust_extn = quote_plus(fee) extn = quote_plus(sid) diff --git a/stripe/api_resources/bank_account.py b/stripe/api_resources/bank_account.py index d23713aff..d13a63d45 100644 --- a/stripe/api_resources/bank_account.py +++ b/stripe/api_resources/bank_account.py @@ -3,13 +3,12 @@ from __future__ import absolute_import, division, print_function from stripe import error -from stripe import util from stripe.api_resources.abstract import DeletableAPIResource from stripe.api_resources.abstract import UpdateableAPIResource from stripe.api_resources.abstract import VerifyMixin from stripe.api_resources.account import Account from stripe.api_resources.customer import Customer -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class BankAccount(DeletableAPIResource, UpdateableAPIResource, VerifyMixin): @@ -26,17 +25,17 @@ class BankAccount(DeletableAPIResource, UpdateableAPIResource, VerifyMixin): OBJECT_NAME = "bank_account" def instance_url(self): - token = util.utf8(self.id) + token = self.id extn = quote_plus(token) if hasattr(self, "customer"): - customer = util.utf8(self.customer) + customer = self.customer base = Customer.class_url() owner_extn = quote_plus(customer) class_base = "sources" elif hasattr(self, "account"): - account = util.utf8(self.account) + account = self.account base = Account.class_url() owner_extn = quote_plus(account) diff --git a/stripe/api_resources/capability.py b/stripe/api_resources/capability.py index 9dda9c4d4..665182327 100644 --- a/stripe/api_resources/capability.py +++ b/stripe/api_resources/capability.py @@ -2,10 +2,9 @@ # File generated from our OpenAPI spec from __future__ import absolute_import, division, print_function -from stripe import util from stripe.api_resources.abstract import UpdateableAPIResource from stripe.api_resources.account import Account -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class Capability(UpdateableAPIResource): @@ -18,8 +17,8 @@ class Capability(UpdateableAPIResource): OBJECT_NAME = "capability" def instance_url(self): - token = util.utf8(self.id) - account = util.utf8(self.account) + token = self.id + account = self.account base = Account.class_url() acct_extn = quote_plus(account) extn = quote_plus(token) diff --git a/stripe/api_resources/card.py b/stripe/api_resources/card.py index 7aa85844c..f77a6eeb9 100644 --- a/stripe/api_resources/card.py +++ b/stripe/api_resources/card.py @@ -3,12 +3,11 @@ from __future__ import absolute_import, division, print_function from stripe import error -from stripe import util from stripe.api_resources.abstract import DeletableAPIResource from stripe.api_resources.abstract import UpdateableAPIResource from stripe.api_resources.account import Account from stripe.api_resources.customer import Customer -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class Card(DeletableAPIResource, UpdateableAPIResource): @@ -23,17 +22,17 @@ class Card(DeletableAPIResource, UpdateableAPIResource): OBJECT_NAME = "card" def instance_url(self): - token = util.utf8(self.id) + token = self.id extn = quote_plus(token) if hasattr(self, "customer"): - customer = util.utf8(self.customer) + customer = self.customer base = Customer.class_url() owner_extn = quote_plus(customer) class_base = "sources" elif hasattr(self, "account"): - account = util.utf8(self.account) + account = self.account base = Account.class_url() owner_extn = quote_plus(account) diff --git a/stripe/api_resources/cash_balance.py b/stripe/api_resources/cash_balance.py index c70e5827f..00b26189f 100644 --- a/stripe/api_resources/cash_balance.py +++ b/stripe/api_resources/cash_balance.py @@ -2,10 +2,9 @@ # File generated from our OpenAPI spec from __future__ import absolute_import, division, print_function -from stripe import util from stripe.api_resources.abstract import APIResource from stripe.api_resources.customer import Customer -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class CashBalance(APIResource): @@ -16,7 +15,7 @@ class CashBalance(APIResource): OBJECT_NAME = "cash_balance" def instance_url(self): - customer = util.utf8(self.customer) + customer = self.customer base = Customer.class_url() cust_extn = quote_plus(customer) return "%s/%s/cash_balance" % (base, cust_extn) diff --git a/stripe/api_resources/customer_balance_transaction.py b/stripe/api_resources/customer_balance_transaction.py index 148d4ed5d..2a9e9abc6 100644 --- a/stripe/api_resources/customer_balance_transaction.py +++ b/stripe/api_resources/customer_balance_transaction.py @@ -2,10 +2,9 @@ # File generated from our OpenAPI spec from __future__ import absolute_import, division, print_function -from stripe import util from stripe.api_resources.abstract import APIResource from stripe.api_resources.customer import Customer -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class CustomerBalanceTransaction(APIResource): @@ -21,8 +20,8 @@ class CustomerBalanceTransaction(APIResource): OBJECT_NAME = "customer_balance_transaction" def instance_url(self): - token = util.utf8(self.id) - customer = util.utf8(self.customer) + token = self.id + customer = self.customer base = Customer.class_url() cust_extn = quote_plus(customer) extn = quote_plus(token) diff --git a/stripe/api_resources/list_object.py b/stripe/api_resources/list_object.py index b452d34d4..4c614ca10 100644 --- a/stripe/api_resources/list_object.py +++ b/stripe/api_resources/list_object.py @@ -1,9 +1,8 @@ from __future__ import absolute_import, division, print_function -from stripe import six, util from stripe.stripe_object import StripeObject -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class ListObject(StripeObject): @@ -47,7 +46,7 @@ def retrieve( stripe_account=None, **params ): - url = "%s/%s" % (self.get("url"), quote_plus(util.utf8(id))) + url = "%s/%s" % (self.get("url"), quote_plus(id)) return self._request( "get", url, @@ -58,7 +57,7 @@ def retrieve( ) def __getitem__(self, k): - if isinstance(k, six.string_types): + if isinstance(k, str): return super(ListObject, self).__getitem__(k) else: raise KeyError( @@ -128,12 +127,14 @@ def next_page( params_with_filters.update({"starting_after": last_id}) params_with_filters.update(params) - return self.list( + result = self.list( api_key=api_key, stripe_version=stripe_version, stripe_account=stripe_account, **params_with_filters ) + assert isinstance(result, ListObject) + return result def previous_page( self, api_key=None, stripe_version=None, stripe_account=None, **params diff --git a/stripe/api_resources/person.py b/stripe/api_resources/person.py index ce9aef6be..48d8a29b2 100644 --- a/stripe/api_resources/person.py +++ b/stripe/api_resources/person.py @@ -2,10 +2,9 @@ # File generated from our OpenAPI spec from __future__ import absolute_import, division, print_function -from stripe import util from stripe.api_resources.abstract import UpdateableAPIResource from stripe.api_resources.account import Account -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class Person(UpdateableAPIResource): @@ -21,8 +20,8 @@ class Person(UpdateableAPIResource): OBJECT_NAME = "person" def instance_url(self): - token = util.utf8(self.id) - account = util.utf8(self.account) + token = self.id + account = self.account base = Account.class_url() acct_extn = quote_plus(account) extn = quote_plus(token) diff --git a/stripe/api_resources/quote.py b/stripe/api_resources/quote.py index 26a567359..19c112b5c 100644 --- a/stripe/api_resources/quote.py +++ b/stripe/api_resources/quote.py @@ -8,7 +8,7 @@ from stripe.api_resources.abstract import CreateableAPIResource from stripe.api_resources.abstract import ListableAPIResource from stripe.api_resources.abstract import UpdateableAPIResource -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class Quote(CreateableAPIResource, ListableAPIResource, UpdateableAPIResource): @@ -182,7 +182,7 @@ def _cls_pdf( ): url = "%s/%s/%s" % ( cls.class_url(), - quote_plus(util.utf8(sid)), + quote_plus(sid), "pdf", ) requestor = api_requestor.APIRequestor( diff --git a/stripe/api_resources/reversal.py b/stripe/api_resources/reversal.py index 19d093f96..36487f18c 100644 --- a/stripe/api_resources/reversal.py +++ b/stripe/api_resources/reversal.py @@ -2,10 +2,9 @@ # File generated from our OpenAPI spec from __future__ import absolute_import, division, print_function -from stripe import util from stripe.api_resources.abstract import UpdateableAPIResource from stripe.api_resources.transfer import Transfer -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class Reversal(UpdateableAPIResource): @@ -28,8 +27,8 @@ class Reversal(UpdateableAPIResource): OBJECT_NAME = "transfer_reversal" def instance_url(self): - token = util.utf8(self.id) - transfer = util.utf8(self.transfer) + token = self.id + transfer = self.transfer base = Transfer.class_url() cust_extn = quote_plus(transfer) extn = quote_plus(token) diff --git a/stripe/api_resources/search_result_object.py b/stripe/api_resources/search_result_object.py index 4a3563e25..c7b7768e1 100644 --- a/stripe/api_resources/search_result_object.py +++ b/stripe/api_resources/search_result_object.py @@ -1,6 +1,5 @@ from __future__ import absolute_import, division, print_function -from stripe import six from stripe.stripe_object import StripeObject @@ -20,7 +19,7 @@ def search( ) def __getitem__(self, k): - if isinstance(k, six.string_types): + if isinstance(k, str): return super(SearchResultObject, self).__getitem__(k) else: raise KeyError( @@ -77,9 +76,11 @@ def next_search_result_page( params_with_filters.update({"page": self.next_page}) params_with_filters.update(params) - return self.search( + result = self.search( api_key=api_key, stripe_version=stripe_version, stripe_account=stripe_account, **params_with_filters ) + assert isinstance(result, SearchResultObject) + return result diff --git a/stripe/api_resources/source.py b/stripe/api_resources/source.py index d198bc0b1..7e4426873 100644 --- a/stripe/api_resources/source.py +++ b/stripe/api_resources/source.py @@ -7,7 +7,7 @@ from stripe.api_resources import Customer from stripe.api_resources.abstract import CreateableAPIResource from stripe.api_resources.abstract import UpdateableAPIResource -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class Source(CreateableAPIResource, UpdateableAPIResource): @@ -89,11 +89,11 @@ def verify(self, idempotency_key=None, **params): ) def detach(self, idempotency_key=None, **params): - token = util.utf8(self.id) + token = self.id if hasattr(self, "customer") and self.customer: extn = quote_plus(token) - customer = util.utf8(self.customer) + customer = self.customer base = Customer.class_url() owner_extn = quote_plus(customer) url = "%s/%s/sources/%s" % (base, owner_extn, extn) diff --git a/stripe/api_resources/tax_id.py b/stripe/api_resources/tax_id.py index 553834971..cf4222c33 100644 --- a/stripe/api_resources/tax_id.py +++ b/stripe/api_resources/tax_id.py @@ -2,10 +2,9 @@ # File generated from our OpenAPI spec from __future__ import absolute_import, division, print_function -from stripe import util from stripe.api_resources.abstract import APIResource from stripe.api_resources.customer import Customer -from stripe.six.moves.urllib.parse import quote_plus +from urllib.parse import quote_plus class TaxId(APIResource): @@ -19,8 +18,8 @@ class TaxId(APIResource): OBJECT_NAME = "tax_id" def instance_url(self): - token = util.utf8(self.id) - customer = util.utf8(self.customer) + token = self.id + customer = self.customer base = Customer.class_url() cust_extn = quote_plus(customer) extn = quote_plus(token) diff --git a/stripe/error.py b/stripe/error.py index 11cf12d7c..254f3770f 100644 --- a/stripe/error.py +++ b/stripe/error.py @@ -1,10 +1,8 @@ from __future__ import absolute_import, division, print_function import stripe -from stripe.six import python_2_unicode_compatible -@python_2_unicode_compatible class StripeError(Exception): def __init__( self, diff --git a/stripe/http_client.py b/stripe/http_client.py index 54008457f..db1db6854 100644 --- a/stripe/http_client.py +++ b/stripe/http_client.py @@ -10,7 +10,7 @@ import json import stripe -from stripe import error, util, six +from stripe import error, util from stripe.request_metrics import RequestMetrics # - Requests is the preferred HTTP library @@ -18,7 +18,7 @@ # - Use Pycurl if it's there (at least it verifies SSL certs) # - Fall back to urllib2 with a warning if needed try: - from stripe.six.moves import urllib + import urllib except ImportError: # Try to load in urllib2, but don't sweat it if it's not available. pass @@ -60,7 +60,7 @@ urlfetch = None # proxy support for the pycurl client -from stripe.six.moves.urllib.parse import urlparse +from urllib.parse import urlparse def _now_ms(): @@ -510,7 +510,7 @@ def __init__(self, verify_ssl_certs=True, proxy=None): if self._proxy: # now that we have the parser, get the proxy url pieces proxy = self._proxy - for scheme, value in six.iteritems(proxy): + for scheme, value in proxy.items(): proxy[scheme] = urlparse(value) def parse_headers(self, data): @@ -518,7 +518,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 six.iteritems(dict(headers))) + return dict((k.lower(), v) for k, v in dict(headers).items()) def request(self, method, url, headers, post_data=None): return self._request_internal( @@ -563,7 +563,7 @@ def _request_internal(self, method, url, headers, post_data, is_streaming): self._curl.setopt(pycurl.CUSTOMREQUEST, method.upper()) # pycurl doesn't like unicode URLs - self._curl.setopt(pycurl.URL, util.utf8(url)) + self._curl.setopt(pycurl.URL, url) self._curl.setopt(pycurl.WRITEFUNCTION, b.write) self._curl.setopt(pycurl.HEADERFUNCTION, rheaders.write) @@ -572,7 +572,7 @@ def _request_internal(self, method, url, headers, post_data, is_streaming): self._curl.setopt(pycurl.TIMEOUT, 80) self._curl.setopt( pycurl.HTTPHEADER, - ["%s: %s" % (k, v) for k, v in six.iteritems(dict(headers))], + ["%s: %s" % (k, v) for k, v in dict(headers).items()], ) if self._verify_ssl_certs: self._curl.setopt(pycurl.CAINFO, stripe.ca_bundle_path) @@ -663,7 +663,7 @@ def request_stream(self, method, url, headers, post_data=None): ) def _request_internal(self, method, url, headers, post_data, is_streaming): - if six.PY3 and isinstance(post_data, six.string_types): + if isinstance(post_data, str): post_data = post_data.encode("utf-8") req = urllib.request.Request(url, post_data, headers) @@ -693,7 +693,7 @@ def _request_internal(self, method, url, headers, post_data, is_streaming): headers = dict(e.info()) except (urllib.error.URLError, ValueError) as e: self._handle_request_error(e) - lh = dict((k.lower(), v) for k, v in six.iteritems(dict(headers))) + lh = dict((k.lower(), v) for k, v in dict(headers).items()) return rcontent, rcode, lh def _handle_request_error(self, e): diff --git a/stripe/multipart_data_generator.py b/stripe/multipart_data_generator.py index c3e25f2fa..02bd4a4a3 100644 --- a/stripe/multipart_data_generator.py +++ b/stripe/multipart_data_generator.py @@ -17,7 +17,7 @@ def add_params(self, params): # Flatten parameters first params = dict(stripe.api_requestor._api_encode(params)) - for key, value in stripe.six.iteritems(params): + for key, value in params.items(): if value is None: continue @@ -29,7 +29,7 @@ def add_params(self, params): # Convert the filename to string, just in case it's not # already one. E.g. `tempfile.TemporaryFile` has a `name` # attribute but it's an `int`. - filename = stripe.six.text_type(value.name) + filename = str(value.name) self._write('Content-Disposition: form-data; name="') self._write(key) @@ -61,9 +61,9 @@ def get_post_data(self): return self.data.getvalue() def _write(self, value): - if isinstance(value, stripe.six.binary_type): + if isinstance(value, bytes): array = bytearray(value) - elif isinstance(value, stripe.six.text_type): + elif isinstance(value, str): array = bytearray(value, encoding="utf-8") else: raise TypeError( diff --git a/stripe/oauth.py b/stripe/oauth.py index b364709d9..20f5789a8 100644 --- a/stripe/oauth.py +++ b/stripe/oauth.py @@ -1,7 +1,7 @@ from __future__ import absolute_import, division, print_function from stripe import api_requestor, connect_api_base, error -from stripe.six.moves.urllib.parse import urlencode +from urllib.parse import urlencode class OAuth(object): diff --git a/stripe/six.py b/stripe/six.py deleted file mode 100644 index d4fe9849f..000000000 --- a/stripe/six.py +++ /dev/null @@ -1,998 +0,0 @@ -# Copyright (c) 2010-2020 Benjamin Peterson -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -"""Utilities for writing code that runs on Python 2 and 3""" - -from __future__ import absolute_import - -import functools -import itertools -import operator -import sys -import types - -__author__ = "Benjamin Peterson " -__version__ = "1.16.0" - - -# Useful for very coarse version differentiation. -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 -PY34 = sys.version_info[0:2] >= (3, 4) - -if PY3: - string_types = str, - integer_types = int, - class_types = type, - text_type = str - binary_type = bytes - - MAXSIZE = sys.maxsize -else: - string_types = basestring, - integer_types = (int, long) - class_types = (type, types.ClassType) - text_type = unicode - binary_type = str - - if sys.platform.startswith("java"): - # Jython always uses 32 bits. - MAXSIZE = int((1 << 31) - 1) - else: - # It's possible to have sizeof(long) != sizeof(Py_ssize_t). - class X(object): - - def __len__(self): - return 1 << 31 - try: - len(X()) - except OverflowError: - # 32-bit - MAXSIZE = int((1 << 31) - 1) - else: - # 64-bit - MAXSIZE = int((1 << 63) - 1) - del X - -if PY34: - from importlib.util import spec_from_loader -else: - spec_from_loader = None - - -def _add_doc(func, doc): - """Add documentation to a function.""" - func.__doc__ = doc - - -def _import_module(name): - """Import module, returning the module after the last dot.""" - __import__(name) - return sys.modules[name] - - -class _LazyDescr(object): - - def __init__(self, name): - self.name = name - - def __get__(self, obj, tp): - result = self._resolve() - setattr(obj, self.name, result) # Invokes __set__. - try: - # This is a bit ugly, but it avoids running this again by - # removing this descriptor. - delattr(obj.__class__, self.name) - except AttributeError: - pass - return result - - -class MovedModule(_LazyDescr): - - def __init__(self, name, old, new=None): - super(MovedModule, self).__init__(name) - if PY3: - if new is None: - new = name - self.mod = new - else: - self.mod = old - - def _resolve(self): - return _import_module(self.mod) - - def __getattr__(self, attr): - _module = self._resolve() - value = getattr(_module, attr) - setattr(self, attr, value) - return value - - -class _LazyModule(types.ModuleType): - - def __init__(self, name): - super(_LazyModule, self).__init__(name) - self.__doc__ = self.__class__.__doc__ - - def __dir__(self): - attrs = ["__doc__", "__name__"] - attrs += [attr.name for attr in self._moved_attributes] - return attrs - - # Subclasses should override this - _moved_attributes = [] - - -class MovedAttribute(_LazyDescr): - - def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): - super(MovedAttribute, self).__init__(name) - if PY3: - if new_mod is None: - new_mod = name - self.mod = new_mod - if new_attr is None: - if old_attr is None: - new_attr = name - else: - new_attr = old_attr - self.attr = new_attr - else: - self.mod = old_mod - if old_attr is None: - old_attr = name - self.attr = old_attr - - def _resolve(self): - module = _import_module(self.mod) - return getattr(module, self.attr) - - -class _SixMetaPathImporter(object): - - """ - A meta path importer to import six.moves and its submodules. - - This class implements a PEP302 finder and loader. It should be compatible - with Python 2.5 and all existing versions of Python3 - """ - - def __init__(self, six_module_name): - self.name = six_module_name - self.known_modules = {} - - def _add_module(self, mod, *fullnames): - for fullname in fullnames: - self.known_modules[self.name + "." + fullname] = mod - - def _get_module(self, fullname): - return self.known_modules[self.name + "." + fullname] - - def find_module(self, fullname, path=None): - if fullname in self.known_modules: - return self - return None - - def find_spec(self, fullname, path, target=None): - if fullname in self.known_modules: - return spec_from_loader(fullname, self) - return None - - def __get_module(self, fullname): - try: - return self.known_modules[fullname] - except KeyError: - raise ImportError("This loader does not know module " + fullname) - - def load_module(self, fullname): - try: - # in case of a reload - return sys.modules[fullname] - except KeyError: - pass - mod = self.__get_module(fullname) - if isinstance(mod, MovedModule): - mod = mod._resolve() - else: - mod.__loader__ = self - sys.modules[fullname] = mod - return mod - - def is_package(self, fullname): - """ - Return true, if the named module is a package. - - We need this method to get correct spec objects with - Python 3.4 (see PEP451) - """ - return hasattr(self.__get_module(fullname), "__path__") - - def get_code(self, fullname): - """Return None - - Required, if is_package is implemented""" - self.__get_module(fullname) # eventually raises ImportError - return None - get_source = get_code # same as get_code - - def create_module(self, spec): - return self.load_module(spec.name) - - def exec_module(self, module): - pass - -_importer = _SixMetaPathImporter(__name__) - - -class _MovedItems(_LazyModule): - - """Lazy loading of moved objects""" - __path__ = [] # mark as package - - -_moved_attributes = [ - MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), - MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), - MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), - MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), - MovedAttribute("intern", "__builtin__", "sys"), - MovedAttribute("map", "itertools", "builtins", "imap", "map"), - MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), - MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), - MovedAttribute("getoutput", "commands", "subprocess"), - MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), - MovedAttribute("reduce", "__builtin__", "functools"), - MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), - MovedAttribute("StringIO", "StringIO", "io"), - MovedAttribute("UserDict", "UserDict", "collections", "IterableUserDict", "UserDict"), - MovedAttribute("UserList", "UserList", "collections"), - MovedAttribute("UserString", "UserString", "collections"), - MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), - MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), - MovedModule("builtins", "__builtin__"), - MovedModule("configparser", "ConfigParser"), - MovedModule("collections_abc", "collections", "collections.abc" if sys.version_info >= (3, 3) else "collections"), - MovedModule("copyreg", "copy_reg"), - MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), - MovedModule("dbm_ndbm", "dbm", "dbm.ndbm"), - MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread" if sys.version_info < (3, 9) else "_thread"), - MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), - MovedModule("http_cookies", "Cookie", "http.cookies"), - MovedModule("html_entities", "htmlentitydefs", "html.entities"), - MovedModule("html_parser", "HTMLParser", "html.parser"), - MovedModule("http_client", "httplib", "http.client"), - MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), - MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"), - MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), - MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), - MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), - MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), - MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), - MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), - MovedModule("cPickle", "cPickle", "pickle"), - MovedModule("queue", "Queue"), - MovedModule("reprlib", "repr"), - MovedModule("socketserver", "SocketServer"), - MovedModule("_thread", "thread", "_thread"), - MovedModule("tkinter", "Tkinter"), - MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), - MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), - MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), - MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), - MovedModule("tkinter_tix", "Tix", "tkinter.tix"), - MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), - MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), - MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), - MovedModule("tkinter_colorchooser", "tkColorChooser", - "tkinter.colorchooser"), - MovedModule("tkinter_commondialog", "tkCommonDialog", - "tkinter.commondialog"), - MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), - MovedModule("tkinter_font", "tkFont", "tkinter.font"), - MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), - MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", - "tkinter.simpledialog"), - MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), - MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), - MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), - MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), - MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), - MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), -] -# Add windows specific modules. -if sys.platform == "win32": - _moved_attributes += [ - MovedModule("winreg", "_winreg"), - ] - -for attr in _moved_attributes: - setattr(_MovedItems, attr.name, attr) - if isinstance(attr, MovedModule): - _importer._add_module(attr, "moves." + attr.name) -del attr - -_MovedItems._moved_attributes = _moved_attributes - -moves = _MovedItems(__name__ + ".moves") -_importer._add_module(moves, "moves") - - -class Module_six_moves_urllib_parse(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_parse""" - - -_urllib_parse_moved_attributes = [ - MovedAttribute("ParseResult", "urlparse", "urllib.parse"), - MovedAttribute("SplitResult", "urlparse", "urllib.parse"), - MovedAttribute("parse_qs", "urlparse", "urllib.parse"), - MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), - MovedAttribute("urldefrag", "urlparse", "urllib.parse"), - MovedAttribute("urljoin", "urlparse", "urllib.parse"), - MovedAttribute("urlparse", "urlparse", "urllib.parse"), - MovedAttribute("urlsplit", "urlparse", "urllib.parse"), - MovedAttribute("urlunparse", "urlparse", "urllib.parse"), - MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), - MovedAttribute("quote", "urllib", "urllib.parse"), - MovedAttribute("quote_plus", "urllib", "urllib.parse"), - MovedAttribute("unquote", "urllib", "urllib.parse"), - MovedAttribute("unquote_plus", "urllib", "urllib.parse"), - MovedAttribute("unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"), - MovedAttribute("urlencode", "urllib", "urllib.parse"), - MovedAttribute("splitquery", "urllib", "urllib.parse"), - MovedAttribute("splittag", "urllib", "urllib.parse"), - MovedAttribute("splituser", "urllib", "urllib.parse"), - MovedAttribute("splitvalue", "urllib", "urllib.parse"), - MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), - MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), - MovedAttribute("uses_params", "urlparse", "urllib.parse"), - MovedAttribute("uses_query", "urlparse", "urllib.parse"), - MovedAttribute("uses_relative", "urlparse", "urllib.parse"), -] -for attr in _urllib_parse_moved_attributes: - setattr(Module_six_moves_urllib_parse, attr.name, attr) -del attr - -Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes - -_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), - "moves.urllib_parse", "moves.urllib.parse") - - -class Module_six_moves_urllib_error(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_error""" - - -_urllib_error_moved_attributes = [ - MovedAttribute("URLError", "urllib2", "urllib.error"), - MovedAttribute("HTTPError", "urllib2", "urllib.error"), - MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), -] -for attr in _urllib_error_moved_attributes: - setattr(Module_six_moves_urllib_error, attr.name, attr) -del attr - -Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes - -_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), - "moves.urllib_error", "moves.urllib.error") - - -class Module_six_moves_urllib_request(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_request""" - - -_urllib_request_moved_attributes = [ - MovedAttribute("urlopen", "urllib2", "urllib.request"), - MovedAttribute("install_opener", "urllib2", "urllib.request"), - MovedAttribute("build_opener", "urllib2", "urllib.request"), - MovedAttribute("pathname2url", "urllib", "urllib.request"), - MovedAttribute("url2pathname", "urllib", "urllib.request"), - MovedAttribute("getproxies", "urllib", "urllib.request"), - MovedAttribute("Request", "urllib2", "urllib.request"), - MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), - MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), - MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), - MovedAttribute("BaseHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), - MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), - MovedAttribute("FileHandler", "urllib2", "urllib.request"), - MovedAttribute("FTPHandler", "urllib2", "urllib.request"), - MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), - MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), - MovedAttribute("urlretrieve", "urllib", "urllib.request"), - MovedAttribute("urlcleanup", "urllib", "urllib.request"), - MovedAttribute("URLopener", "urllib", "urllib.request"), - MovedAttribute("FancyURLopener", "urllib", "urllib.request"), - MovedAttribute("proxy_bypass", "urllib", "urllib.request"), - MovedAttribute("parse_http_list", "urllib2", "urllib.request"), - MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"), -] -for attr in _urllib_request_moved_attributes: - setattr(Module_six_moves_urllib_request, attr.name, attr) -del attr - -Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes - -_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), - "moves.urllib_request", "moves.urllib.request") - - -class Module_six_moves_urllib_response(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_response""" - - -_urllib_response_moved_attributes = [ - MovedAttribute("addbase", "urllib", "urllib.response"), - MovedAttribute("addclosehook", "urllib", "urllib.response"), - MovedAttribute("addinfo", "urllib", "urllib.response"), - MovedAttribute("addinfourl", "urllib", "urllib.response"), -] -for attr in _urllib_response_moved_attributes: - setattr(Module_six_moves_urllib_response, attr.name, attr) -del attr - -Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes - -_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), - "moves.urllib_response", "moves.urllib.response") - - -class Module_six_moves_urllib_robotparser(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_robotparser""" - - -_urllib_robotparser_moved_attributes = [ - MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), -] -for attr in _urllib_robotparser_moved_attributes: - setattr(Module_six_moves_urllib_robotparser, attr.name, attr) -del attr - -Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes - -_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), - "moves.urllib_robotparser", "moves.urllib.robotparser") - - -class Module_six_moves_urllib(types.ModuleType): - - """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" - __path__ = [] # mark as package - parse = _importer._get_module("moves.urllib_parse") - error = _importer._get_module("moves.urllib_error") - request = _importer._get_module("moves.urllib_request") - response = _importer._get_module("moves.urllib_response") - robotparser = _importer._get_module("moves.urllib_robotparser") - - def __dir__(self): - return ['parse', 'error', 'request', 'response', 'robotparser'] - -_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), - "moves.urllib") - - -def add_move(move): - """Add an item to six.moves.""" - setattr(_MovedItems, move.name, move) - - -def remove_move(name): - """Remove item from six.moves.""" - try: - delattr(_MovedItems, name) - except AttributeError: - try: - del moves.__dict__[name] - except KeyError: - raise AttributeError("no such move, %r" % (name,)) - - -if PY3: - _meth_func = "__func__" - _meth_self = "__self__" - - _func_closure = "__closure__" - _func_code = "__code__" - _func_defaults = "__defaults__" - _func_globals = "__globals__" -else: - _meth_func = "im_func" - _meth_self = "im_self" - - _func_closure = "func_closure" - _func_code = "func_code" - _func_defaults = "func_defaults" - _func_globals = "func_globals" - - -try: - advance_iterator = next -except NameError: - def advance_iterator(it): - return it.next() -next = advance_iterator - - -try: - callable = callable -except NameError: - def callable(obj): - return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) - - -if PY3: - def get_unbound_function(unbound): - return unbound - - create_bound_method = types.MethodType - - def create_unbound_method(func, cls): - return func - - Iterator = object -else: - def get_unbound_function(unbound): - return unbound.im_func - - def create_bound_method(func, obj): - return types.MethodType(func, obj, obj.__class__) - - def create_unbound_method(func, cls): - return types.MethodType(func, None, cls) - - class Iterator(object): - - def next(self): - return type(self).__next__(self) - - callable = callable -_add_doc(get_unbound_function, - """Get the function out of a possibly unbound function""") - - -get_method_function = operator.attrgetter(_meth_func) -get_method_self = operator.attrgetter(_meth_self) -get_function_closure = operator.attrgetter(_func_closure) -get_function_code = operator.attrgetter(_func_code) -get_function_defaults = operator.attrgetter(_func_defaults) -get_function_globals = operator.attrgetter(_func_globals) - - -if PY3: - def iterkeys(d, **kw): - return iter(d.keys(**kw)) - - def itervalues(d, **kw): - return iter(d.values(**kw)) - - def iteritems(d, **kw): - return iter(d.items(**kw)) - - def iterlists(d, **kw): - return iter(d.lists(**kw)) - - viewkeys = operator.methodcaller("keys") - - viewvalues = operator.methodcaller("values") - - viewitems = operator.methodcaller("items") -else: - def iterkeys(d, **kw): - return d.iterkeys(**kw) - - def itervalues(d, **kw): - return d.itervalues(**kw) - - def iteritems(d, **kw): - return d.iteritems(**kw) - - def iterlists(d, **kw): - return d.iterlists(**kw) - - viewkeys = operator.methodcaller("viewkeys") - - viewvalues = operator.methodcaller("viewvalues") - - viewitems = operator.methodcaller("viewitems") - -_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") -_add_doc(itervalues, "Return an iterator over the values of a dictionary.") -_add_doc(iteritems, - "Return an iterator over the (key, value) pairs of a dictionary.") -_add_doc(iterlists, - "Return an iterator over the (key, [values]) pairs of a dictionary.") - - -if PY3: - def b(s): - return s.encode("latin-1") - - def u(s): - return s - unichr = chr - import struct - int2byte = struct.Struct(">B").pack - del struct - byte2int = operator.itemgetter(0) - indexbytes = operator.getitem - iterbytes = iter - import io - StringIO = io.StringIO - BytesIO = io.BytesIO - del io - _assertCountEqual = "assertCountEqual" - if sys.version_info[1] <= 1: - _assertRaisesRegex = "assertRaisesRegexp" - _assertRegex = "assertRegexpMatches" - _assertNotRegex = "assertNotRegexpMatches" - else: - _assertRaisesRegex = "assertRaisesRegex" - _assertRegex = "assertRegex" - _assertNotRegex = "assertNotRegex" -else: - def b(s): - return s - # Workaround for standalone backslash - - def u(s): - return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") - unichr = unichr - int2byte = chr - - def byte2int(bs): - return ord(bs[0]) - - def indexbytes(buf, i): - return ord(buf[i]) - iterbytes = functools.partial(itertools.imap, ord) - import StringIO - StringIO = BytesIO = StringIO.StringIO - _assertCountEqual = "assertItemsEqual" - _assertRaisesRegex = "assertRaisesRegexp" - _assertRegex = "assertRegexpMatches" - _assertNotRegex = "assertNotRegexpMatches" -_add_doc(b, """Byte literal""") -_add_doc(u, """Text literal""") - - -def assertCountEqual(self, *args, **kwargs): - return getattr(self, _assertCountEqual)(*args, **kwargs) - - -def assertRaisesRegex(self, *args, **kwargs): - return getattr(self, _assertRaisesRegex)(*args, **kwargs) - - -def assertRegex(self, *args, **kwargs): - return getattr(self, _assertRegex)(*args, **kwargs) - - -def assertNotRegex(self, *args, **kwargs): - return getattr(self, _assertNotRegex)(*args, **kwargs) - - -if PY3: - exec_ = getattr(moves.builtins, "exec") - - def reraise(tp, value, tb=None): - try: - if value is None: - value = tp() - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - finally: - value = None - tb = None - -else: - def exec_(_code_, _globs_=None, _locs_=None): - """Execute code in a namespace.""" - if _globs_ is None: - frame = sys._getframe(1) - _globs_ = frame.f_globals - if _locs_ is None: - _locs_ = frame.f_locals - del frame - elif _locs_ is None: - _locs_ = _globs_ - exec("""exec _code_ in _globs_, _locs_""") - - exec_("""def reraise(tp, value, tb=None): - try: - raise tp, value, tb - finally: - tb = None -""") - - -if sys.version_info[:2] > (3,): - exec_("""def raise_from(value, from_value): - try: - raise value from from_value - finally: - value = None -""") -else: - def raise_from(value, from_value): - raise value - - -print_ = getattr(moves.builtins, "print", None) -if print_ is None: - def print_(*args, **kwargs): - """The new-style print function for Python 2.4 and 2.5.""" - fp = kwargs.pop("file", sys.stdout) - if fp is None: - return - - def write(data): - if not isinstance(data, basestring): - data = str(data) - # If the file has an encoding, encode unicode with it. - if (isinstance(fp, file) and - isinstance(data, unicode) and - fp.encoding is not None): - errors = getattr(fp, "errors", None) - if errors is None: - errors = "strict" - data = data.encode(fp.encoding, errors) - fp.write(data) - want_unicode = False - sep = kwargs.pop("sep", None) - if sep is not None: - if isinstance(sep, unicode): - want_unicode = True - elif not isinstance(sep, str): - raise TypeError("sep must be None or a string") - end = kwargs.pop("end", None) - if end is not None: - if isinstance(end, unicode): - want_unicode = True - elif not isinstance(end, str): - raise TypeError("end must be None or a string") - if kwargs: - raise TypeError("invalid keyword arguments to print()") - if not want_unicode: - for arg in args: - if isinstance(arg, unicode): - want_unicode = True - break - if want_unicode: - newline = unicode("\n") - space = unicode(" ") - else: - newline = "\n" - space = " " - if sep is None: - sep = space - if end is None: - end = newline - for i, arg in enumerate(args): - if i: - write(sep) - write(arg) - write(end) -if sys.version_info[:2] < (3, 3): - _print = print_ - - def print_(*args, **kwargs): - fp = kwargs.get("file", sys.stdout) - flush = kwargs.pop("flush", False) - _print(*args, **kwargs) - if flush and fp is not None: - fp.flush() - -_add_doc(reraise, """Reraise an exception.""") - -if sys.version_info[0:2] < (3, 4): - # This does exactly the same what the :func:`py3:functools.update_wrapper` - # function does on Python versions after 3.2. It sets the ``__wrapped__`` - # attribute on ``wrapper`` object and it doesn't raise an error if any of - # the attributes mentioned in ``assigned`` and ``updated`` are missing on - # ``wrapped`` object. - def _update_wrapper(wrapper, wrapped, - assigned=functools.WRAPPER_ASSIGNMENTS, - updated=functools.WRAPPER_UPDATES): - for attr in assigned: - try: - value = getattr(wrapped, attr) - except AttributeError: - continue - else: - setattr(wrapper, attr, value) - for attr in updated: - getattr(wrapper, attr).update(getattr(wrapped, attr, {})) - wrapper.__wrapped__ = wrapped - return wrapper - _update_wrapper.__doc__ = functools.update_wrapper.__doc__ - - def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, - updated=functools.WRAPPER_UPDATES): - return functools.partial(_update_wrapper, wrapped=wrapped, - assigned=assigned, updated=updated) - wraps.__doc__ = functools.wraps.__doc__ - -else: - wraps = functools.wraps - - -def with_metaclass(meta, *bases): - """Create a base class with a metaclass.""" - # This requires a bit of explanation: the basic idea is to make a dummy - # metaclass for one level of class instantiation that replaces itself with - # the actual metaclass. - class metaclass(type): - - def __new__(cls, name, this_bases, d): - if sys.version_info[:2] >= (3, 7): - # This version introduced PEP 560 that requires a bit - # of extra care (we mimic what is done by __build_class__). - resolved_bases = types.resolve_bases(bases) - if resolved_bases is not bases: - d['__orig_bases__'] = bases - else: - resolved_bases = bases - return meta(name, resolved_bases, d) - - @classmethod - def __prepare__(cls, name, this_bases): - return meta.__prepare__(name, bases) - return type.__new__(metaclass, 'temporary_class', (), {}) - - -def add_metaclass(metaclass): - """Class decorator for creating a class with a metaclass.""" - def wrapper(cls): - orig_vars = cls.__dict__.copy() - slots = orig_vars.get('__slots__') - if slots is not None: - if isinstance(slots, str): - slots = [slots] - for slots_var in slots: - orig_vars.pop(slots_var) - orig_vars.pop('__dict__', None) - orig_vars.pop('__weakref__', None) - if hasattr(cls, '__qualname__'): - orig_vars['__qualname__'] = cls.__qualname__ - return metaclass(cls.__name__, cls.__bases__, orig_vars) - return wrapper - - -def ensure_binary(s, encoding='utf-8', errors='strict'): - """Coerce **s** to six.binary_type. - - For Python 2: - - `unicode` -> encoded to `str` - - `str` -> `str` - - For Python 3: - - `str` -> encoded to `bytes` - - `bytes` -> `bytes` - """ - if isinstance(s, binary_type): - return s - if isinstance(s, text_type): - return s.encode(encoding, errors) - raise TypeError("not expecting type '%s'" % type(s)) - - -def ensure_str(s, encoding='utf-8', errors='strict'): - """Coerce *s* to `str`. - - For Python 2: - - `unicode` -> encoded to `str` - - `str` -> `str` - - For Python 3: - - `str` -> `str` - - `bytes` -> decoded to `str` - """ - # Optimization: Fast return for the common case. - if type(s) is str: - return s - if PY2 and isinstance(s, text_type): - return s.encode(encoding, errors) - elif PY3 and isinstance(s, binary_type): - return s.decode(encoding, errors) - elif not isinstance(s, (text_type, binary_type)): - raise TypeError("not expecting type '%s'" % type(s)) - return s - - -def ensure_text(s, encoding='utf-8', errors='strict'): - """Coerce *s* to six.text_type. - - For Python 2: - - `unicode` -> `unicode` - - `str` -> `unicode` - - For Python 3: - - `str` -> `str` - - `bytes` -> decoded to `str` - """ - if isinstance(s, binary_type): - return s.decode(encoding, errors) - elif isinstance(s, text_type): - return s - else: - raise TypeError("not expecting type '%s'" % type(s)) - - -def python_2_unicode_compatible(klass): - """ - A class decorator that defines __unicode__ and __str__ methods under Python 2. - Under Python 3 it does nothing. - - To support Python 2 and 3 with a single code base, define a __str__ method - returning text and apply this decorator to the class. - """ - if PY2: - if '__str__' not in klass.__dict__: - raise ValueError("@python_2_unicode_compatible cannot be applied " - "to %s because it doesn't define __str__()." % - klass.__name__) - klass.__unicode__ = klass.__str__ - klass.__str__ = lambda self: self.__unicode__().encode('utf-8') - return klass - - -# Complete the moves implementation. -# This code is at the end of this module to speed up module loading. -# Turn this module into a package. -__path__ = [] # required for PEP 302 and PEP 451 -__package__ = __name__ # see PEP 366 @ReservedAssignment -if globals().get("__spec__") is not None: - __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable -# Remove other six meta path importers, since they cause problems. This can -# happen if six is removed from sys.modules and then reloaded. (Setuptools does -# this for some reason.) -if sys.meta_path: - for i, importer in enumerate(sys.meta_path): - # Here's some real nastiness: Another "instance" of the six module might - # be floating around. Therefore, we can't use isinstance() to check for - # the six meta path importer, since the other six instance will have - # inserted an importer with different class. - if (type(importer).__name__ == "_SixMetaPathImporter" and - importer.name == __name__): - del sys.meta_path[i] - break - del i, importer -# Finally, add the importer to the meta path import hook. -sys.meta_path.append(_importer) diff --git a/stripe/stripe_object.py b/stripe/stripe_object.py index 80ca5d664..068c89d91 100644 --- a/stripe/stripe_object.py +++ b/stripe/stripe_object.py @@ -5,7 +5,7 @@ from copy import deepcopy import stripe -from stripe import api_requestor, util, six +from stripe import api_requestor, util def _compute_diff(current, previous): @@ -218,7 +218,7 @@ def refresh_from( self._transient_values = self._transient_values - set(values) - for k, v in six.iteritems(values): + for k, v in values.items(): super(StripeObject, self).__setitem__( k, util.convert_to_stripe_object( @@ -301,10 +301,10 @@ def request_stream(self, method, url, params=None, headers=None): def __repr__(self): ident_parts = [type(self).__name__] - if isinstance(self.get("object"), six.string_types): + if isinstance(self.get("object"), str): ident_parts.append(self.get("object")) - if isinstance(self.get("id"), six.string_types): + if isinstance(self.get("id"), str): ident_parts.append("id=%s" % (self.get("id"),)) unicode_repr = "<%s at %s> JSON: %s" % ( @@ -313,10 +313,7 @@ def __repr__(self): str(self), ) - if six.PY2: - return unicode_repr.encode("utf-8") - else: - return unicode_repr + return unicode_repr def __str__(self): return json.dumps( @@ -342,7 +339,7 @@ def maybe_to_dict_recursive(value): key: list(map(maybe_to_dict_recursive, value)) if isinstance(value, list) else maybe_to_dict_recursive(value) - for key, value in six.iteritems(dict(self)) + for key, value in dict(self).items() } @property @@ -354,7 +351,7 @@ def serialize(self, previous): unsaved_keys = self._unsaved_values or set() previous = previous or self._previous or {} - for k, v in six.iteritems(self): + for k, v in self.items(): if k == "id" or (isinstance(k, str) and k.startswith("_")): continue elif isinstance(v, stripe.api_resources.abstract.APIResource): @@ -385,7 +382,7 @@ def __copy__(self): copied._retrieve_params = self._retrieve_params - for k, v in six.iteritems(self): + for k, v in self.items(): # 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) @@ -401,7 +398,7 @@ def __deepcopy__(self, memo): copied = self.__copy__() memo[id(self)] = copied - for k, v in six.iteritems(self): + for k, v in self.items(): # 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/util.py b/stripe/util.py index b5ad1ab84..be3087920 100644 --- a/stripe/util.py +++ b/stripe/util.py @@ -9,8 +9,7 @@ import re import stripe -from stripe import six -from stripe.six.moves.urllib.parse import parse_qsl, quote_plus +from urllib.parse import parse_qsl, quote_plus STRIPE_LOG = os.environ.get("STRIPE_LOG") @@ -19,7 +18,6 @@ __all__ = [ "io", "parse_qsl", - "utf8", "log_info", "log_debug", "dashboard_link", @@ -27,13 +25,6 @@ ] -def utf8(value): - if six.PY2 and isinstance(value, six.text_type): - return value.encode("utf-8") - else: - return value - - def is_appengine_dev(): return "APPENGINE_RUNTIME" in os.environ and "Dev" in os.environ.get( "SERVER_SOFTWARE", "" @@ -81,14 +72,14 @@ def dashboard_link(request_id): def logfmt(props): def fmt(key, val): # Handle case where val is a bytes or bytesarray - if six.PY3 and hasattr(val, "decode"): + if hasattr(val, "decode"): val = val.decode("utf-8") # Check if val is already a string to avoid re-encoding into # ascii. Since the code is sent through 2to3, we can't just # use unicode(val, encoding='utf8') since it will be # translated incorrectly. - if not isinstance(val, six.string_types): - val = six.text_type(val) + if not isinstance(val, str): + val = str(val) if re.search(r"\s", val): val = repr(val) # key should already be a string @@ -103,7 +94,7 @@ def fmt(key, val): if hasattr(hmac, "compare_digest"): # Prefer the stdlib implementation, when available. def secure_compare(val1, val2): - return hmac.compare_digest(utf8(val1), utf8(val2)) + return hmac.compare_digest(val1, val2) else: @@ -115,11 +106,10 @@ def secure_compare(val1, val2): only when the two strings have the same length. It short-circuits when they have different lengths. """ - val1, val2 = utf8(val1), utf8(val2) if len(val1) != len(val2): return False result = 0 - if six.PY3 and isinstance(val1, bytes) and isinstance(val2, bytes): + if isinstance(val1, bytes) and isinstance(val2, bytes): for x, y in zip(val1, val2): result |= x ^ y else: @@ -159,7 +149,7 @@ def convert_to_stripe_object( ): resp = resp.copy() klass_name = resp.get("object") - if isinstance(klass_name, six.string_types): + if isinstance(klass_name, str): klass = get_object_classes().get( klass_name, stripe.stripe_object.StripeObject ) @@ -204,7 +194,7 @@ def convert_to_dict(obj): # comprehension returns a regular dict and recursively applies the # conversion to each value. elif isinstance(obj, dict): - return {k: convert_to_dict(v) for k, v in six.iteritems(obj)} + return {k: convert_to_dict(v) for k, v in obj.items()} else: return obj @@ -236,8 +226,7 @@ def merge_dicts(x, y): def sanitize_id(id): - utf8id = utf8(id) - quotedId = quote_plus(utf8id) + quotedId = quote_plus(id) return quotedId diff --git a/tests/api_resources/test_search_result_object.py b/tests/api_resources/test_search_result_object.py index 379131eb0..8517c7881 100644 --- a/tests/api_resources/test_search_result_object.py +++ b/tests/api_resources/test_search_result_object.py @@ -59,14 +59,14 @@ def test_bool(self, search_result_object): assert search_result_object empty = stripe.SearchResultObject.construct_from( - {"object": "list", "url": "/my/path", "data": []}, "mykey" + {"object": "search_result", "url": "/my/path", "data": []}, "mykey" ) assert bool(empty) is False def test_next_search_result_page(self, request_mock): sro = stripe.SearchResultObject.construct_from( { - "object": "list", + "object": "search_result", "data": [{"id": 1}], "has_more": True, "next_page": "next_page_token", @@ -79,7 +79,7 @@ def test_next_search_result_page(self, request_mock): "get", "/things", { - "object": "list", + "object": "search_result", "data": [{"id": 2}], "has_more": False, "url": "/things", @@ -97,7 +97,7 @@ def test_next_search_result_page(self, request_mock): def test_next_search_result_page_with_filters(self, request_mock): sro = stripe.SearchResultObject.construct_from( { - "object": "list", + "object": "search_result", "data": [{"id": 1}], "has_more": True, "next_page": "next_page_token", @@ -111,7 +111,7 @@ def test_next_search_result_page_with_filters(self, request_mock): "get", "/things", { - "object": "list", + "object": "search_result", "data": [{"id": 2}], "has_more": False, "next_page": None, @@ -129,7 +129,7 @@ def test_next_search_result_page_with_filters(self, request_mock): def test_next_search_result_page_empty_search_result(self): sro = stripe.SearchResultObject.construct_from( { - "object": "list", + "object": "search_result", "data": [{"id": 1}], "has_more": False, "next_page": None, @@ -143,7 +143,7 @@ def test_next_search_result_page_empty_search_result(self): def test_serialize_empty_search_result(self): empty = stripe.SearchResultObject.construct_from( - {"object": "list", "data": []}, "mykey" + {"object": "search_result", "data": []}, "mykey" ) serialized = str(empty) deserialized = stripe.SearchResultObject.construct_from( @@ -153,7 +153,7 @@ def test_serialize_empty_search_result(self): def test_serialize_nested_empty_search_result(self): empty = stripe.SearchResultObject.construct_from( - {"object": "list", "data": []}, "mykey" + {"object": "search_result", "data": []}, "mykey" ) obj = stripe.stripe_object.StripeObject.construct_from( {"nested": empty}, "mykey" diff --git a/tests/conftest.py b/tests/conftest.py index f868d72a9..f501ee62a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,8 +8,8 @@ import pytest import stripe -from stripe.six.moves.urllib.request import urlopen -from stripe.six.moves.urllib.error import HTTPError +from urllib.request import urlopen +from urllib.error import HTTPError from tests.request_mock import RequestMock from tests.stripe_mock import StripeMock diff --git a/tests/request_mock.py b/tests/request_mock.py index 3d53eeb51..a346998ee 100644 --- a/tests/request_mock.py +++ b/tests/request_mock.py @@ -3,7 +3,7 @@ import json import stripe -from stripe import six, util +from stripe import util from stripe.stripe_response import StripeResponse, StripeStreamResponse @@ -187,7 +187,7 @@ def get_response(self, method, url, expect_stream=False): if expect_stream != is_streaming: return None - if not isinstance(rbody, six.string_types): + if not isinstance(rbody, str): rbody = json.dumps(rbody) if is_streaming: stripe_response = StripeStreamResponse( diff --git a/tests/test_api_requestor.py b/tests/test_api_requestor.py index 9e6759ee1..b3815090f 100644 --- a/tests/test_api_requestor.py +++ b/tests/test_api_requestor.py @@ -9,10 +9,10 @@ import pytest import stripe -from stripe import six, util +from stripe import util from stripe.stripe_response import StripeResponse, StripeStreamResponse -from stripe.six.moves.urllib.parse import urlsplit +from urllib.parse import urlsplit import urllib3 @@ -118,7 +118,7 @@ def _x_stripe_ua_handles_failed_platform_function(self, other): return True def _extra_match(self, other): - for k, v in six.iteritems(self.extra): + for k, v in self.extra.items(): if other[k] != v: return False @@ -206,7 +206,7 @@ class TestAPIRequestor(object): ], "list": [("%s[0]", 1), ("%s[1]", "foo"), ("%s[2]", "baz")], "string": [("%s", "boo")], - "unicode": [("%s", stripe.util.utf8(u"\u1234"))], + "unicode": [("%s", u"\u1234")], "datetime": [("%s", 1356994801)], "none": [], } @@ -324,7 +324,7 @@ def test_param_encoding(self, requestor, mock_response, check_call): requestor.request("get", "", self.ENCODE_INPUTS) expectation = [] - for type_, values in six.iteritems(self.ENCODE_EXPECTATIONS): + for type_, values in self.ENCODE_EXPECTATIONS.items(): expectation.extend([(k % (type_,), str(v)) for k, v in values]) check_call("get", QueryMatcher(expectation)) diff --git a/tests/test_error.py b/tests/test_error.py index 644c321b0..e53d7f639 100644 --- a/tests/test_error.py +++ b/tests/test_error.py @@ -2,55 +2,32 @@ from __future__ import absolute_import, division, print_function -from stripe import six, error +from stripe import error class TestStripeError(object): def test_formatting(self): err = error.StripeError(u"öre") - assert six.text_type(err) == u"öre" - if six.PY2: - assert str(err) == "\xc3\xb6re" - else: - assert str(err) == u"öre" + assert str(err) == u"öre" def test_formatting_with_request_id(self): err = error.StripeError(u"öre", headers={"request-id": "123"}) - assert six.text_type(err) == u"Request 123: öre" - if six.PY2: - assert str(err) == "Request 123: \xc3\xb6re" - else: - assert str(err) == u"Request 123: öre" + assert str(err) == u"Request 123: öre" def test_formatting_with_none(self): err = error.StripeError(None, headers={"request-id": "123"}) - assert six.text_type(err) == u"Request 123: " - if six.PY2: - assert str(err) == "Request 123: " - else: - assert str(err) == "Request 123: " + assert str(err) == "Request 123: " def test_formatting_with_message_none_and_request_id_none(self): err = error.StripeError(None) - assert six.text_type(err) == u"" - if six.PY2: - assert str(err) == "" - else: - assert str(err) == u"" + assert str(err) == u"" def test_repr(self): err = error.StripeError(u"öre", headers={"request-id": "123"}) - if six.PY2: - assert ( - repr(err) - == "StripeError(message=u'\\xf6re', http_status=None, " - "request_id='123')" - ) - else: - assert ( - repr(err) == "StripeError(message='öre', http_status=None, " - "request_id='123')" - ) + assert ( + repr(err) == "StripeError(message='öre', http_status=None, " + "request_id='123')" + ) def test_error_object(self): err = error.StripeError( @@ -74,17 +51,11 @@ def test_repr(self): http_status=403, headers={"request-id": "123"}, ) - if six.PY2: - assert ( - repr(err) == "CardError(message=u'\\xf6re', param='cparam', " - "code='ccode', http_status=403, request_id='123')" - ) - else: - assert ( - repr(err) - == "CardError(message='öre', param='cparam', code='ccode', " - "http_status=403, request_id='123')" - ) + assert ( + repr(err) + == "CardError(message='öre', param='cparam', code='ccode', " + "http_status=403, request_id='123')" + ) class TestApiConnectionError(object): diff --git a/tests/test_http_client.py b/tests/test_http_client.py index 10fbd9dd6..86d3047b0 100644 --- a/tests/test_http_client.py +++ b/tests/test_http_client.py @@ -5,7 +5,7 @@ import stripe import urllib3 -from stripe import six, util +from stripe import util VALID_API_METHODS = ("get", "post", "delete") @@ -775,7 +775,7 @@ def check_call(self): def check_call( mock, method, url, post_data, headers, is_streaming=False ): - if six.PY3 and isinstance(post_data, six.string_types): + if isinstance(post_data, str): post_data = post_data.encode("utf-8") mock.Request.assert_called_with(url, post_data, headers) @@ -912,7 +912,7 @@ def check_call( # statements where things are more likely to go wrong. mock.setopt.assert_any_call(lib_mock.NOSIGNAL, 1) - mock.setopt.assert_any_call(lib_mock.URL, stripe.util.utf8(url)) + mock.setopt.assert_any_call(lib_mock.URL, url) if method == "get": mock.setopt.assert_any_call(lib_mock.HTTPGET, 1) diff --git a/tests/test_multipart_data_generator.py b/tests/test_multipart_data_generator.py index bdb6da830..ff5f64384 100644 --- a/tests/test_multipart_data_generator.py +++ b/tests/test_multipart_data_generator.py @@ -3,8 +3,8 @@ from __future__ import absolute_import, division, print_function import re +import io -from stripe import six from stripe.multipart_data_generator import MultipartDataGenerator @@ -24,10 +24,7 @@ def run_test_multipart_data_with_file(self, test_file): } generator = MultipartDataGenerator() generator.add_params(params) - http_body = generator.get_post_data() - - if six.PY3: - http_body = http_body.decode("utf-8") + http_body = generator.get_post_data().decode("utf-8") assert re.search( r"Content-Disposition: form-data; name=\"key1\"", http_body @@ -70,7 +67,7 @@ def run_test_multipart_data_with_file(self, test_file): test_file.seek(0) file_contents = test_file.read() - if six.PY3 and isinstance(file_contents, bytes): + if isinstance(file_contents, bytes): file_contents = file_contents.decode("utf-8") assert http_body.find(file_contents) != -1 @@ -84,10 +81,10 @@ def test_multipart_data_file_binary(self): self.run_test_multipart_data_with_file(test_file) def test_multipart_data_stringio(self): - string = six.StringIO("foo") + string = io.StringIO("foo") self.run_test_multipart_data_with_file(string) def test_multipart_data_unicode_file_name(self): - string = six.StringIO("foo") + string = io.StringIO("foo") string.name = u"паспорт.png" self.run_test_multipart_data_with_file(string) diff --git a/tests/test_oauth.py b/tests/test_oauth.py index 8b2a23d8e..1a6432fcb 100644 --- a/tests/test_oauth.py +++ b/tests/test_oauth.py @@ -1,6 +1,6 @@ from __future__ import absolute_import, division, print_function -from stripe.six.moves.urllib.parse import parse_qs, urlparse +from urllib.parse import parse_qs, urlparse import stripe diff --git a/tests/test_stripe_object.py b/tests/test_stripe_object.py index 15c26b670..bb0dedcd4 100644 --- a/tests/test_stripe_object.py +++ b/tests/test_stripe_object.py @@ -8,7 +8,6 @@ import pytest import stripe -from stripe import six SAMPLE_INVOICE = json.loads( @@ -245,9 +244,6 @@ def test_repr(self): res = repr(obj) - if six.PY2: - res = six.text_type(repr(obj), "utf-8") - assert u"