Repository: GoogleCloudPlatform/google-auth-library-python
Pull request #75 (2016-11-07 21:00:51)

Add scopes argument to default


Patch:
diff --git a/google/auth/_default.py b/google/auth/_default.py
index 356780b..f9829d4 100644
--- a/google/auth/_default.py
+++ b/google/auth/_default.py
@@ -28,6 +28,7 @@ from google.auth import compute_engine
 from google.auth import environment_vars
 from google.auth import exceptions
 from google.auth.compute_engine import _metadata
+import google.auth.credentials
 import google.auth.transport._http_client
 from google.oauth2 import service_account
 import google.oauth2.credentials
@@ -185,7 +186,7 @@ def _get_gce_credentials(request=None):
         return None, None
 
 
-def default(request=None):
+def default(scopes=None, request=None):
     """Gets the default credentials for the current environment.
 
     `Application Default Credentials`_ provides an easy way to obtain
@@ -238,6 +239,9 @@ def default(request=None):
         credentials, project_id = google.auth.default()
 
     Args:
+        scopes (Sequence[str]): The list of scopes for the credentials. If
+            specified, the credentials will automatically be scoped if
+            necessary.
         request (google.auth.transport.Request): An object used to make
             HTTP requests. This is used to detect whether the application
             is running on Compute Engine. If not specified, then it will
@@ -254,7 +258,9 @@ def default(request=None):
             If no credentials were found, or if the credentials found were
             invalid.
     """
-    explicit_project_id = os.environ.get(environment_vars.PROJECT)
+    explicit_project_id = os.environ.get(
+        environment_vars.PROJECT,
+        os.environ.get(environment_vars.LEGACY_PROJECT))
 
     checkers = (
         _get_explicit_environ_credentials,
@@ -265,6 +271,8 @@ def default(request=None):
     for checker in checkers:
         credentials, project_id = checker()
         if credentials is not None:
+            credentials = google.auth.credentials.with_scopes_if_required(
+                credentials, scopes)
             return credentials, explicit_project_id or project_id
 
     raise exceptions.DefaultCredentialsError(_HELP_MESSAGE)
diff --git a/google/auth/environment_vars.py b/google/auth/environment_vars.py
index 9785c34..b4ed2b2 100644
--- a/google/auth/environment_vars.py
+++ b/google/auth/environment_vars.py
@@ -22,6 +22,13 @@ This used by :func:`google.auth.default` to explicitly set a project ID. This
 environment variable is also used by the Google Cloud Python Library.
 """
 
+LEGACY_PROJECT = 'GCLOUD_PROJECT'
+"""Previously used environment variable defining the default project.
+
+This environment variable is used instead of the current one in some
+situations (such as Google App Engine).
+"""
+
 CREDENTIALS = 'GOOGLE_APPLICATION_CREDENTIALS'
 """Environment variable defining the location of Google application default
 credentials."""


Test patch:
diff --git a/tests/test__default.py b/tests/test__default.py
index e244b3d..bfb0c39 100644
--- a/tests/test__default.py
+++ b/tests/test__default.py
@@ -266,6 +266,15 @@ def test_default_explict_project_id(get_mock, monkeypatch):
         mock.sentinel.credentials, 'explicit-env')
 
 
+@mock.patch(
+    'google.auth._default._get_explicit_environ_credentials',
+    return_value=(mock.sentinel.credentials, mock.sentinel.project_id))
+def test_default_explict_legacy_project_id(get_mock, monkeypatch):
+    monkeypatch.setenv(environment_vars.LEGACY_PROJECT, 'explicit-env')
+    assert _default.default() == (
+        mock.sentinel.credentials, 'explicit-env')
+
+
 @mock.patch(
     'google.auth._default._get_explicit_environ_credentials',
     return_value=(None, None))
@@ -281,3 +290,19 @@ def test_default_explict_project_id(get_mock, monkeypatch):
 def test_default_fail(unused_gce, unused_gae, unused_sdk, unused_explicit):
     with pytest.raises(exceptions.DefaultCredentialsError):
         assert _default.default()
+
+
+@mock.patch(
+    'google.auth._default._get_explicit_environ_credentials',
+    return_value=(mock.sentinel.credentials, mock.sentinel.project_id))
+@mock.patch(
+    'google.auth.credentials.with_scopes_if_required')
+def test_default_scoped(with_scopes_mock, get_mock):
+    scopes = ['one', 'two']
+
+    credentials, project_id = _default.default(scopes=scopes)
+
+    assert credentials == with_scopes_mock.return_value
+    assert project_id == mock.sentinel.project_id
+    with_scopes_mock.assert_called_once_with(
+        mock.sentinel.credentials, scopes)