Repository: globus/globus-sdk-python
Pull request #309 (2018-08-28 20:13:40)

Make RenewingAuthorizer expiration check public
Simply rename:
```
-    def _check_expiration_time(self):
+    def check_expiration_time(self):
```
so that it's official.

Also improve documentation around Renewing Authorizer and its subclasses. In order to do this without writing some complex sphinx extension code or other shenanigans, I accepted a bit of repetition. It makes the docs a tiny bit harder to maintain in exchange for making the docs a lot easier to maintain.


Patch:
diff --git a/globus_sdk/authorizers/client_credentials.py b/globus_sdk/authorizers/client_credentials.py
index 6f82b4ee..d5649942 100644
--- a/globus_sdk/authorizers/client_credentials.py
+++ b/globus_sdk/authorizers/client_credentials.py
@@ -48,8 +48,16 @@ class ClientCredentialsAuthorizer(RenewingAuthorizer):
           POSIX timestamp (i.e. seconds since the epoch)
 
         ``on_refresh`` (*callable*)
-          Will be called as fn(token_data) any time this authorizer
-          fetches a new access_token
+          A callback which is triggered any time this authorizer fetches a new
+          access_token. The ``on_refresh`` callable is invoked on the
+          :class:`OAuthTokenResponse \
+                  <globus_sdk.auth.token_response.OAuthTokenResponse>`
+          object resulting from the token being refreshed.
+          It should take only one argument, the token response object.
+
+          This is useful for implementing storage for Access Tokens, as the
+          ``on_refresh`` callback can be used to update the Access Tokens and
+          their expiration times.
     """
     def __init__(self, confidential_client, scopes,
                  access_token=None, expires_at=None, on_refresh=None):
diff --git a/globus_sdk/authorizers/refresh_token.py b/globus_sdk/authorizers/refresh_token.py
index 6ca6e458..1cd35305 100644
--- a/globus_sdk/authorizers/refresh_token.py
+++ b/globus_sdk/authorizers/refresh_token.py
@@ -43,8 +43,16 @@ class RefreshTokenAuthorizer(RenewingAuthorizer):
           POSIX timestamp (i.e. seconds since the epoch)
 
         ``on_refresh`` (*callable*)
-        Will be called as fn(token_data) any time this authorizer
-        fetches a new access_token
+          A callback which is triggered any time this authorizer fetches a new
+          access_token. The ``on_refresh`` callable is invoked on the
+          :class:`OAuthTokenResponse \
+                  <globus_sdk.auth.token_response.OAuthTokenResponse>`
+          object resulting from the token being refreshed.
+          It should take only one argument, the token response object.
+
+          This is useful for implementing storage for Access Tokens, as the
+          ``on_refresh`` callback can be used to update the Access Tokens and
+          their expiration times.
     """
     def __init__(self, refresh_token, auth_client,
                  access_token=None, expires_at=None, on_refresh=None):
diff --git a/globus_sdk/authorizers/renewing.py b/globus_sdk/authorizers/renewing.py
index 07fe7cd5..e2d711e8 100644
--- a/globus_sdk/authorizers/renewing.py
+++ b/globus_sdk/authorizers/renewing.py
@@ -28,6 +28,28 @@ class RenewingAuthorizer(GlobusAuthorizer):
     To make an authorizer that implements this class implement
     the _get_token_response and _extract_token_data methods for that
     authorization type,
+
+    **Parameters**
+
+        ``access_token`` (*string*)
+          Initial Access Token to use. Used only if ``expires_at`` is also set,
+          otherwise ignored.
+
+        ``expires_at`` (*int*)
+          Expiration time for the starting ``access_token`` expressed as a
+          POSIX timestamp (i.e. seconds since the epoch)
+
+        ``on_refresh`` (*callable*)
+          A callback which is triggered any time this authorizer fetches a new
+          access_token. The ``on_refresh`` callable is invoked on the
+          :class:`OAuthTokenResponse \
+                  <globus_sdk.auth.token_response.OAuthTokenResponse>`
+          object resulting from the token being refreshed.
+          It should take only one argument, the token response object.
+
+          This is useful for implementing storage for Access Tokens, as the
+          ``on_refresh`` callback can be used to update the Access Tokens and
+          their expiration times.
     """
 
     def __init__(self, access_token=None, expires_at=None, on_refresh=None):
@@ -109,9 +131,14 @@ class RenewingAuthorizer(GlobusAuthorizer):
             self.on_refresh(res)
             logger.debug("Invoked on_refresh callback")
 
-    def _check_expiration_time(self):
+    def check_expiration_time(self):
         """
         Check if the expiration timer is done, and renew the token if it is.
+
+        This is called implicitly by ``set_authorization_header``, but you can
+        call it explicitly if you want to ensure that a token gets refreshed.
+        This can be useful in order to get at a new, valid token via the
+        ``on_refresh`` handler.
         """
         logger.debug("RenewingAuthorizer checking expiration time")
         if self.access_token is None or (
@@ -129,7 +156,7 @@ class RenewingAuthorizer(GlobusAuthorizer):
         Once that's done, sets the ``Authorization`` header to
         "Bearer <access_token>"
         """
-        self._check_expiration_time()
+        self.check_expiration_time()
         logger.debug(("Setting RefreshToken Authorization Header:"
                       'Bearer token has hash "{}"')
                      .format(self.access_token_hash))


Test patch:
diff --git a/tests/unit/test_renewing_authorizer.py b/tests/unit/test_renewing_authorizer.py
index ed227b92..ffda8551 100644
--- a/tests/unit/test_renewing_authorizer.py
+++ b/tests/unit/test_renewing_authorizer.py
@@ -105,7 +105,7 @@ class RenewingAuthorizerTests(CapturedIOTestCase):
         """
         Confirms nothing is done before the access_token expires,
         """
-        self.authorizer._check_expiration_time()
+        self.authorizer.check_expiration_time()
         self.assertEqual(self.authorizer.access_token, self.access_token)
 
     def test_check_expiration_time_expired(self):
@@ -113,7 +113,7 @@ class RenewingAuthorizerTests(CapturedIOTestCase):
         Confirms a new access_token is gotten after waiting for expiration
         """
         time.sleep(1)
-        self.authorizer._check_expiration_time()
+        self.authorizer.check_expiration_time()
         self.assertEqual(self.authorizer.access_token,
                          self.token_data["access_token"])
         self.assertEqual(self.authorizer.expires_at,
@@ -125,7 +125,7 @@ class RenewingAuthorizerTests(CapturedIOTestCase):
         Confirms a new access_token is gotten if the old one is set to None
         """
         self.authorizer.access_token = None
-        self.authorizer._check_expiration_time()
+        self.authorizer.check_expiration_time()
         self.assertEqual(self.authorizer.access_token,
                          self.token_data["access_token"])
         self.assertEqual(self.authorizer.expires_at,
@@ -137,7 +137,7 @@ class RenewingAuthorizerTests(CapturedIOTestCase):
         Confirms a new access_token is gotten if expires_at is set to None
         """
         self.authorizer.expires_at = None
-        self.authorizer._check_expiration_time()
+        self.authorizer.check_expiration_time()
         self.assertEqual(self.authorizer.access_token,
                          self.token_data["access_token"])
         self.assertEqual(self.authorizer.expires_at,