From 41c27203483df31426e03ab2453f3ae43677a078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89amonn=20McManus?= Date: Wed, 17 Jun 2015 15:33:15 -0700 Subject: [PATCH 1/2] Remove @util.positional from the authorize() wrapper Since the original method does not have a constraint on positional parameters, its wrapper should not either. See http://stackoverflow.com/questions/18126157/appengine-warning-during-python-app-update/30469210 for a case where this is producing annoying warnings. --- oauth2client/client.py | 1 - 1 file changed, 1 deletion(-) diff --git a/oauth2client/client.py b/oauth2client/client.py index 8108bd8..2613eb1 100644 --- a/oauth2client/client.py +++ b/oauth2client/client.py @@ -532,7 +532,6 @@ class OAuth2Credentials(Credentials): request_orig = http.request # The closure that will replace 'httplib2.Http.request'. - @util.positional(1) def new_request(uri, method='GET', body=None, headers=None, redirections=httplib2.DEFAULT_MAX_REDIRECTS, connection_type=None): From 1426ec69137f1290e58104d036ab1bd9c19d321d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89amonn=20McManus?= Date: Wed, 17 Jun 2015 17:49:55 -0700 Subject: [PATCH 2/2] Add a regression test for the @util.positional bug --- tests/test_oauth2client.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) mode change 100644 => 100755 tests/test_oauth2client.py diff --git a/tests/test_oauth2client.py b/tests/test_oauth2client.py old mode 100644 new mode 100755 index af580f3..da5369c --- a/tests/test_oauth2client.py +++ b/tests/test_oauth2client.py @@ -40,6 +40,7 @@ from .http_mock import HttpMockSequence from oauth2client import GOOGLE_REVOKE_URI from oauth2client import GOOGLE_TOKEN_URI from oauth2client import client +from oauth2client import util as oauth2client_util from oauth2client.client import AccessTokenCredentials from oauth2client.client import AccessTokenCredentialsError from oauth2client.client import AccessTokenRefreshError @@ -581,6 +582,10 @@ class BasicCredentialsTests(unittest.TestCase): refresh_token, token_expiry, GOOGLE_TOKEN_URI, user_agent, revoke_uri=GOOGLE_REVOKE_URI) + # Provoke a failure if @util.positional is not respected. + oauth2client_util.positional_parameters_enforcement = ( + oauth2client_util.POSITIONAL_EXCEPTION) + def test_token_refresh_success(self): for status_code in REFRESH_STATUS_CODES: token_response = {'access_token': '1/3w', 'expires_in': 3600} @@ -595,6 +600,26 @@ class BasicCredentialsTests(unittest.TestCase): self.assertFalse(self.credentials.access_token_expired) self.assertEqual(token_response, self.credentials.token_response) + def test_recursive_authorize(self): + """Tests that OAuth2Credentials does not introduce new method constraints. + + Formerly, OAuth2Credentials.authorize monkeypatched the request method of + its httplib2.Http argument with a wrapper annotated with + @util.positional(1). Since the original method has no such annotation, that + meant that the wrapper was violating the contract of the original method by + adding a new requirement to it. And in fact the wrapper itself doesn't + even respect that requirement. So before the removal of the annotation, this + test would fail. + """ + token_response = {'access_token': '1/3w', 'expires_in': 3600} + encoded_response = json.dumps(token_response).encode('utf-8') + http = HttpMockSequence([ + ({'status': '200'}, encoded_response), + ]) + http = self.credentials.authorize(http) + http = self.credentials.authorize(http) + http.request('http://example.com') + def test_token_refresh_failure(self): for status_code in REFRESH_STATUS_CODES: http = HttpMockSequence([