diff --git a/requests_oauthlib/compliance_fixes/__init__.py b/requests_oauthlib/compliance_fixes/__init__.py index 65e49c15..1084f63d 100644 --- a/requests_oauthlib/compliance_fixes/__init__.py +++ b/requests_oauthlib/compliance_fixes/__init__.py @@ -6,3 +6,4 @@ from .slack import slack_compliance_fix from .mailchimp import mailchimp_compliance_fix from .weibo import weibo_compliance_fix +from .plentymarkets import plentymarkets_compliance_fix diff --git a/requests_oauthlib/compliance_fixes/plentymarkets.py b/requests_oauthlib/compliance_fixes/plentymarkets.py new file mode 100644 index 00000000..1b8a236f --- /dev/null +++ b/requests_oauthlib/compliance_fixes/plentymarkets.py @@ -0,0 +1,27 @@ +from json import dumps, loads +import re + +from oauthlib.common import to_unicode + + +def plentymarkets_compliance_fix(session): + + def _to_snake_case(n): + return re.sub('(.)([A-Z][a-z]+)', r'\1_\2', n).lower() + + def _compliance_fix(r): + # Plenty returns the Token in CamelCase instead of _ + if 'application/json' in r.headers.get('content-type', {}) and r.status_code == 200: + token = loads(r.text) + else: + return r + + fixed_token = {} + for k, v in token.items(): + fixed_token[_to_snake_case(k)] = v + + r._content = to_unicode(dumps(fixed_token)).encode('UTF-8') + return r + + session.register_compliance_hook('access_token_response', _compliance_fix) + return session diff --git a/tests/test_compliance_fixes.py b/tests/test_compliance_fixes.py index 0184d33b..8e9ee2df 100644 --- a/tests/test_compliance_fixes.py +++ b/tests/test_compliance_fixes.py @@ -20,6 +20,7 @@ from requests_oauthlib.compliance_fixes import mailchimp_compliance_fix from requests_oauthlib.compliance_fixes import weibo_compliance_fix from requests_oauthlib.compliance_fixes import slack_compliance_fix +from requests_oauthlib.compliance_fixes import plentymarkets_compliance_fix class FacebookComplianceFixTest(TestCase): @@ -275,3 +276,40 @@ def test_protected_request_override_token_url(self): query = parse_qs(urlparse(url).query) self.assertEqual(query["token"], ["different-token"]) self.assertIsNone(response.request.body) + + +class PlentymarketsComplianceFixTest(TestCase): + + def setUp(self): + mocker = requests_mock.Mocker() + mocker.post( + "https://shop.plentymarkets-cloud02.com", + json= + { + "accessToken": "ecUN1r8KhJewMCdLAmpHOdZ4O0ofXKB9zf6CXK61", + "tokenType": "Bearer", + "expiresIn": 86400, + "refreshToken": "iG2kBGIjcXaRE4xmTVUnv7xwxX7XMcWCHqJmFaSX" + }, + headers={"Content-Type": "application/json"} + ) + mocker.start() + self.addCleanup(mocker.stop) + + plentymarkets = OAuth2Session('foo', redirect_uri='https://i.b') + self.session = plentymarkets_compliance_fix(plentymarkets) + + def test_fetch_access_token(self): + token = self.session.fetch_token( + "https://shop.plentymarkets-cloud02.com", + authorization_response='https://i.b/?code=hello', + ) + + approx_expires_at = time.time() + 86400 + actual_expires_at = token.pop('expires_at') + self.assertAlmostEqual(actual_expires_at, approx_expires_at, places=2) + + self.assertEqual(token, {u'access_token': u'ecUN1r8KhJewMCdLAmpHOdZ4O0ofXKB9zf6CXK61', + u'expires_in': 86400, + u'token_type': u'Bearer', + u'refresh_token': u'iG2kBGIjcXaRE4xmTVUnv7xwxX7XMcWCHqJmFaSX'})