Repository: googleapis/google-cloud-python

Issue:
Cleanup duplicated "credentials can not sign" error
Context: https://github.com/GoogleCloudPlatform/google-cloud-python/pull/2998#discussion_r100650121


Discussion:
@jonparrott Is this still a thing?
Good question - @dhermes is it?
We still have duplicated code:

```
$ git log -1 --pretty=%H
d750a1394781dbe33679057c02233d2dfc2540e1
$ git grep -n 'you need a private key to sign'
storage/google/cloud/storage/_signing.py:51:        raise AttributeError('you need a private key to sign credentials.'
storage/google/cloud/storage/bucket.py:1121:                'you need a private key to sign credentials.'
```

Now that `google.cloud.storage._signing` exists, you could probably move the check from `Bucket.generate_upload_policy()` into the `_signing` module.
Meta-comment: This is a really good example of an issue where a `TODO` in the code would have served a lot better than an issue does. The issue actually _loses_ context.

Resolving patch:
diff --git a/storage/google/cloud/storage/_signing.py b/storage/google/cloud/storage/_signing.py
--- a/storage/google/cloud/storage/_signing.py
+++ b/storage/google/cloud/storage/_signing.py
@@ -25,6 +25,23 @@
 NOW = datetime.datetime.utcnow  # To be replaced by tests.
 
 
+def ensure_signed_credentials(credentials):
+    """Raise AttributeError if the credentials are unsigned.
+
+    :type credentials: :class:`google.auth.credentials.Signer`
+    :param credentials: The credentials used to create a private key
+                        for signing text.
+    """
+    if not isinstance(credentials, google.auth.credentials.Signing):
+        auth_uri = ('https://google-cloud-python.readthedocs.io/en/latest/'
+                    'core/auth.html?highlight=authentication#setting-up-'
+                    'a-service-account')
+        raise AttributeError('you need a private key to sign credentials.'
+                             'the credentials you are currently using %s '
+                             'just contains a token. see %s for more '
+                             'details.' % (type(credentials), auth_uri))
+
+
 def get_signed_query_params(credentials, expiration, string_to_sign):
     """Gets query parameters for creating a signed URL.
 
@@ -44,15 +61,7 @@ def get_signed_query_params(credentials, expiration, string_to_sign):
     :returns: Query parameters matching the signing credentials with a
               signed payload.
     """
-    if not isinstance(credentials, google.auth.credentials.Signing):
-        auth_uri = ('https://google-cloud-python.readthedocs.io/en/latest/'
-                    'core/auth.html?highlight=authentication#setting-up-'
-                    'a-service-account')
-        raise AttributeError('you need a private key to sign credentials.'
-                             'the credentials you are currently using %s '
-                             'just contains a token. see %s for more '
-                             'details.' % (type(credentials), auth_uri))
-
+    ensure_signed_credentials(credentials)
     signature_bytes = credentials.sign_bytes(string_to_sign)
     signature = base64.b64encode(signature_bytes)
     service_account_name = credentials.signer_email
diff --git a/storage/google/cloud/storage/bucket.py b/storage/google/cloud/storage/bucket.py
--- a/storage/google/cloud/storage/bucket.py
+++ b/storage/google/cloud/storage/bucket.py
@@ -19,7 +19,6 @@
 import datetime
 import json
 
-import google.auth.credentials
 import six
 
 from google.api.core import page_iterator
@@ -28,6 +27,7 @@
 from google.cloud._helpers import _rfc3339_to_datetime
 from google.cloud.exceptions import NotFound
 from google.cloud.iam import Policy
+from google.cloud.storage import _signing
 from google.cloud.storage._helpers import _PropertyMixin
 from google.cloud.storage._helpers import _scalar_property
 from google.cloud.storage._helpers import _validate_name
@@ -1112,16 +1112,7 @@ def generate_upload_policy(
         """
         client = self._require_client(client)
         credentials = client._base_connection.credentials
-
-        if not isinstance(credentials, google.auth.credentials.Signing):
-            auth_uri = ('https://google-cloud-python.readthedocs.io/en/latest/'
-                        'core/auth.html?highlight=authentication#setting-up-'
-                        'a-service-account')
-            raise AttributeError(
-                'you need a private key to sign credentials.'
-                'the credentials you are currently using %s '
-                'just contains a token. see %s for more '
-                'details.' % (type(credentials), auth_uri))
+        _signing.ensure_signed_credentials(credentials)
 
         if expiration is None:
             expiration = _NOW() + datetime.timedelta(hours=1)


Test patch: