diff --git a/README.md b/README.md index 6c99d50..2dc7e9b 100644 --- a/README.md +++ b/README.md @@ -19,11 +19,10 @@ source code") for `payjp-python`, and then run: Please see our official [documentation](https://pay.jp/docs/api). -## Dependencies +## Dependencies - requests -- six Install dependencies from using [pip](http://www.pip-installer.org/en/latest/): - + pip install -r requirements.txt diff --git a/payjp/api_requestor.py b/payjp/api_requestor.py index 69ec46a..168bff4 100644 --- a/payjp/api_requestor.py +++ b/payjp/api_requestor.py @@ -8,15 +8,12 @@ import platform import time import random - -from six import PY3 -from six.moves.urllib.parse import urlencode, urlsplit, urlunsplit +from urllib.parse import urlencode, urlsplit, urlunsplit import payjp from . import ( error, http_client, - util, version, ) @@ -128,12 +125,9 @@ def request_raw(self, method, url, params=None, supplied_headers=None): val = '!! %s' % (e,) ua[attr] = val - if PY3: - encoded_api_key = str( - base64.b64encode( - bytes(''.join([my_api_key, ':']), 'utf-8')), 'utf-8') - else: - encoded_api_key = base64.b64encode(''.join([my_api_key, ':'])) + encoded_api_key = str( + base64.b64encode( + bytes(''.join([my_api_key, ':']), 'utf-8')), 'utf-8') headers = { 'X-Payjp-Client-User-Agent': json.dumps(ua), @@ -190,14 +184,13 @@ def _encode_datetime(dttime): def _api_encode(data): for key, value in data.items(): - key = util.utf8(key) if value is None: continue elif hasattr(value, 'payjp_id'): yield (key, value.payjp_id) elif isinstance(value, list) or isinstance(value, tuple): for subvalue in value: - yield ("%s[]" % (key,), util.utf8(subvalue)) + yield ("%s[]" % (key,), subvalue) elif isinstance(value, dict): subdict = dict(('%s[%s]' % (key, subkey), subvalue) for subkey, subvalue in value.items()) @@ -206,7 +199,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): scheme, netloc, path, base_query, fragment = urlsplit(url) @@ -215,4 +208,3 @@ def _build_api_url(url, query): query = '%s&%s' % (base_query, query) return urlunsplit((scheme, netloc, path, query, fragment)) - diff --git a/payjp/error.py b/payjp/error.py index c1a82ac..027f130 100644 --- a/payjp/error.py +++ b/payjp/error.py @@ -16,7 +16,7 @@ def __init__(self, message=None, http_body=None, http_status=None, self.http_body = http_body self.http_status = http_status - self.json_body = json_body + self.json_body = json_body class APIError(PayjpException): @@ -33,7 +33,7 @@ def __init__(self, message, param, code, http_body=None, super(CardError, self).__init__(message, http_body, http_status, json_body) self.param = param - self.code = code + self.code = code class AuthenticationError(PayjpException): diff --git a/payjp/resource.py b/payjp/resource.py index 1b55c27..b4e9f8b 100644 --- a/payjp/resource.py +++ b/payjp/resource.py @@ -3,11 +3,9 @@ import json import logging import sys +from urllib.parse import quote_plus -from six import string_types -from six.moves.urllib.parse import quote_plus - -from payjp import api_requestor, error, util +from payjp import api_requestor, error logger = logging.getLogger('payjp') @@ -34,7 +32,7 @@ def convert_to_payjp_object(resp, api_key, account, api_base=None): elif isinstance(resp, dict) and not isinstance(resp, PayjpObject): resp = resp.copy() klass_name = resp.get('object') - if isinstance(klass_name, string_types): + if isinstance(klass_name, str): klass = types.get(klass_name, PayjpObject) else: klass = PayjpObject @@ -206,10 +204,10 @@ def request(self, method, url, params=None, headers=None): def __repr__(self): ident_parts = [type(self).__name__] - if isinstance(self.get('object'), string_types): + if isinstance(self.get('object'), str): ident_parts.append(self.get('object')) - if isinstance(self.get('id'), string_types): + if isinstance(self.get('id'), str): ident_parts.append('id=%s' % (self.get('id'),)) unicode_repr = '<%s at %s> JSON: %s' % ( @@ -241,7 +239,6 @@ def create(self, **params): def retrieve(self, id, **params): base = self.get('url') - id = util.utf8(id) extn = quote_plus(id) url = "%s/%s" % (base, extn) @@ -382,7 +379,6 @@ def instance_url(self): id = self.get('id') if not id: return "/v1/accounts" - id = util.utf8(id) base = self.class_url() extn = quote_plus(id) return "%s/%s" % (base, extn) @@ -391,11 +387,8 @@ def instance_url(self): class Card(UpdateableAPIResource, DeletableAPIResource): def instance_url(self): - self.id = util.utf8(self.id) extn = quote_plus(self.id) if (hasattr(self, 'customer')): - self.customer = util.utf8(self.customer) - base = Customer.class_url() owner_extn = quote_plus(self.customer) diff --git a/payjp/test/helper.py b/payjp/test/helper.py index a93c706..ae6d366 100644 --- a/payjp/test/helper.py +++ b/payjp/test/helper.py @@ -8,8 +8,6 @@ from mock import patch, Mock -from six import string_types - import payjp NOW = datetime.datetime.now() @@ -72,7 +70,7 @@ def assertRaisesRegexp(self, exception, regexp, callable, *args, **kwargs): if regexp is None: return True - if isinstance(regexp, string_types): + if isinstance(regexp, str): regexp = re.compile(regexp) if not regexp.search(str(err)): raise self.failureException('"%s" does not match "%s"' % diff --git a/payjp/test/test_integration.py b/payjp/test/test_integration.py index 9e7a6b4..749201b 100644 --- a/payjp/test/test_integration.py +++ b/payjp/test/test_integration.py @@ -3,8 +3,6 @@ import unittest import payjp -from six import string_types - from payjp.test.helper import (PayjpTestCase, NOW, DUMMY_CARD) @@ -17,7 +15,7 @@ def test_invalid_credentials(self): payjp.Customer.create() except payjp.error.AuthenticationError as e: self.assertEqual(401, e.http_status) - self.assertTrue(isinstance(e.http_body, string_types)) + self.assertTrue(isinstance(e.http_body, str)) self.assertTrue(isinstance(e.json_body, dict)) finally: payjp.api_key = key @@ -33,7 +31,7 @@ def test_invalid_card_props(self): payjp.Charge.create(amount=100, currency='jpy', card=EXPIRED_CARD) except payjp.error.InvalidRequestError as e: self.assertEqual(400, e.http_status) - self.assertTrue(isinstance(e.http_body, string_types)) + self.assertTrue(isinstance(e.http_body, str)) self.assertTrue(isinstance(e.json_body, dict)) @@ -44,7 +42,7 @@ def test_nonexistent_object(self): payjp.Charge.retrieve('invalid') except payjp.error.InvalidRequestError as e: self.assertEqual(404, e.http_status) - self.assertTrue(isinstance(e.http_body, string_types)) + self.assertTrue(isinstance(e.http_body, str)) self.assertTrue(isinstance(e.json_body, dict)) def test_invalid_data(self): @@ -52,7 +50,7 @@ def test_invalid_data(self): payjp.Charge.create() except payjp.error.InvalidRequestError as e: self.assertEqual(400, e.http_status) - self.assertTrue(isinstance(e.http_body, string_types)) + self.assertTrue(isinstance(e.http_body, str)) self.assertTrue(isinstance(e.json_body, dict)) diff --git a/payjp/test/test_requestor.py b/payjp/test/test_requestor.py index be8e6c7..cdc79d3 100644 --- a/payjp/test/test_requestor.py +++ b/payjp/test/test_requestor.py @@ -3,10 +3,9 @@ import base64 import datetime import unittest +from urllib.parse import parse_qsl, urlsplit from mock import Mock, MagicMock, patch -from six.moves.urllib.parse import parse_qsl, urlsplit -from six import PY3 import payjp @@ -45,12 +44,9 @@ def __eq__(self, other): self._extra_match(other)) def _encode(self, api_key): - if PY3: - return str( - base64.b64encode( - bytes(''.join([api_key, ':']), 'utf-8')), 'utf-8') - else: - return base64.b64encode(''.join([api_key, ':'])) + return str( + base64.b64encode( + bytes(''.join([api_key, ':']), 'utf-8')), 'utf-8') def _keys_match(self, other): expected_keys = self.EXP_KEYS + list(self.extra.keys()) @@ -137,7 +133,7 @@ class APIRequestorRequestTests(PayjpUnitTestCase): ('%s[]', 'baz'), ], 'string': [('%s', 'boo')], - 'unicode': [('%s', payjp.util.utf8(u'\u1234'))], + 'unicode': [('%s', u'\u1234')], 'datetime': [('%s', 1356994801)], 'none': [], } @@ -413,7 +409,7 @@ def test_retry_disabled(self): with self.request_raw_patch: with self.assertRaises(payjp.error.APIError) as error: self.requestor.request('get', '/test', {}) - + self.assertEqual(error.exception.http_status, 499) def test_no_retry(self): @@ -423,7 +419,7 @@ def test_no_retry(self): with self.request_raw_patch: with self.assertRaises(payjp.error.APIError) as error: self.requestor.request('get', '/test', {}) - + self.assertEqual(error.exception.http_status, 599) def test_full_retry(self): @@ -434,7 +430,7 @@ def test_full_retry(self): with self.request_raw_patch: with self.assertRaises(payjp.error.APIError) as error: self.requestor.request('get', '/test', {}) - + self.assertEqual(error.exception.http_status, 429) def test_success_at_halfway_of_retries(self): @@ -464,7 +460,7 @@ def test_retry_initial_delay(self): self.assertTrue(16 <= self.requestor._get_retry_delay(10) <= 32) - + if __name__ == '__main__': unittest.main() diff --git a/payjp/util.py b/payjp/util.py deleted file mode 100644 index 248d3ff..0000000 --- a/payjp/util.py +++ /dev/null @@ -1,9 +0,0 @@ -# coding: utf-8 - -import sys - -def utf8(value): - if sys.version_info < (3, 0) and isinstance(value, unicode): - return value.encode('utf-8') - else: - return value diff --git a/requirements.txt b/requirements.txt index 640e3d4..f229360 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1 @@ requests -six diff --git a/setup.py b/setup.py index c1f5546..696ad9c 100644 --- a/setup.py +++ b/setup.py @@ -1,16 +1,13 @@ -# coding: utf-8 - import sys from setuptools import setup install_requires = [] -if sys.version_info < (2, 7): - raise DeprecationWarning('Python 2.6 and older are no longer supported by PAY.JP. ') +if sys.version_info < (3, 8): + raise DeprecationWarning('Python versions below 3.8 are no longer supported by PAY.JP. Please use Python 3.8 or higher.') install_requires.append('requests >= 2.7.0') -install_requires.append('six >= 1.9.0') setup( name="payjp", @@ -21,4 +18,5 @@ packages=['payjp', 'payjp.test'], url='https://github.com/payjp/payjp-python', install_requires=install_requires, + python_requires='>=3.0', )