Repository: GoogleCloudPlatform/google-auth-library-python
Pull request #206 (2017-10-30 19:48:36)

Add 'AnonymousCredentials' class.
See: https://github.com/GoogleCloudPlatform/google-cloud-python/issues/4279.

/cc @jonparrott 


Patch:
diff --git a/google/auth/credentials.py b/google/auth/credentials.py
index 28f9c9f..1fb5dec 100644
--- a/google/auth/credentials.py
+++ b/google/auth/credentials.py
@@ -122,6 +122,43 @@ class Credentials(object):
         self.apply(headers)
 
 
+class AnonymousCredentials(Credentials):
+    """Credentials that do not provide any authentication information.
+
+    These are useful in the case of services that support anonymous access or
+    local service emulators that do not use credentials.
+    """
+
+    @property
+    def expired(self):
+        """Returns `False`, anonymous credentials never expire."""
+        return False
+
+    @property
+    def valid(self):
+        """Returns `True`, anonymous credentials are always valid."""
+        return True
+
+    def refresh(self, request):
+        """Raises :class:`ValueError``, anonymous credentials cannot be
+        refreshed."""
+        raise ValueError("Anonymous credentials cannot be refreshed.")
+
+    def apply(self, headers, token=None):
+        """Anonymous credentials do nothing to the request.
+
+        The optional ``token`` argument is not supported.
+
+        Raises:
+            ValueError: If a token was specified.
+        """
+        if token is not None:
+            raise ValueError("Anonymous credentials don't support tokens.")
+
+    def before_request(self, request, method, url, headers):
+        """Anonymous credentials do nothing to the request."""
+
+
 @six.add_metaclass(abc.ABCMeta)
 class ReadOnlyScoped(object):
     """Interface for credentials whose scopes can be queried.


Test patch:
diff --git a/tests/test_credentials.py b/tests/test_credentials.py
index 128ae1a..b302989 100644
--- a/tests/test_credentials.py
+++ b/tests/test_credentials.py
@@ -14,6 +14,8 @@
 
 import datetime
 
+import pytest
+
 from google.auth import _helpers
 from google.auth import credentials
 
@@ -77,6 +79,40 @@ def test_before_request():
     assert headers['authorization'] == 'Bearer token'
 
 
+def test_anonymous_credentials_ctor():
+    anon = credentials.AnonymousCredentials()
+    assert anon.token is None
+    assert anon.expiry is None
+    assert not anon.expired
+    assert anon.valid
+
+
+def test_anonymous_credentials_refresh():
+    anon = credentials.AnonymousCredentials()
+    request = object()
+    with pytest.raises(ValueError):
+        anon.refresh(request)
+
+
+def test_anonymous_credentials_apply_default():
+    anon = credentials.AnonymousCredentials()
+    headers = {}
+    anon.apply(headers)
+    assert headers == {}
+    with pytest.raises(ValueError):
+        anon.apply(headers, token='TOKEN')
+
+
+def test_anonymous_credentials_before_request():
+    anon = credentials.AnonymousCredentials()
+    request = object()
+    method = 'GET'
+    url = 'https://example.com/api/endpoint'
+    headers = {}
+    anon.before_request(request, method, url, headers)
+    assert headers == {}
+
+
 class ReadOnlyScopedCredentialsImpl(
         credentials.ReadOnlyScoped, CredentialsImpl):
     @property