diff --git a/bigquery/unit_tests/test_client.py b/bigquery/unit_tests/test_client.py index 61ad81227aee..74b27b843905 100644 --- a/bigquery/unit_tests/test_client.py +++ b/bigquery/unit_tests/test_client.py @@ -28,7 +28,7 @@ def _make_one(self, *args, **kw): def test_ctor(self): from google.cloud.bigquery._http import Connection PROJECT = 'PROJECT' - creds = _Credentials() + creds = object() http = object() client = self._make_one(project=PROJECT, credentials=creds, http=http) self.assertIsInstance(client._connection, Connection) @@ -57,7 +57,7 @@ def test_list_projects_defaults(self): 'friendlyName': 'Two'}, ] } - creds = _Credentials() + creds = object() client = self._make_one(PROJECT_1, creds) conn = client._connection = _Connection(DATA) @@ -86,7 +86,7 @@ def test_list_projects_explicit_response_missing_projects_key(self): PATH = 'projects' TOKEN = 'TOKEN' DATA = {} - creds = _Credentials() + creds = object() client = self._make_one(PROJECT, creds) conn = client._connection = _Connection(DATA) @@ -128,7 +128,7 @@ def test_list_datasets_defaults(self): 'friendlyName': 'Two'}, ] } - creds = _Credentials() + creds = object() client = self._make_one(PROJECT, creds) conn = client._connection = _Connection(DATA) @@ -156,7 +156,7 @@ def test_list_datasets_explicit_response_missing_datasets_key(self): PATH = 'projects/%s/datasets' % PROJECT TOKEN = 'TOKEN' DATA = {} - creds = _Credentials() + creds = object() client = self._make_one(PROJECT, creds) conn = client._connection = _Connection(DATA) @@ -180,7 +180,7 @@ def test_dataset(self): from google.cloud.bigquery.dataset import Dataset PROJECT = 'PROJECT' DATASET = 'dataset_name' - creds = _Credentials() + creds = object() http = object() client = self._make_one(project=PROJECT, credentials=creds, http=http) dataset = client.dataset(DATASET) @@ -190,7 +190,7 @@ def test_dataset(self): def test_job_from_resource_unknown_type(self): PROJECT = 'PROJECT' - creds = _Credentials() + creds = object() client = self._make_one(PROJECT, creds) with self.assertRaises(ValueError): client.job_from_resource({'configuration': {'nonesuch': {}}}) @@ -304,7 +304,7 @@ def test_list_jobs_defaults(self): LOAD_DATA, ] } - creds = _Credentials() + creds = object() client = self._make_one(PROJECT, creds) conn = client._connection = _Connection(DATA) @@ -360,7 +360,7 @@ def test_list_jobs_load_job_wo_sourceUris(self): LOAD_DATA, ] } - creds = _Credentials() + creds = object() client = self._make_one(PROJECT, creds) conn = client._connection = _Connection(DATA) @@ -388,7 +388,7 @@ def test_list_jobs_explicit_missing(self): PATH = 'projects/%s/jobs' % PROJECT DATA = {} TOKEN = 'TOKEN' - creds = _Credentials() + creds = object() client = self._make_one(PROJECT, creds) conn = client._connection = _Connection(DATA) @@ -419,7 +419,7 @@ def test_load_table_from_storage(self): DATASET = 'dataset_name' DESTINATION = 'destination_table' SOURCE_URI = 'http://example.com/source.csv' - creds = _Credentials() + creds = object() http = object() client = self._make_one(project=PROJECT, credentials=creds, http=http) dataset = client.dataset(DATASET) @@ -438,7 +438,7 @@ def test_copy_table(self): DATASET = 'dataset_name' SOURCE = 'source_table' DESTINATION = 'destination_table' - creds = _Credentials() + creds = object() http = object() client = self._make_one(project=PROJECT, credentials=creds, http=http) dataset = client.dataset(DATASET) @@ -458,7 +458,7 @@ def test_extract_table_to_storage(self): DATASET = 'dataset_name' SOURCE = 'source_table' DESTINATION = 'gs://bucket_name/object_name' - creds = _Credentials() + creds = object() http = object() client = self._make_one(project=PROJECT, credentials=creds, http=http) dataset = client.dataset(DATASET) @@ -475,7 +475,7 @@ def test_run_async_query(self): PROJECT = 'PROJECT' JOB = 'job_name' QUERY = 'select count(*) from persons' - creds = _Credentials() + creds = object() http = object() client = self._make_one(project=PROJECT, credentials=creds, http=http) job = client.run_async_query(JOB, QUERY) @@ -488,7 +488,7 @@ def test_run_sync_query(self): from google.cloud.bigquery.query import QueryResults PROJECT = 'PROJECT' QUERY = 'select count(*) from persons' - creds = _Credentials() + creds = object() http = object() client = self._make_one(project=PROJECT, credentials=creds, http=http) job = client.run_sync_query(QUERY) @@ -498,19 +498,6 @@ def test_run_sync_query(self): self.assertEqual(job.query, QUERY) -class _Credentials(object): - - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self - - class _Connection(object): def __init__(self, *responses): diff --git a/bigtable/google/cloud/bigtable/client.py b/bigtable/google/cloud/bigtable/client.py index 18d9c685916f..037b6efa15ea 100644 --- a/bigtable/google/cloud/bigtable/client.py +++ b/bigtable/google/cloud/bigtable/client.py @@ -29,6 +29,7 @@ import os +import google.auth.credentials from google.longrunning import operations_grpc from google.cloud._helpers import make_insecure_stub @@ -201,14 +202,16 @@ def __init__(self, project=None, credentials=None, else: scopes.append(DATA_SCOPE) + self._read_only = bool(read_only) + if admin: scopes.append(ADMIN_SCOPE) self._admin = bool(admin) - try: - credentials = credentials.create_scoped(scopes) - except AttributeError: - pass + + credentials = google.auth.credentials.with_scopes_if_required( + credentials, scopes) + self._credentials = credentials self.user_agent = user_agent self.emulator_host = os.getenv(BIGTABLE_EMULATOR) @@ -229,12 +232,10 @@ def copy(self): :rtype: :class:`.Client` :returns: A copy of the current client. """ - credentials = self._credentials - copied_creds = credentials.create_scoped(credentials.scopes) return self.__class__( self.project, - copied_creds, - READ_ONLY_SCOPE in copied_creds.scopes, + self._credentials, + self._read_only, self._admin, self.user_agent, ) diff --git a/bigtable/tox.ini b/bigtable/tox.ini index ac77cf8fe314..257e21288b27 100644 --- a/bigtable/tox.ini +++ b/bigtable/tox.ini @@ -7,6 +7,7 @@ localdeps = pip install --quiet --upgrade {toxinidir}/../core deps = {toxinidir}/../core + mock pytest covercmd = py.test --quiet \ diff --git a/bigtable/unit_tests/test_client.py b/bigtable/unit_tests/test_client.py index bd880c6dc669..a6b82cde0aae 100644 --- a/bigtable/unit_tests/test_client.py +++ b/bigtable/unit_tests/test_client.py @@ -26,7 +26,7 @@ def test_without_emulator(self): from google.cloud._testing import _Monkey from google.cloud.bigtable import client as MUT - credentials = _Credentials() + credentials = object() user_agent = 'you-sir-age-int' client = _Client(credentials, user_agent) @@ -86,7 +86,7 @@ def test_without_emulator(self): from google.cloud._testing import _Monkey from google.cloud.bigtable import client as MUT - credentials = _Credentials() + credentials = object() user_agent = 'you-sir-age-int' client = _Client(credentials, user_agent) @@ -148,7 +148,7 @@ def test_without_emulator(self): from google.cloud._testing import _Monkey from google.cloud.bigtable import client as MUT - credentials = _Credentials() + credentials = object() user_agent = 'you-sir-age-int' client = _Client(credentials, user_agent) @@ -210,7 +210,7 @@ def test_without_emulator(self): from google.cloud._testing import _Monkey from google.cloud.bigtable import client as MUT - credentials = _Credentials() + credentials = object() user_agent = 'you-sir-age-int' client = _Client(credentials, user_agent) @@ -289,6 +289,11 @@ def _make_oneWithMocks(self, *args, **kwargs): _make_table_stub=mock_make_table_stub): return self._make_one(*args, **kwargs) + def _make_credentials(self): + import mock + import google.auth.credentials + return mock.Mock(spec=google.auth.credentials.Scoped) + def _constructor_test_helper(self, expected_scopes, creds, read_only=False, admin=False, user_agent=None, expected_creds=None): @@ -320,10 +325,11 @@ def _constructor_test_helper(self, expected_scopes, creds, self.assertSequenceEqual(mock_make_operations_stub.calls, []) self.assertSequenceEqual(mock_make_table_stub.calls, []) - expected_creds = expected_creds or creds + expected_creds = expected_creds or creds.with_scopes.return_value self.assertIs(client._credentials, expected_creds) + if expected_scopes is not None: - self.assertEqual(client._credentials.scopes, expected_scopes) + creds.with_scopes.assert_called_once_with(expected_scopes) self.assertEqual(client.project, self.PROJECT) self.assertEqual(client.user_agent, user_agent) @@ -345,7 +351,7 @@ def test_constructor_default_scopes(self): from google.cloud.bigtable import client as MUT expected_scopes = [MUT.DATA_SCOPE] - creds = _Credentials() + creds = self._make_credentials() self._constructor_test_helper(expected_scopes, creds) def test_constructor_custom_user_agent(self): @@ -353,7 +359,7 @@ def test_constructor_custom_user_agent(self): CUSTOM_USER_AGENT = 'custom-application' expected_scopes = [MUT.DATA_SCOPE] - creds = _Credentials() + creds = self._make_credentials() self._constructor_test_helper(expected_scopes, creds, user_agent=CUSTOM_USER_AGENT) @@ -361,18 +367,18 @@ def test_constructor_with_admin(self): from google.cloud.bigtable import client as MUT expected_scopes = [MUT.DATA_SCOPE, MUT.ADMIN_SCOPE] - creds = _Credentials() + creds = self._make_credentials() self._constructor_test_helper(expected_scopes, creds, admin=True) def test_constructor_with_read_only(self): from google.cloud.bigtable import client as MUT expected_scopes = [MUT.READ_ONLY_SCOPE] - creds = _Credentials() + creds = self._make_credentials() self._constructor_test_helper(expected_scopes, creds, read_only=True) def test_constructor_both_admin_and_read_only(self): - creds = _Credentials() + creds = self._make_credentials() with self.assertRaises(ValueError): self._constructor_test_helper([], creds, admin=True, read_only=True) @@ -381,18 +387,21 @@ def test_constructor_implicit_credentials(self): from google.cloud._testing import _Monkey from google.cloud.bigtable import client as MUT - creds = _Credentials() + creds = self._make_credentials() expected_scopes = [MUT.DATA_SCOPE] def mock_get_credentials(): return creds with _Monkey(MUT, get_credentials=mock_get_credentials): - self._constructor_test_helper(expected_scopes, None, - expected_creds=creds) + self._constructor_test_helper( + None, None, + expected_creds=creds.with_scopes.return_value) + + creds.with_scopes.assert_called_once_with(expected_scopes) def test_constructor_credentials_wo_create_scoped(self): - creds = object() + creds = self._make_credentials() expected_scopes = None self._constructor_test_helper(expected_scopes, creds) @@ -400,7 +409,7 @@ def _copy_test_helper(self, read_only=False, admin=False): from google.cloud._testing import _Monkey from google.cloud.bigtable import client as MUT - credentials = _Credentials('value') + credentials = self._make_credentials() client = self._make_oneWithMocks( project=self.PROJECT, credentials=credentials, @@ -447,14 +456,14 @@ def test_copy_read_only(self): self._copy_test_helper(read_only=True) def test_credentials_getter(self): - credentials = _Credentials() + credentials = object() project = 'PROJECT' client = self._make_oneWithMocks(project=project, credentials=credentials) self.assertIs(client.credentials, credentials) def test_project_name_property(self): - credentials = _Credentials() + credentials = object() project = 'PROJECT' client = self._make_oneWithMocks(project=project, credentials=credentials) @@ -462,14 +471,14 @@ def test_project_name_property(self): self.assertEqual(client.project_name, project_name) def test_instance_stub_getter(self): - credentials = _Credentials() + credentials = object() project = 'PROJECT' client = self._make_oneWithMocks(project=project, credentials=credentials, admin=True) self.assertIs(client._instance_stub, client._instance_stub_internal) def test_instance_stub_non_admin_failure(self): - credentials = _Credentials() + credentials = object() project = 'PROJECT' client = self._make_oneWithMocks(project=project, credentials=credentials, admin=False) @@ -477,7 +486,7 @@ def test_instance_stub_non_admin_failure(self): getattr(client, '_instance_stub') def test_operations_stub_getter(self): - credentials = _Credentials() + credentials = object() project = 'PROJECT' client = self._make_oneWithMocks(project=project, credentials=credentials, admin=True) @@ -485,7 +494,7 @@ def test_operations_stub_getter(self): client._operations_stub_internal) def test_operations_stub_non_admin_failure(self): - credentials = _Credentials() + credentials = object() project = 'PROJECT' client = self._make_oneWithMocks(project=project, credentials=credentials, admin=False) @@ -493,14 +502,14 @@ def test_operations_stub_non_admin_failure(self): getattr(client, '_operations_stub') def test_table_stub_getter(self): - credentials = _Credentials() + credentials = object() project = 'PROJECT' client = self._make_oneWithMocks(project=project, credentials=credentials, admin=True) self.assertIs(client._table_stub, client._table_stub_internal) def test_table_stub_non_admin_failure(self): - credentials = _Credentials() + credentials = object() project = 'PROJECT' client = self._make_oneWithMocks(project=project, credentials=credentials, admin=False) @@ -516,7 +525,7 @@ def test_instance_factory_defaults(self): PROJECT = 'PROJECT' INSTANCE_ID = 'instance-id' DISPLAY_NAME = 'display-name' - credentials = _Credentials() + credentials = object() client = self._make_oneWithMocks(project=PROJECT, credentials=credentials) @@ -538,7 +547,7 @@ def test_instance_factory_w_explicit_serve_nodes(self): DISPLAY_NAME = 'display-name' LOCATION_ID = 'locname' SERVE_NODES = 5 - credentials = _Credentials() + credentials = object() client = self._make_oneWithMocks(project=PROJECT, credentials=credentials) @@ -569,7 +578,7 @@ def test_list_instances(self): INSTANCE_NAME2 = ( 'projects/' + self.PROJECT + '/instances/' + INSTANCE_ID2) - credentials = _Credentials() + credentials = object() client = self._make_oneWithMocks( project=self.PROJECT, credentials=credentials, @@ -619,22 +628,6 @@ def test_list_instances(self): )]) -class _Credentials(object): - - scopes = None - - def __init__(self, access_token=None): - self._access_token = access_token - self._tokens = [] - - def create_scoped(self, scope): - self.scopes = scope - return self - - def __eq__(self, other): - return self._access_token == other._access_token - - class _Client(object): def __init__(self, credentials, user_agent, emulator_host=None): diff --git a/core/google/cloud/_helpers.py b/core/google/cloud/_helpers.py index 33d9161cbf58..9b4ec5736cb0 100644 --- a/core/google/cloud/_helpers.py +++ b/core/google/cloud/_helpers.py @@ -22,27 +22,25 @@ import calendar import datetime -import json import os import re -import socket from threading import local as Local +import google.auth from google.protobuf import timestamp_pb2 -try: - from google.appengine.api import app_identity -except ImportError: - app_identity = None +import google_auth_httplib2 + try: import grpc -except ImportError: # pragma: NO COVER + from google.auth.transport.grpc import ( + AuthMetadataPlugin) # pragma: NO COVER +except ImportError: grpc = None + AuthMetadataPlugin = None + +import httplib2 import six from six.moves import http_client -from six.moves import configparser - -from google.cloud.environment_vars import PROJECT -from google.cloud.environment_vars import CREDENTIALS _NOW = datetime.datetime.utcnow # To be replaced by tests. @@ -168,139 +166,11 @@ def _ensure_tuple_or_list(arg_name, tuple_or_list): return list(tuple_or_list) -def _app_engine_id(): - """Gets the App Engine application ID if it can be inferred. - - :rtype: str or ``NoneType`` - :returns: App Engine application ID if running in App Engine, - else ``None``. - """ - if app_identity is None: - return None - - return app_identity.get_application_id() - - -def _file_project_id(): - """Gets the project ID from the credentials file if one is available. - - :rtype: str or ``NoneType`` - :returns: Project ID from JSON credentials file if value exists, - else ``None``. - """ - credentials_file_path = os.getenv(CREDENTIALS) - if credentials_file_path: - with open(credentials_file_path, 'rb') as credentials_file: - credentials_json = credentials_file.read() - credentials = json.loads(credentials_json.decode('utf-8')) - return credentials.get('project_id') - - -def _get_nix_config_path(): - """Get the ``gcloud`` CLI config path on *nix systems. - - :rtype: str - :returns: The filename on a *nix system containing the CLI - config file. - """ - return os.path.join(_USER_ROOT, '.config', _GCLOUD_CONFIG_FILE) - - -def _get_windows_config_path(): - """Get the ``gcloud`` CLI config path on Windows systems. - - :rtype: str - :returns: The filename on a Windows system containing the CLI - config file. - """ - appdata_dir = os.getenv('APPDATA', '') - return os.path.join(appdata_dir, _GCLOUD_CONFIG_FILE) - - -def _default_service_project_id(): - """Retrieves the project ID from the gcloud command line tool. - - This assumes the ``.config`` directory is stored - - in ~/.config on *nix systems - - in the %APPDATA% directory on Windows systems - - Additionally, the ${HOME} / "~" directory may not be present on Google - App Engine, so this may be conditionally ignored. - - Files that cannot be opened with configparser are silently ignored; this is - designed so that you can specify a list of potential configuration file - locations. - - :rtype: str or ``NoneType`` - :returns: Project-ID from default configuration file else ``None`` - """ - search_paths = [] - if _USER_ROOT is not None: - search_paths.append(_get_nix_config_path()) - - if os.name == 'nt': - search_paths.append(_get_windows_config_path()) - - config = configparser.RawConfigParser() - config.read(search_paths) - - if config.has_section(_GCLOUD_CONFIG_SECTION): - try: - return config.get(_GCLOUD_CONFIG_SECTION, _GCLOUD_CONFIG_KEY) - except configparser.NoOptionError: - return None - - -def _compute_engine_id(): - """Gets the Compute Engine project ID if it can be inferred. - - Uses 169.254.169.254 for the metadata server to avoid request - latency from DNS lookup. - - See https://cloud.google.com/compute/docs/metadata#metadataserver - for information about this IP address. (This IP is also used for - Amazon EC2 instances, so the metadata flavor is crucial.) - - See https://github.com/google/oauth2client/issues/93 for context about - DNS latency. - - :rtype: str or ``NoneType`` - :returns: Compute Engine project ID if the metadata service is available, - else ``None``. - """ - host = '169.254.169.254' - uri_path = '/computeMetadata/v1/project/project-id' - headers = {'Metadata-Flavor': 'Google'} - connection = http_client.HTTPConnection(host, timeout=0.1) - - try: - connection.request('GET', uri_path, headers=headers) - response = connection.getresponse() - if response.status == 200: - return response.read() - except socket.error: # socket.timeout or socket.error(64, 'Host is down') - pass - finally: - connection.close() - - -def _get_production_project(): - """Gets the production project if it can be inferred.""" - return os.getenv(PROJECT) - - def _determine_default_project(project=None): """Determine default project ID explicitly or implicitly as fall-back. - In implicit case, supports three environments. In order of precedence, the - implicit environments are: - - * GOOGLE_CLOUD_PROJECT environment variable - * GOOGLE_APPLICATION_CREDENTIALS JSON file - * Get default service project from - ``$ gcloud beta auth application-default login`` - * Google App Engine application ID - * Google Compute Engine project ID (from metadata server) + See :func:`google.auth.default` for details on how the default project + is determined. :type project: str :param project: Optional. The project name to use as default. @@ -309,20 +179,7 @@ def _determine_default_project(project=None): :returns: Default project if it can be determined. """ if project is None: - project = _get_production_project() - - if project is None: - project = _file_project_id() - - if project is None: - project = _default_service_project_id() - - if project is None: - project = _app_engine_id() - - if project is None: - project = _compute_engine_id() - + _, project = google.auth.default() return project @@ -597,40 +454,12 @@ def _name_from_project_path(path, project, template): return match.group('name') -class MetadataPlugin(object): - """Callable class to transform metadata for gRPC requests. - - :type credentials: :class:`oauth2client.client.OAuth2Credentials` - :param credentials: The OAuth2 Credentials to use for creating - access tokens. - """ - - def __init__(self, credentials): - self._credentials = credentials - - def __call__(self, unused_context, callback): - """Adds authorization header to request metadata. - - :type unused_context: object - :param unused_context: A gRPC context which is not needed - to modify headers. - - :type callback: callable - :param callback: A callback which will use the headers. - """ - access_token = self._credentials.get_access_token().access_token - headers = [ - ('authorization', 'Bearer ' + access_token), - ] - callback(headers, None) - - def make_secure_channel(credentials, user_agent, host): """Makes a secure channel for an RPC service. Uses / depends on gRPC. - :type credentials: :class:`oauth2client.client.OAuth2Credentials` + :type credentials: :class:`google.auth.credentials.Credentials` :param credentials: The OAuth2 Credentials to use for creating access tokens. @@ -646,7 +475,9 @@ def make_secure_channel(credentials, user_agent, host): # ssl_channel_credentials() loads root certificates from # `grpc/_adapter/credentials/roots.pem`. transport_creds = grpc.ssl_channel_credentials() - custom_metadata_plugin = MetadataPlugin(credentials) + http = httplib2.Http() + custom_metadata_plugin = AuthMetadataPlugin( + credentials, google_auth_httplib2.Request(http=http)) auth_creds = grpc.metadata_call_credentials( custom_metadata_plugin, name='google_creds') channel_creds = grpc.composite_channel_credentials( @@ -664,7 +495,7 @@ def make_secure_stub(credentials, user_agent, stub_class, host): Uses / depends on gRPC. - :type credentials: :class:`oauth2client.client.OAuth2Credentials` + :type credentials: :class:`google.auth.credentials.Credentials` :param credentials: The OAuth2 Credentials to use for creating access tokens. diff --git a/core/google/cloud/_http.py b/core/google/cloud/_http.py index 03e11449c558..c68958e356a6 100644 --- a/core/google/cloud/_http.py +++ b/core/google/cloud/_http.py @@ -19,6 +19,8 @@ import six from six.moves.urllib.parse import urlencode +import google.auth.credentials +import google_auth_httplib2 import httplib2 from google.cloud.exceptions import make_exception @@ -59,9 +61,9 @@ class Connection(object): object will also need to be able to add a bearer token to API requests and handle token refresh on 401 errors. - :type credentials: :class:`oauth2client.client.OAuth2Credentials` or + :type credentials: :class:`google.auth.credentials.Credentials` or :class:`NoneType` - :param credentials: The OAuth2 Credentials to use for this connection. + :param credentials: The credentials to use for this connection. :type http: :class:`httplib2.Http` or class that defines ``request()``. :param http: An optional HTTP object to make requests. @@ -77,14 +79,14 @@ class Connection(object): def __init__(self, credentials=None, http=None): self._http = http - self._credentials = self._create_scoped_credentials( + self._credentials = google.auth.credentials.with_scopes_if_required( credentials, self.SCOPE) @property def credentials(self): """Getter for current credentials. - :rtype: :class:`oauth2client.client.OAuth2Credentials` or + :rtype: :class:`google.auth.credentials.Credentials` or :class:`NoneType` :returns: The credentials object associated with this connection. """ @@ -98,34 +100,13 @@ def http(self): :returns: A Http object used to transport data. """ if self._http is None: - self._http = httplib2.Http() if self._credentials: - self._http = self._credentials.authorize(self._http) + self._http = google_auth_httplib2.AuthorizedHttp( + self._credentials) + else: + self._http = httplib2.Http() return self._http - @staticmethod - def _create_scoped_credentials(credentials, scope): - """Create a scoped set of credentials if it is required. - - :type credentials: :class:`oauth2client.client.OAuth2Credentials` or - :class:`NoneType` - :param credentials: The OAuth2 Credentials to add a scope to. - - :type scope: list of URLs - :param scope: the effective service auth scopes for the connection. - - :rtype: :class:`oauth2client.client.OAuth2Credentials` or - :class:`NoneType` - :returns: A new credentials object that has a scope added (if needed). - """ - if credentials: - try: - if credentials.create_scoped_required(): - credentials = credentials.create_scoped(scope) - except AttributeError: - pass - return credentials - class JSONConnection(Connection): """A connection to a Google JSON-based API. diff --git a/core/google/cloud/client.py b/core/google/cloud/client.py index 521fa11e8e2b..a63c614888ef 100644 --- a/core/google/cloud/client.py +++ b/core/google/cloud/client.py @@ -14,7 +14,7 @@ """Base classes for client used to interact with Google Cloud APIs.""" -from oauth2client.service_account import ServiceAccountCredentials +from google.oauth2 import service_account import six from google.cloud._helpers import _determine_default_project @@ -55,46 +55,11 @@ def from_service_account_json(cls, json_credentials_path, *args, **kwargs): """ if 'credentials' in kwargs: raise TypeError('credentials must not be in keyword arguments') - credentials = ServiceAccountCredentials.from_json_keyfile_name( + credentials = service_account.Credentials.from_service_account_file( json_credentials_path) kwargs['credentials'] = credentials return cls(*args, **kwargs) - @classmethod - def from_service_account_p12(cls, client_email, private_key_path, - *args, **kwargs): - """Factory to retrieve P12 credentials while creating client. - - .. note:: - Unless you have an explicit reason to use a PKCS12 key for your - service account, we recommend using a JSON key. - - :type client_email: str - :param client_email: The e-mail attached to the service account. - - :type private_key_path: str - :param private_key_path: The path to a private key file (this file was - given to you when you created the service - account). This file must be in P12 format. - - :type args: tuple - :param args: Remaining positional arguments to pass to constructor. - - :type kwargs: dict - :param kwargs: Remaining keyword arguments to pass to constructor. - - :rtype: :class:`google.cloud.client.Client` - :returns: The client created with the retrieved P12 credentials. - :raises: :class:`TypeError` if there is a conflict with the kwargs - and the credentials created by the factory. - """ - if 'credentials' in kwargs: - raise TypeError('credentials must not be in keyword arguments') - credentials = ServiceAccountCredentials.from_p12_keyfile( - client_email, private_key_path) - kwargs['credentials'] = credentials - return cls(*args, **kwargs) - class Client(_ClientFactoryMixin): """Client to bundle configuration needed for API requests. @@ -102,7 +67,7 @@ class Client(_ClientFactoryMixin): Assumes that the associated ``_connection_class`` only accepts ``http`` and ``credentials`` in its constructor. - :type credentials: :class:`oauth2client.client.OAuth2Credentials` or + :type credentials: :class:`google.auth.credentials.Credentials` or :class:`NoneType` :param credentials: The OAuth2 Credentials to use for the connection owned by this client. If not passed (and if no ``http`` @@ -165,7 +130,7 @@ class JSONClient(Client, _ClientProjectMixin): passed falls back to the default inferred from the environment. - :type credentials: :class:`oauth2client.client.OAuth2Credentials` or + :type credentials: :class:`google.auth.credentials.Credentials` or :class:`NoneType` :param credentials: The OAuth2 Credentials to use for the connection owned by this client. If not passed (and if no ``http`` diff --git a/core/google/cloud/credentials.py b/core/google/cloud/credentials.py index 8b1bc8d14bf3..52cba9b22fcc 100644 --- a/core/google/cloud/credentials.py +++ b/core/google/cloud/credentials.py @@ -19,7 +19,8 @@ import six from six.moves.urllib.parse import urlencode -from oauth2client import client +import google.auth +import google.auth.credentials from google.cloud._helpers import UTC from google.cloud._helpers import _NOW @@ -29,68 +30,20 @@ def get_credentials(): """Gets credentials implicitly from the current environment. - .. note:: + Uses :func:`google.auth.default()`. - You should not need to use this function directly. Instead, use a - helper method which uses this method under the hood. - - Checks environment in order of precedence: - - * Google App Engine (production and testing) - * Environment variable :envvar:`GOOGLE_APPLICATION_CREDENTIALS` pointing to - a file with stored credentials information. - * Stored "well known" file associated with ``gcloud`` command line tool. - * Google Compute Engine production environment. - - The file referred to in :envvar:`GOOGLE_APPLICATION_CREDENTIALS` is - expected to contain information about credentials that are ready to use. - This means either service account information or user account information - with a ready-to-use refresh token: - - .. code:: json - - { - 'type': 'authorized_user', - 'client_id': '...', - 'client_secret': '...', - 'refresh_token': '...' - } - - or - - .. code:: json - - { - 'type': 'service_account', - 'project_id': '...', - 'private_key_id': '...', - 'private_key': '...', - 'client_email': '...', - 'client_id': '...', - 'auth_uri': '...', - 'token_uri': '...', - 'auth_provider_x509_cert_url': '...', - 'client_x509_cert_url': '...' - } - - The second of these is simply a JSON key downloaded from the Google APIs - console. The first is a close cousin of the "client secrets" JSON file - used by :mod:`oauth2client.clientsecrets` but differs in formatting. - - :rtype: :class:`oauth2client.client.GoogleCredentials`, - :class:`oauth2client.contrib.appengine.AppAssertionCredentials`, - :class:`oauth2client.contrib.gce.AppAssertionCredentials`, - :class:`oauth2client.service_account.ServiceAccountCredentials` + :rtype: :class:`google.auth.credentials.Credentials`, :returns: A new credentials instance corresponding to the implicit environment. """ - return client.GoogleCredentials.get_application_default() + credentials, _ = google.auth.default() + return credentials def _get_signed_query_params(credentials, expiration, string_to_sign): """Gets query parameters for creating a signed URL. - :type credentials: :class:`oauth2client.client.AssertionCredentials` + :type credentials: :class:`google.auth.credentials.Signer` :param credentials: The credentials used to create a private key for signing text. @@ -106,7 +59,7 @@ def _get_signed_query_params(credentials, expiration, string_to_sign): :returns: Query parameters matching the signing credentials with a signed payload. """ - if not hasattr(credentials, 'sign_blob'): + if not isinstance(credentials, google.auth.credentials.Signing): auth_uri = ('http://google-cloud-python.readthedocs.io/en/latest/' 'google-cloud-auth.html#setting-up-a-service-account') raise AttributeError('you need a private key to sign credentials.' @@ -114,9 +67,9 @@ def _get_signed_query_params(credentials, expiration, string_to_sign): 'just contains a token. see %s for more ' 'details.' % (type(credentials), auth_uri)) - _, signature_bytes = credentials.sign_blob(string_to_sign) + signature_bytes = credentials.sign_bytes(string_to_sign) signature = base64.b64encode(signature_bytes) - service_account_name = credentials.service_account_email + service_account_name = credentials.signer_email return { 'GoogleAccessId': service_account_name, 'Expires': str(expiration), @@ -160,10 +113,8 @@ def generate_signed_url(credentials, resource, expiration, .. note:: - Assumes ``credentials`` implements a ``sign_blob()`` method that takes - bytes to sign and returns a pair of the key ID (unused here) and the - signed bytes (this is abstract in the base class - :class:`oauth2client.client.AssertionCredentials`). Also assumes + Assumes ``credentials`` implements the + :class:`google.auth.credentials.Signing` interface. Also assumes ``credentials`` has a ``service_account_email`` property which identifies the credentials. @@ -180,7 +131,7 @@ def generate_signed_url(credentials, resource, expiration, google-cloud-python/issues/922 .. _reference: https://cloud.google.com/storage/docs/reference-headers - :type credentials: :class:`oauth2client.appengine.AppAssertionCredentials` + :type credentials: :class:`google.auth.credentials.Signing` :param credentials: Credentials object with an associated private key to sign text. diff --git a/core/google/cloud/environment_vars.py b/core/google/cloud/environment_vars.py index d27eca8742d0..15e8ee1ce109 100644 --- a/core/google/cloud/environment_vars.py +++ b/core/google/cloud/environment_vars.py @@ -18,9 +18,6 @@ and tests. """ -PROJECT = 'GOOGLE_CLOUD_PROJECT' -"""Environment variable defining default project.""" - GCD_DATASET = 'DATASTORE_DATASET' """Environment variable defining default dataset ID under GCD.""" @@ -33,9 +30,6 @@ BIGTABLE_EMULATOR = 'BIGTABLE_EMULATOR_HOST' """Environment variable defining host for Bigtable emulator.""" -CREDENTIALS = 'GOOGLE_APPLICATION_CREDENTIALS' -"""Environment variable defining location of Google credentials.""" - DISABLE_GRPC = 'GOOGLE_CLOUD_DISABLE_GRPC' """Environment variable acting as flag to disable gRPC. diff --git a/core/google/cloud/streaming/http_wrapper.py b/core/google/cloud/streaming/http_wrapper.py index 3f8d8355645d..e80e105175e7 100644 --- a/core/google/cloud/streaming/http_wrapper.py +++ b/core/google/cloud/streaming/http_wrapper.py @@ -90,7 +90,7 @@ def _httplib2_debug_level(http_request, level, http=None): old_level = httplib2.debuglevel http_levels = {} httplib2.debuglevel = level - if http is not None: + if http is not None and getattr(http, 'connections', None) is not None: for connection_key, connection in http.connections.items(): # httplib2 stores two kinds of values in this dict, connection # classes and instances. Since the connection types are all diff --git a/core/setup.py b/core/setup.py index 5d2f0d1fef7f..8e7085d27904 100644 --- a/core/setup.py +++ b/core/setup.py @@ -52,8 +52,9 @@ REQUIREMENTS = [ 'httplib2 >= 0.9.1', 'googleapis-common-protos >= 1.3.4', - 'oauth2client >= 3.0.0, < 4.0.0dev', 'protobuf >= 3.0.0', + 'google-auth >= 0.4.0, < 2.0.0dev', + 'google-auth-httplib2', 'six', ] diff --git a/core/tox.ini b/core/tox.ini index 182562b6a42f..7c5ef9d29dde 100644 --- a/core/tox.ini +++ b/core/tox.ini @@ -4,6 +4,7 @@ envlist = [testing] deps = + mock pytest covercmd = py.test --quiet \ diff --git a/core/unit_tests/test__helpers.py b/core/unit_tests/test__helpers.py index 9430caf19967..78391e56ef42 100644 --- a/core/unit_tests/test__helpers.py +++ b/core/unit_tests/test__helpers.py @@ -12,9 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os import unittest +import mock + class Test__LocalStack(unittest.TestCase): @@ -126,329 +127,27 @@ def test_invalid_iterable(self): self._call_fut('ARGNAME', invalid_tuple_or_list) -class Test__app_engine_id(unittest.TestCase): - - def _call_fut(self): - from google.cloud._helpers import _app_engine_id - return _app_engine_id() - - def test_no_value(self): - from google.cloud._testing import _Monkey - from google.cloud import _helpers - - with _Monkey(_helpers, app_identity=None): - dataset_id = self._call_fut() - self.assertIsNone(dataset_id) - - def test_value_set(self): - from google.cloud._testing import _Monkey - from google.cloud import _helpers - - APP_ENGINE_ID = object() - APP_IDENTITY = _AppIdentity(APP_ENGINE_ID) - with _Monkey(_helpers, app_identity=APP_IDENTITY): - dataset_id = self._call_fut() - self.assertEqual(dataset_id, APP_ENGINE_ID) - - -class Test__file_project_id(unittest.TestCase): - - def _call_fut(self): - from google.cloud._helpers import _file_project_id - return _file_project_id() - - def test_success(self): - from google.cloud.environment_vars import CREDENTIALS - from google.cloud._testing import _Monkey - from google.cloud._testing import _NamedTemporaryFile - - project_id = 'test-project-id' - payload = '{"%s":"%s"}' % ('project_id', project_id) - with _NamedTemporaryFile() as temp: - with open(temp.name, 'w') as creds_file: - creds_file.write(payload) - - environ = {CREDENTIALS: temp.name} - with _Monkey(os, getenv=environ.get): - result = self._call_fut() - - self.assertEqual(result, project_id) - - def test_no_environment_variable_set(self): - from google.cloud._testing import _Monkey - - environ = {} - with _Monkey(os, getenv=environ.get): - result = self._call_fut() - - self.assertIsNone(result) - - -class Test__get_nix_config_path(unittest.TestCase): - - def _call_fut(self): - from google.cloud._helpers import _get_nix_config_path - return _get_nix_config_path() - - def test_it(self): - from google.cloud import _helpers as MUT - from google.cloud._testing import _Monkey - - user_root = 'a' - config_file = 'b' - with _Monkey(MUT, _USER_ROOT=user_root, - _GCLOUD_CONFIG_FILE=config_file): - result = self._call_fut() - - expected = os.path.join(user_root, '.config', config_file) - self.assertEqual(result, expected) - - -class Test__get_windows_config_path(unittest.TestCase): - - def _call_fut(self): - from google.cloud._helpers import _get_windows_config_path - return _get_windows_config_path() - - def test_it(self): - from google.cloud import _helpers as MUT - from google.cloud._testing import _Monkey - - appdata_dir = 'a' - environ = {'APPDATA': appdata_dir} - config_file = 'b' - with _Monkey(os, getenv=environ.get): - with _Monkey(MUT, _GCLOUD_CONFIG_FILE=config_file): - result = self._call_fut() - - expected = os.path.join(appdata_dir, config_file) - self.assertEqual(result, expected) - - -class Test__default_service_project_id(unittest.TestCase): - - CONFIG_TEMPLATE = '[%s]\n%s = %s\n' - - def _call_fut(self): - from google.cloud._helpers import _default_service_project_id - return _default_service_project_id() - - def test_nix(self): - from google.cloud import _helpers as MUT - from google.cloud._testing import _Monkey - from google.cloud._testing import _NamedTemporaryFile - - project_id = 'test-project-id' - with _NamedTemporaryFile() as temp: - config_value = self.CONFIG_TEMPLATE % ( - MUT._GCLOUD_CONFIG_SECTION, - MUT._GCLOUD_CONFIG_KEY, project_id) - with open(temp.name, 'w') as config_file: - config_file.write(config_value) - - def mock_get_path(): - return temp.name - - with _Monkey(os, name='not-nt'): - with _Monkey(MUT, _get_nix_config_path=mock_get_path, - _USER_ROOT='not-None'): - result = self._call_fut() - - self.assertEqual(result, project_id) - - def test_nix_missing_prject_key(self): - from google.cloud import _helpers as MUT - from google.cloud._testing import _Monkey - from google.cloud._testing import _NamedTemporaryFile - - with _NamedTemporaryFile() as temp: - config_value = '[%s]' % (MUT._GCLOUD_CONFIG_SECTION,) - with open(temp.name, 'w') as config_file: - config_file.write(config_value) - - def mock_get_path(): - return temp.name - - with _Monkey(os, name='not-nt'): - with _Monkey(MUT, _get_nix_config_path=mock_get_path, - _USER_ROOT='not-None'): - result = self._call_fut() - - self.assertEqual(result, None) - - def test_windows(self): - from google.cloud import _helpers as MUT - from google.cloud._testing import _Monkey - from google.cloud._testing import _NamedTemporaryFile - - project_id = 'test-project-id' - with _NamedTemporaryFile() as temp: - config_value = self.CONFIG_TEMPLATE % ( - MUT._GCLOUD_CONFIG_SECTION, - MUT._GCLOUD_CONFIG_KEY, project_id) - with open(temp.name, 'w') as config_file: - config_file.write(config_value) - - def mock_get_path(): - return temp.name - - with _Monkey(os, name='nt'): - with _Monkey(MUT, _get_windows_config_path=mock_get_path, - _USER_ROOT=None): - result = self._call_fut() - - self.assertEqual(result, project_id) - - def test_gae(self): - from google.cloud import _helpers as MUT - from google.cloud._testing import _Monkey - - with _Monkey(os, name='not-nt'): - with _Monkey(MUT, _USER_ROOT=None): - result = self._call_fut() - - self.assertIsNone(result) - - -class Test__compute_engine_id(unittest.TestCase): - - def _call_fut(self): - from google.cloud._helpers import _compute_engine_id - return _compute_engine_id() - - def _monkeyConnection(self, connection): - from six.moves import http_client - from google.cloud._testing import _Monkey - - def _connection_factory(host, timeout): - connection.host = host - connection.timeout = timeout - return connection - - return _Monkey(http_client, HTTPConnection=_connection_factory) - - def test_bad_status(self): - connection = _HTTPConnection(404, None) - with self._monkeyConnection(connection): - dataset_id = self._call_fut() - self.assertIsNone(dataset_id) - - def test_success(self): - COMPUTE_ENGINE_ID = object() - connection = _HTTPConnection(200, COMPUTE_ENGINE_ID) - with self._monkeyConnection(connection): - dataset_id = self._call_fut() - self.assertEqual(dataset_id, COMPUTE_ENGINE_ID) - - def test_socket_raises(self): - connection = _TimeoutHTTPConnection() - with self._monkeyConnection(connection): - dataset_id = self._call_fut() - self.assertIsNone(dataset_id) - - -class Test__get_production_project(unittest.TestCase): - - def _call_fut(self): - from google.cloud._helpers import _get_production_project - return _get_production_project() - - def test_no_value(self): - from google.cloud._testing import _Monkey - - environ = {} - with _Monkey(os, getenv=environ.get): - project = self._call_fut() - self.assertIsNone(project) - - def test_value_set(self): - from google.cloud._testing import _Monkey - from google.cloud._helpers import PROJECT - - MOCK_PROJECT = object() - environ = {PROJECT: MOCK_PROJECT} - with _Monkey(os, getenv=environ.get): - project = self._call_fut() - self.assertEqual(project, MOCK_PROJECT) - - class Test__determine_default_project(unittest.TestCase): def _call_fut(self, project=None): from google.cloud._helpers import _determine_default_project return _determine_default_project(project=project) - def _determine_default_helper(self, prod=None, gae=None, gce=None, - file_id=None, srv_id=None, project=None): - from google.cloud._testing import _Monkey - from google.cloud import _helpers - - _callers = [] - - def prod_mock(): - _callers.append('prod_mock') - return prod - - def file_id_mock(): - _callers.append('file_id_mock') - return file_id - - def srv_id_mock(): - _callers.append('srv_id_mock') - return srv_id - - def gae_mock(): - _callers.append('gae_mock') - return gae - - def gce_mock(): - _callers.append('gce_mock') - return gce - - patched_methods = { - '_get_production_project': prod_mock, - '_file_project_id': file_id_mock, - '_default_service_project_id': srv_id_mock, - '_app_engine_id': gae_mock, - '_compute_engine_id': gce_mock, - } - - with _Monkey(_helpers, **patched_methods): - returned_project = self._call_fut(project) - - return returned_project, _callers + def test_it(self): + with mock.patch('google.auth.default', autospec=True) as default: + default.return_value = ( + mock.sentinel.credentials, mock.sentinel.project) + project = self._call_fut() - def test_no_value(self): - project, callers = self._determine_default_helper() - self.assertIsNone(project) - self.assertEqual(callers, ['prod_mock', 'file_id_mock', 'srv_id_mock', - 'gae_mock', 'gce_mock']) + self.assertEqual(project, mock.sentinel.project) + default.assert_called_once_with() def test_explicit(self): - PROJECT = object() - project, callers = self._determine_default_helper(project=PROJECT) - self.assertEqual(project, PROJECT) - self.assertEqual(callers, []) - - def test_prod(self): - PROJECT = object() - project, callers = self._determine_default_helper(prod=PROJECT) - self.assertEqual(project, PROJECT) - self.assertEqual(callers, ['prod_mock']) - - def test_gae(self): - PROJECT = object() - project, callers = self._determine_default_helper(gae=PROJECT) - self.assertEqual(project, PROJECT) - self.assertEqual(callers, ['prod_mock', 'file_id_mock', - 'srv_id_mock', 'gae_mock']) - - def test_gce(self): - PROJECT = object() - project, callers = self._determine_default_helper(gce=PROJECT) - self.assertEqual(project, PROJECT) - self.assertEqual(callers, ['prod_mock', 'file_id_mock', 'srv_id_mock', - 'gae_mock', 'gce_mock']) + with mock.patch('google.auth.default', autospec=True) as default: + project = self._call_fut(mock.sentinel.project) + + self.assertEqual(project, mock.sentinel.project) + self.assertFalse(default.called) class Test__millis(unittest.TestCase): @@ -905,39 +604,6 @@ def test_w_project_passed_as_none(self): self.assertEqual(name, self.THING_NAME) -class TestMetadataPlugin(unittest.TestCase): - - @staticmethod - def _get_target_class(): - from google.cloud._helpers import MetadataPlugin - return MetadataPlugin - - def _make_one(self, *args, **kwargs): - return self._get_target_class()(*args, **kwargs) - - def test_constructor(self): - credentials = object() - plugin = self._make_one(credentials) - self.assertIs(plugin._credentials, credentials) - - def test___call__(self): - access_token_expected = 'FOOBARBAZ' - credentials = _Credentials(access_token=access_token_expected) - callback_args = [] - - def callback(*args): - callback_args.append(args) - - transformer = self._make_one(credentials) - result = transformer(None, callback) - cb_headers = [ - ('authorization', 'Bearer ' + access_token_expected), - ] - self.assertIsNone(result) - self.assertEqual(callback_args, [(cb_headers, None)]) - self.assertEqual(len(credentials._tokens), 1) - - class Test_make_secure_channel(unittest.TestCase): def _call_fut(self, *args, **kwargs): @@ -946,7 +612,6 @@ def _call_fut(self, *args, **kwargs): def test_it(self): from six.moves import http_client - from google.cloud._testing import _Monkey from google.cloud import _helpers as MUT SSL_CREDS = object() @@ -979,25 +644,23 @@ def secure_channel(self, *args, **kwargs): return CHANNEL grpc_mod = _GRPCModule() - metadata_plugin = object() - plugin_args = [] - - def mock_plugin(*args): - plugin_args.append(args) - return metadata_plugin host = 'HOST' credentials = object() user_agent = 'USER_AGENT' - with _Monkey(MUT, grpc=grpc_mod, - MetadataPlugin=mock_plugin): + + grpc_patch = mock.patch.object(MUT, 'grpc', new=grpc_mod) + request_patch = mock.patch('google_auth_httplib2.Request') + plugin_patch = mock.patch.object( + MUT, 'AuthMetadataPlugin', create=True) + with grpc_patch, request_patch as request_mock, plugin_patch as plugin: result = self._call_fut(credentials, user_agent, host) self.assertIs(result, CHANNEL) - self.assertEqual(plugin_args, [(credentials,)]) + plugin.assert_called_once_with(credentials, request_mock.return_value) self.assertEqual(grpc_mod.ssl_channel_credentials_args, ()) self.assertEqual(grpc_mod.metadata_call_credentials_args, - ((metadata_plugin,), {'name': 'google_creds'})) + ((plugin.return_value,), {'name': 'google_creds'})) self.assertEqual( grpc_mod.composite_channel_credentials_args, (SSL_CREDS, METADATA_CREDS)) @@ -1088,71 +751,3 @@ def test_with_port_argument(self): def test_without_port_argument(self): host = 'HOST:1114' self._helper(host, host) - - -class _AppIdentity(object): - - def __init__(self, app_id): - self.app_id = app_id - - def get_application_id(self): - return self.app_id - - -class _HTTPResponse(object): - - def __init__(self, status, data): - self.status = status - self.data = data - - def read(self): - return self.data - - -class _BaseHTTPConnection(object): - - host = timeout = None - - def __init__(self): - self._close_count = 0 - self._called_args = [] - self._called_kwargs = [] - - def request(self, method, uri, **kwargs): - self._called_args.append((method, uri)) - self._called_kwargs.append(kwargs) - - def close(self): - self._close_count += 1 - - -class _HTTPConnection(_BaseHTTPConnection): - - def __init__(self, status, project): - super(_HTTPConnection, self).__init__() - self.status = status - self.project = project - - def getresponse(self): - return _HTTPResponse(self.status, self.project) - - -class _TimeoutHTTPConnection(_BaseHTTPConnection): - - def getresponse(self): - import socket - raise socket.timeout('timed out') - - -class _Credentials(object): - - def __init__(self, access_token=None): - self._access_token = access_token - self._tokens = [] - - def get_access_token(self): - from oauth2client.client import AccessTokenInfo - token = AccessTokenInfo(access_token=self._access_token, - expires_in=None) - self._tokens.append(token) - return token diff --git a/core/unit_tests/test__http.py b/core/unit_tests/test__http.py index 72d79a707aac..b27f0240d82a 100644 --- a/core/unit_tests/test__http.py +++ b/core/unit_tests/test__http.py @@ -14,6 +14,8 @@ import unittest +import mock + class TestConnection(unittest.TestCase): @@ -31,11 +33,14 @@ def test_ctor_defaults(self): self.assertIsNone(conn.credentials) def test_ctor_explicit(self): - credentials = _Credentials() - self.assertEqual(credentials._create_scoped_calls, 0) + import google.auth.credentials + + credentials = mock.Mock(spec=google.auth.credentials.Scoped) + conn = self._make_one(credentials) - self.assertEqual(credentials._create_scoped_calls, 1) - self.assertIs(conn.credentials, credentials) + + credentials.with_scopes.assert_called_once_with(conn.SCOPE) + self.assertIs(conn.credentials, credentials.with_scopes.return_value) self.assertIsNone(conn._http) def test_ctor_explicit_http(self): @@ -61,13 +66,15 @@ def test_http_wo_creds(self): self.assertIsInstance(conn.http, httplib2.Http) def test_http_w_creds(self): - import httplib2 + import google.auth.credentials + import google_auth_httplib2 + + credentials = mock.Mock(spec=google.auth.credentials.Credentials) - authorized = object() - credentials = _Credentials(authorized) conn = self._make_one(credentials) - self.assertIs(conn.http, authorized) - self.assertIsInstance(credentials._called_with, httplib2.Http) + + self.assertIsInstance(conn.http, google_auth_httplib2.AuthorizedHttp) + self.assertIs(conn.http.credentials, credentials) def test_user_agent_format(self): from pkg_resources import get_distribution @@ -76,37 +83,6 @@ def test_user_agent_format(self): conn = self._make_one() self.assertEqual(conn.USER_AGENT, expected_ua) - def test__create_scoped_credentials_with_scoped_credentials(self): - klass = self._get_target_class() - scoped_creds = object() - scope = 'google-specific-scope' - credentials = _Credentials(scoped=scoped_creds) - - result = klass._create_scoped_credentials(credentials, scope) - self.assertIs(result, scoped_creds) - self.assertEqual(credentials._create_scoped_calls, 1) - self.assertEqual(credentials._scopes, [scope]) - - def test__create_scoped_credentials_without_scope_required(self): - klass = self._get_target_class() - credentials = _Credentials() - - result = klass._create_scoped_credentials(credentials, None) - self.assertIs(result, credentials) - self.assertEqual(credentials._create_scoped_calls, 1) - self.assertEqual(credentials._scopes, []) - - def test__create_scoped_credentials_non_scoped_credentials(self): - klass = self._get_target_class() - credentials = object() - result = klass._create_scoped_credentials(credentials, None) - self.assertIs(result, credentials) - - def test__create_scoped_credentials_no_credentials(self): - klass = self._get_target_class() - result = klass._create_scoped_credentials(None, None) - self.assertIsNone(result) - class TestJSONConnection(unittest.TestCase): @@ -137,9 +113,8 @@ def test_ctor_defaults(self): self.assertIsNone(conn.credentials) def test_ctor_explicit(self): - credentials = _Credentials() - conn = self._make_one(credentials) - self.assertIs(conn.credentials, credentials) + conn = self._make_one(mock.sentinel.credentials) + self.assertIs(conn.credentials, mock.sentinel.credentials) def test_http_w_existing(self): conn = self._make_one() @@ -152,13 +127,15 @@ def test_http_wo_creds(self): self.assertIsInstance(conn.http, httplib2.Http) def test_http_w_creds(self): - import httplib2 + import google.auth.credentials + import google_auth_httplib2 + + credentials = mock.Mock(spec=google.auth.credentials.Credentials) - authorized = object() - credentials = _Credentials(authorized) conn = self._make_one(credentials) - self.assertIs(conn.http, authorized) - self.assertIsInstance(credentials._called_with, httplib2.Http) + + self.assertIsInstance(conn.http, google_auth_httplib2.AuthorizedHttp) + self.assertIs(conn.http.credentials, credentials) def test_build_api_url_no_extra_query_params(self): conn = self._makeMockOne() @@ -437,25 +414,3 @@ def __init__(self, headers, content): def request(self, **kw): self._called_with = kw return self._response, self._content - - -class _Credentials(object): - - def __init__(self, authorized=None, scoped=None): - self._authorized = authorized - self._scoped = scoped - self._scoped_required = scoped is not None - self._create_scoped_calls = 0 - self._scopes = [] - - def authorize(self, http): - self._called_with = http - return self._authorized - - def create_scoped_required(self): - self._create_scoped_calls += 1 - return self._scoped_required - - def create_scoped(self, scope): - self._scopes.append(scope) - return self._scoped diff --git a/core/unit_tests/test_client.py b/core/unit_tests/test_client.py index e7fe5c03be12..975dcc710b27 100644 --- a/core/unit_tests/test_client.py +++ b/core/unit_tests/test_client.py @@ -14,6 +14,8 @@ import unittest +import mock + class Test_ClientFactoryMixin(unittest.TestCase): @@ -74,45 +76,26 @@ def test_ctor_explicit(self): self.assertIs(client_obj._connection.http, HTTP) def test_from_service_account_json(self): - from google.cloud._testing import _Monkey - from google.cloud import client - KLASS = self._get_target_class() - MOCK_FILENAME = 'foo.path' - mock_creds = _MockServiceAccountCredentials() - with _Monkey(client, ServiceAccountCredentials=mock_creds): - client_obj = KLASS.from_service_account_json(MOCK_FILENAME) - self.assertIs(client_obj._connection.credentials, mock_creds._result) - self.assertEqual(mock_creds.json_called, [MOCK_FILENAME]) + constructor_patch = mock.patch( + 'google.oauth2.service_account.Credentials.' + 'from_service_account_file') - def test_from_service_account_json_fail(self): - KLASS = self._get_target_class() - CREDENTIALS = object() - self.assertRaises(TypeError, KLASS.from_service_account_json, None, - credentials=CREDENTIALS) + with constructor_patch as constructor: + client_obj = KLASS.from_service_account_json( + mock.sentinel.filename) - def test_from_service_account_p12(self): - from google.cloud._testing import _Monkey - from google.cloud import client + self.assertIs( + client_obj._connection.credentials, constructor.return_value) + constructor.assert_called_once_with(mock.sentinel.filename) + def test_from_service_account_json_bad_args(self): KLASS = self._get_target_class() - CLIENT_EMAIL = 'phred@example.com' - MOCK_FILENAME = 'foo.path' - mock_creds = _MockServiceAccountCredentials() - with _Monkey(client, ServiceAccountCredentials=mock_creds): - client_obj = KLASS.from_service_account_p12(CLIENT_EMAIL, - MOCK_FILENAME) - - self.assertIs(client_obj._connection.credentials, mock_creds._result) - self.assertEqual(mock_creds.p12_called, - [(CLIENT_EMAIL, MOCK_FILENAME)]) - - def test_from_service_account_p12_fail(self): - KLASS = self._get_target_class() - CREDENTIALS = object() - self.assertRaises(TypeError, KLASS.from_service_account_p12, None, - None, credentials=CREDENTIALS) + + with self.assertRaises(TypeError): + KLASS.from_service_account_json( + mock.sentinel.filename, credentials=mock.sentinel.credentials) class TestJSONClient(unittest.TestCase): @@ -214,19 +197,3 @@ class _MockConnection(object): def __init__(self, credentials=None, http=None): self.credentials = credentials self.http = http - - -class _MockServiceAccountCredentials(object): - - def __init__(self): - self.p12_called = [] - self.json_called = [] - self._result = object() - - def from_p12_keyfile(self, email, path): - self.p12_called.append((email, path)) - return self._result - - def from_json_keyfile_name(self, path): - self.json_called.append(path) - return self._result diff --git a/core/unit_tests/test_credentials.py b/core/unit_tests/test_credentials.py index ef583b35d98a..6489dd19c4dd 100644 --- a/core/unit_tests/test_credentials.py +++ b/core/unit_tests/test_credentials.py @@ -14,6 +14,8 @@ import unittest +import mock + class Test_get_credentials(unittest.TestCase): @@ -22,15 +24,13 @@ def _call_fut(self): return credentials.get_credentials() def test_it(self): - from google.cloud._testing import _Monkey - from google.cloud import credentials as MUT - - client = _Client() - with _Monkey(MUT, client=client): + with mock.patch('google.auth.default', autospec=True) as default: + default.return_value = ( + mock.sentinel.credentials, mock.sentinel.project) found = self._call_fut() - self.assertIsInstance(found, _Credentials) - self.assertIs(found, client._signed) - self.assertTrue(client._get_app_default_called) + + self.assertIs(found, mock.sentinel.credentials) + default.assert_called_once_with() class Test_generate_signed_url(unittest.TestCase): @@ -44,18 +44,20 @@ def _generate_helper(self, response_type=None, response_disposition=None, import base64 from six.moves.urllib.parse import parse_qs from six.moves.urllib.parse import urlsplit + import google.auth.credentials from google.cloud._testing import _Monkey from google.cloud import credentials as MUT ENDPOINT = 'http://api.example.com' RESOURCE = '/name/path' SIGNED = base64.b64encode(b'DEADBEEF') - CREDENTIALS = _Credentials() + CREDENTIALS = mock.Mock(spec=google.auth.credentials.Signing) + CREDENTIALS.signer_email = 'service@example.com' def _get_signed_query_params(*args): credentials, expiration = args[:2] return { - 'GoogleAccessId': credentials.service_account_email, + 'GoogleAccessId': credentials.signer_email, 'Expires': str(expiration), 'Signature': SIGNED, } @@ -76,7 +78,7 @@ def _get_signed_query_params(*args): self.assertEqual(params.pop('Signature'), [SIGNED.decode('ascii')]) self.assertEqual(params.pop('Expires'), ['1000']) self.assertEqual(params.pop('GoogleAccessId'), - [CREDENTIALS.service_account_email]) + [CREDENTIALS.signer_email]) if response_type is not None: self.assertEqual(params.pop('response-content-type'), [response_type]) @@ -104,10 +106,11 @@ def test_w_custom_fields(self): class Test_generate_signed_url_exception(unittest.TestCase): def test_with_google_credentials(self): import time + import google.auth.credentials from google.cloud.credentials import generate_signed_url RESOURCE = '/name/path' - credentials = _GoogleCredentials() + credentials = mock.Mock(spec=google.auth.credentials.Credentials) expiration = int(time.time() + 5) self.assertRaises(AttributeError, generate_signed_url, credentials, resource=RESOURCE, expiration=expiration) @@ -122,11 +125,13 @@ def _call_fut(self, credentials, expiration, string_to_sign): def test_it(self): import base64 + import google.auth.credentials SIG_BYTES = b'DEADBEEF' - ACCOUNT_NAME = object() - CREDENTIALS = _Credentials(sign_result=SIG_BYTES, - service_account_email=ACCOUNT_NAME) + ACCOUNT_NAME = mock.sentinel.service_account_email + CREDENTIALS = mock.Mock(spec=google.auth.credentials.Signing) + CREDENTIALS.signer_email = ACCOUNT_NAME + CREDENTIALS.sign_bytes.return_value = SIG_BYTES EXPIRATION = 100 STRING_TO_SIGN = 'dummy_signature' result = self._call_fut(CREDENTIALS, EXPIRATION, @@ -137,7 +142,7 @@ def test_it(self): 'Expires': str(EXPIRATION), 'Signature': base64.b64encode(b'DEADBEEF'), }) - self.assertEqual(CREDENTIALS._signed, [STRING_TO_SIGN]) + CREDENTIALS.sign_bytes.assert_called_once_with(STRING_TO_SIGN) class Test__get_expiration_seconds(unittest.TestCase): @@ -221,36 +226,3 @@ def test_w_timedelta_days(self): result = self._call_fut(expiration_as_delta) self.assertEqual(result, utc_seconds + 86400) - - -class _Credentials(object): - - def __init__(self, service_account_email='testing@example.com', - sign_result=''): - self.service_account_email = service_account_email - self._sign_result = sign_result - self._signed = [] - - def sign_blob(self, bytes_to_sign): - self._signed.append(bytes_to_sign) - return None, self._sign_result - - -class _GoogleCredentials(object): - - def __init__(self, service_account_email='testing@example.com'): - self.service_account_email = service_account_email - - -class _Client(object): - - def __init__(self): - self._signed = _Credentials() - - class GoogleCredentials(object): - @staticmethod - def get_application_default(): - self._get_app_default_called = True - return self._signed - - self.GoogleCredentials = GoogleCredentials diff --git a/datastore/unit_tests/test__http.py b/datastore/unit_tests/test__http.py index 2b0e826143ff..35781cdf3a40 100644 --- a/datastore/unit_tests/test__http.py +++ b/datastore/unit_tests/test__http.py @@ -455,9 +455,7 @@ def mock_api(connection, secure): def test_ctor_explicit(self): class Creds(object): - - def create_scoped_required(self): - return False + pass creds = Creds() conn = self._make_one(creds) @@ -475,23 +473,12 @@ def test_http_wo_creds(self): self.assertIsInstance(conn.http, httplib2.Http) def test_http_w_creds(self): - import httplib2 - - authorized = object() - class Creds(object): - - def authorize(self, http): - self._called_with = http - return authorized - - def create_scoped_required(self): - return False + pass creds = Creds() conn = self._make_one(creds) - self.assertIs(conn.http, authorized) - self.assertIsInstance(creds._called_with, httplib2.Http) + self.assertIs(conn.http.credentials, creds) def test_build_api_url_w_default_base_version(self): PROJECT = 'PROJECT' diff --git a/dns/unit_tests/test_client.py b/dns/unit_tests/test_client.py index 40eecc512921..eeca097c63b9 100644 --- a/dns/unit_tests/test_client.py +++ b/dns/unit_tests/test_client.py @@ -30,7 +30,7 @@ def _make_one(self, *args, **kw): def test_ctor(self): from google.cloud.dns.connection import Connection - creds = _Credentials() + creds = object() http = object() client = self._make_one(project=self.PROJECT, credentials=creds, http=http) @@ -58,7 +58,7 @@ def test_quotas_defaults(self): } CONVERTED = {key: int(value) for key, value in DATA['quota'].items()} - creds = _Credentials() + creds = object() client = self._make_one(self.PROJECT, creds) conn = client._connection = _Connection(DATA) @@ -93,7 +93,7 @@ def test_quotas_w_kind_key(self): for key, value in DATA['quota'].items()} WITH_KIND = {'quota': DATA['quota'].copy()} WITH_KIND['quota']['kind'] = 'dns#quota' - creds = _Credentials() + creds = object() client = self._make_one(self.PROJECT, creds) conn = client._connection = _Connection(WITH_KIND) @@ -130,7 +130,7 @@ def test_list_zones_defaults(self): 'dnsName': DNS_2}, ] } - creds = _Credentials() + creds = object() client = self._make_one(self.PROJECT, creds) conn = client._connection = _Connection(DATA) @@ -175,7 +175,7 @@ def test_list_zones_explicit(self): 'dnsName': DNS_2}, ] } - creds = _Credentials() + creds = object() client = self._make_one(self.PROJECT, creds) conn = client._connection = _Connection(DATA) @@ -203,7 +203,7 @@ def test_zone_explicit(self): from google.cloud.dns.zone import ManagedZone DESCRIPTION = 'DESCRIPTION' DNS_NAME = 'test.example.com' - creds = _Credentials() + creds = object() client = self._make_one(self.PROJECT, creds) zone = client.zone(self.ZONE_NAME, DNS_NAME, DESCRIPTION) self.assertIsInstance(zone, ManagedZone) @@ -215,7 +215,7 @@ def test_zone_explicit(self): def test_zone_w_dns_name_wo_description(self): from google.cloud.dns.zone import ManagedZone DNS_NAME = 'test.example.com' - creds = _Credentials() + creds = object() client = self._make_one(self.PROJECT, creds) zone = client.zone(self.ZONE_NAME, DNS_NAME) self.assertIsInstance(zone, ManagedZone) @@ -226,7 +226,7 @@ def test_zone_w_dns_name_wo_description(self): def test_zone_wo_dns_name(self): from google.cloud.dns.zone import ManagedZone - creds = _Credentials() + creds = object() client = self._make_one(self.PROJECT, creds) zone = client.zone(self.ZONE_NAME) self.assertIsInstance(zone, ManagedZone) @@ -236,19 +236,6 @@ def test_zone_wo_dns_name(self): self.assertIs(zone._client, client) -class _Credentials(object): - - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self - - class _Connection(object): def __init__(self, *responses): diff --git a/docs/conf.py b/docs/conf.py index 244cced6cc98..8f56935ff640 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -289,4 +289,5 @@ 'oauth2client': ('http://oauth2client.readthedocs.io/en/latest', None), 'pandas': ('http://pandas.pydata.org/pandas-docs/stable/', None), 'python': ('https://docs.python.org/2', None), + 'google-auth': ('https://google-auth.readthedocs.io/en/stable', None), } diff --git a/error_reporting/unit_tests/test_client.py b/error_reporting/unit_tests/test_client.py index a94919ecaacc..ca042b511ddf 100644 --- a/error_reporting/unit_tests/test_client.py +++ b/error_reporting/unit_tests/test_client.py @@ -38,14 +38,14 @@ def _makeHTTP(self, *args, **kw): VERSION = 'myversion' def test_ctor_default(self): - CREDENTIALS = _Credentials() + CREDENTIALS = object() target = self._make_one(project=self.PROJECT, credentials=CREDENTIALS) self.assertEquals(target.service, target.DEFAULT_SERVICE) self.assertEquals(target.version, None) def test_ctor_params(self): - CREDENTIALS = _Credentials() + CREDENTIALS = object() target = self._make_one(project=self.PROJECT, credentials=CREDENTIALS, service=self.SERVICE, @@ -54,7 +54,7 @@ def test_ctor_params(self): self.assertEquals(target.version, self.VERSION) def test_report_exception(self): - CREDENTIALS = _Credentials() + CREDENTIALS = object() target = self._make_one(project=self.PROJECT, credentials=CREDENTIALS) @@ -74,7 +74,7 @@ def test_report_exception(self): self.assertIn('test_client.py', payload['message']) def test_report_exception_with_service_version_in_constructor(self): - CREDENTIALS = _Credentials() + CREDENTIALS = object() SERVICE = "notdefault" VERSION = "notdefaultversion" target = self._make_one(project=self.PROJECT, @@ -109,7 +109,7 @@ def test_report_exception_with_service_version_in_constructor(self): self.assertEquals(payload['context']['user'], USER) def test_report(self): - CREDENTIALS = _Credentials() + CREDENTIALS = object() target = self._make_one(project=self.PROJECT, credentials=CREDENTIALS) @@ -128,19 +128,6 @@ def test_report(self): self.assertLess(report_location['lineNumber'], 150) -class _Credentials(object): - - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self - - class _Logger(object): def log_struct(self, payload, # pylint: disable=unused-argument diff --git a/language/unit_tests/test_client.py b/language/unit_tests/test_client.py index 165f149e5909..7eb04bcf1b8e 100644 --- a/language/unit_tests/test_client.py +++ b/language/unit_tests/test_client.py @@ -17,10 +17,9 @@ def make_mock_credentials(): import mock - from oauth2client.client import GoogleCredentials + from google.auth import credentials - credentials = mock.Mock(spec=GoogleCredentials) - credentials.create_scoped_required.return_value = False + credentials = mock.Mock(spec=credentials.Credentials) return credentials diff --git a/logging/google/cloud/logging/handlers/transports/background_thread.py b/logging/google/cloud/logging/handlers/transports/background_thread.py index aa50e0d3ffc1..c090474a540b 100644 --- a/logging/google/cloud/logging/handlers/transports/background_thread.py +++ b/logging/google/cloud/logging/handlers/transports/background_thread.py @@ -151,7 +151,6 @@ class BackgroundThreadTransport(Transport): def __init__(self, client, name): http = copy.deepcopy(client._connection.http) - http = client._connection.credentials.authorize(http) self.client = client.__class__(client.project, client._connection.credentials, http) logger = self.client.logger(name) diff --git a/logging/unit_tests/handlers/transports/test_background_thread.py b/logging/unit_tests/handlers/transports/test_background_thread.py index eb9204b4e2ae..5ca76a2f68c3 100644 --- a/logging/unit_tests/handlers/transports/test_background_thread.py +++ b/logging/unit_tests/handlers/transports/test_background_thread.py @@ -157,17 +157,11 @@ def commit(self): del self.entries[:] -class _Credentials(object): - - def authorize(self, _): - pass - - class _Connection(object): def __init__(self): self.http = None - self.credentials = _Credentials() + self.credentials = object() class _Logger(object): diff --git a/logging/unit_tests/test__http.py b/logging/unit_tests/test__http.py index 1a6e2d548a06..8dccefa1dcb0 100644 --- a/logging/unit_tests/test__http.py +++ b/logging/unit_tests/test__http.py @@ -29,10 +29,9 @@ def _make_one(self, *args, **kw): return self._get_target_class()(*args, **kw) def test_default_url(self): - creds = _Credentials() + creds = object() conn = self._make_one(creds) - klass = self._get_target_class() - self.assertEqual(conn.credentials._scopes, klass.SCOPE) + self.assertEqual(conn.credentials, creds) class Test_LoggingAPI(unittest.TestCase): @@ -759,19 +758,6 @@ def test_metric_delete_hit(self): self.assertEqual(conn._called_with['path'], path) -class _Credentials(object): - - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self - - class _Connection(object): _called_with = None diff --git a/logging/unit_tests/test_client.py b/logging/unit_tests/test_client.py index 6e7fc8f80f56..4e0cf9129c67 100644 --- a/logging/unit_tests/test_client.py +++ b/logging/unit_tests/test_client.py @@ -35,14 +35,14 @@ def _make_one(self, *args, **kw): return self._get_target_class()(*args, **kw) def test_ctor(self): - creds = _Credentials() + creds = object() client = self._make_one(project=self.PROJECT, credentials=creds) self.assertEqual(client.project, self.PROJECT) def test_logging_api_wo_gax(self): from google.cloud.logging._http import _LoggingAPI - client = self._make_one(self.PROJECT, credentials=_Credentials(), + client = self._make_one(self.PROJECT, credentials=object(), use_gax=False) conn = client._connection = object() api = client.logging_api @@ -63,7 +63,7 @@ def make_api(client_obj): clients.append(client_obj) return api_obj - creds = _Credentials() + creds = object() client = self._make_one(project=self.PROJECT, credentials=creds, use_gax=True) @@ -83,7 +83,7 @@ def test_no_gax_ctor(self): import mock from google.cloud.logging._http import _LoggingAPI - creds = _Credentials() + creds = object() patch = mock.patch( 'google.cloud.logging.client._USE_GAX', new=True) @@ -98,7 +98,7 @@ def test_sinks_api_wo_gax(self): from google.cloud.logging._http import _SinksAPI client = self._make_one( - self.PROJECT, credentials=_Credentials(), + self.PROJECT, credentials=object(), use_gax=False) conn = client._connection = object() @@ -120,7 +120,7 @@ def make_api(client_obj): clients.append(client_obj) return api_obj - creds = _Credentials() + creds = object() client = self._make_one(project=self.PROJECT, credentials=creds, use_gax=True) @@ -140,7 +140,7 @@ def test_metrics_api_wo_gax(self): from google.cloud.logging._http import _MetricsAPI client = self._make_one( - self.PROJECT, credentials=_Credentials(), + self.PROJECT, credentials=object(), use_gax=False) conn = client._connection = object() @@ -162,7 +162,7 @@ def make_api(client_obj): clients.append(client_obj) return api_obj - creds = _Credentials() + creds = object() client = self._make_one(project=self.PROJECT, credentials=creds, use_gax=True) @@ -180,7 +180,7 @@ def make_api(client_obj): def test_logger(self): from google.cloud.logging.logger import Logger - creds = _Credentials() + creds = object() client = self._make_one(project=self.PROJECT, credentials=creds) logger = client.logger(self.LOGGER_NAME) self.assertIsInstance(logger, Logger) @@ -204,7 +204,7 @@ def test_list_entries_defaults(self): 'logName': 'projects/%s/logs/%s' % ( self.PROJECT, self.LOGGER_NAME), }] - creds = _Credentials() + creds = object() client = self._make_one(project=self.PROJECT, credentials=creds, use_gax=False) returned = { @@ -269,7 +269,7 @@ def test_list_entries_explicit(self): 'logName': 'projects/%s/logs/%s' % ( self.PROJECT, self.LOGGER_NAME), }] - client = self._make_one(self.PROJECT, credentials=_Credentials(), + client = self._make_one(self.PROJECT, credentials=object(), use_gax=False) returned = {'entries': ENTRIES} client._connection = _Connection(returned) @@ -320,7 +320,7 @@ def test_list_entries_explicit(self): def test_sink_defaults(self): from google.cloud.logging.sink import Sink - creds = _Credentials() + creds = object() client = self._make_one(project=self.PROJECT, credentials=creds) sink = client.sink(self.SINK_NAME) self.assertIsInstance(sink, Sink) @@ -332,7 +332,7 @@ def test_sink_defaults(self): def test_sink_explicit(self): from google.cloud.logging.sink import Sink - creds = _Credentials() + creds = object() client = self._make_one(project=self.PROJECT, credentials=creds) sink = client.sink(self.SINK_NAME, self.FILTER, self.DESTINATION_URI) self.assertIsInstance(sink, Sink) @@ -355,7 +355,7 @@ def test_list_sinks_no_paging(self): 'filter': FILTER, 'destination': self.DESTINATION_URI, }] - client = self._make_one(project=PROJECT, credentials=_Credentials(), + client = self._make_one(project=PROJECT, credentials=object(), use_gax=False) returned = { 'sinks': SINKS, @@ -401,7 +401,7 @@ def test_list_sinks_with_paging(self): 'filter': FILTER, 'destination': self.DESTINATION_URI, }] - client = self._make_one(project=PROJECT, credentials=_Credentials(), + client = self._make_one(project=PROJECT, credentials=object(), use_gax=False) returned = { 'sinks': SINKS, @@ -437,7 +437,7 @@ def test_list_sinks_with_paging(self): def test_metric_defaults(self): from google.cloud.logging.metric import Metric - creds = _Credentials() + creds = object() client_obj = self._make_one(project=self.PROJECT, credentials=creds) metric = client_obj.metric(self.METRIC_NAME) @@ -450,7 +450,7 @@ def test_metric_defaults(self): def test_metric_explicit(self): from google.cloud.logging.metric import Metric - creds = _Credentials() + creds = object() client_obj = self._make_one(project=self.PROJECT, credentials=creds) metric = client_obj.metric(self.METRIC_NAME, self.FILTER, @@ -471,7 +471,7 @@ def test_list_metrics_no_paging(self): 'description': self.DESCRIPTION, }] client = self._make_one( - project=self.PROJECT, credentials=_Credentials(), + project=self.PROJECT, credentials=object(), use_gax=False) returned = { 'metrics': metrics, @@ -513,7 +513,7 @@ def test_list_metrics_with_paging(self): 'description': self.DESCRIPTION, }] client = self._make_one( - project=self.PROJECT, credentials=_Credentials(), + project=self.PROJECT, credentials=object(), use_gax=False) returned = { 'metrics': metrics, @@ -557,7 +557,7 @@ def test_get_default_handler_app_engine(self): from google.cloud.logging.handlers import AppEngineHandler client = self._make_one(project=self.PROJECT, - credentials=_Credentials(), + credentials=object(), use_gax=False) with _Monkey(_MUT, _LOG_PATH_TEMPLATE='{pid}'): @@ -573,7 +573,7 @@ def test_get_default_handler_container_engine(self): from google.cloud.logging.handlers import ContainerEngineHandler client = self._make_one(project=self.PROJECT, - credentials=_Credentials(), + credentials=object(), use_gax=False) with _Monkey(os, environ={_CONTAINER_ENGINE_ENV: 'True'}): @@ -587,7 +587,7 @@ def test_get_default_handler_general(self): from google.cloud.logging.handlers import CloudLoggingHandler http_mock = mock.Mock(spec=httplib2.Http) - credentials = _Credentials() + credentials = object() deepcopy = mock.Mock(return_value=http_mock) with mock.patch('copy.deepcopy', new=deepcopy): @@ -598,7 +598,6 @@ def test_get_default_handler_general(self): deepcopy.assert_called_once_with(client._connection.http) self.assertIsInstance(handler, CloudLoggingHandler) - self.assertTrue(credentials.authorized, http_mock) def test_setup_logging(self): import httplib2 @@ -608,7 +607,7 @@ def test_setup_logging(self): deepcopy = mock.Mock(return_value=http_mock) setup_logging = mock.Mock() - credentials = _Credentials() + credentials = object() with mock.patch('copy.deepcopy', new=deepcopy): with mock.patch('google.cloud.logging.client.setup_logging', @@ -620,23 +619,6 @@ def test_setup_logging(self): deepcopy.assert_called_once_with(client._connection.http) setup_logging.assert_called() - self.assertTrue(credentials.authorized, http_mock) - - -class _Credentials(object): - - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self - - def authorize(self, http): - self.authorized = http class _Connection(object): diff --git a/monitoring/unit_tests/test_client.py b/monitoring/unit_tests/test_client.py index 98a737887825..1d6807e5ca46 100644 --- a/monitoring/unit_tests/test_client.py +++ b/monitoring/unit_tests/test_client.py @@ -85,7 +85,7 @@ def P(timestamp, value): RESPONSE = {'timeSeries': [SERIES1, SERIES2]} - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) connection = client._connection = _Connection(RESPONSE) # A simple query. In practice, it can be very convenient to let the @@ -138,7 +138,7 @@ def test_metric_descriptor_factory(self): VALUE_TYPE = 'DOUBLE' DESCRIPTION = 'This is my metric.' - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) client._connection = _Connection() # For safety's sake. descriptor = client.metric_descriptor(TYPE, metric_kind=METRIC_KIND, @@ -164,7 +164,7 @@ def test_metric_factory(self): 'instance_name': 'my-instance' } - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) client._connection = _Connection() # For safety's sake. metric = client.metric(TYPE, LABELS) self.assertEqual(metric.type, TYPE) @@ -177,7 +177,7 @@ def test_resource_factory(self): 'zone': 'us-central1-f' } - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) client._connection = _Connection() # For safety's sake. resource = client.resource(TYPE, LABELS) self.assertEqual(resource.type, TYPE) @@ -202,7 +202,7 @@ def test_timeseries_factory_gauge(self): TIME1 = datetime.datetime.utcnow() TIME1_STR = _datetime_to_rfc3339(TIME1, ignore_zone=False) - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) client._connection = _Connection() # For safety's sake. metric = client.metric(METRIC_TYPE, METRIC_LABELS) resource = client.resource(RESOURCE_TYPE, RESOURCE_LABELS) @@ -242,7 +242,7 @@ def test_timeseries_factory_cumulative(self): 'zone': 'us-central1-f' } - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) client._connection = _Connection() # For safety's sake. resource = client.resource(RESOURCE_TYPE, RESOURCE_LABELS) @@ -296,7 +296,7 @@ def test_fetch_metric_descriptor(self): # This test is identical to TestMetricDescriptor.test_fetch() # except for the following three lines. - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) connection = client._connection = _Connection(METRIC_DESCRIPTOR) descriptor = client.fetch_metric_descriptor(TYPE) @@ -340,7 +340,7 @@ def test_list_metric_descriptors(self): # This test is identical to TestMetricDescriptor.test_list() # except for the following three lines. - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) connection = client._connection = _Connection(RESPONSE) descriptors = client.list_metric_descriptors() @@ -385,7 +385,7 @@ def test_fetch_resource_descriptor(self): # This test is identical to TestResourceDescriptor.test_fetch() # except for the following three lines. - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) connection = client._connection = _Connection(RESOURCE_DESCRIPTOR) descriptor = client.fetch_resource_descriptor(TYPE) @@ -433,7 +433,7 @@ def test_list_resource_descriptors(self): # This test is identical to TestResourceDescriptor.test_list() # except for the following three lines. - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) connection = client._connection = _Connection(RESPONSE) descriptors = client.list_resource_descriptors() @@ -460,7 +460,7 @@ def test_group(self): FILTER = 'resource.type = "gce_instance"' IS_CLUSTER = False - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) group = client.group(GROUP_ID, display_name=DISPLAY_NAME, parent_id=PARENT_ID, filter_string=FILTER, is_cluster=IS_CLUSTER) @@ -472,7 +472,7 @@ def test_group(self): self.assertEqual(group.is_cluster, IS_CLUSTER) def test_group_defaults(self): - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) group = client.group() self.assertIsNone(group.id) @@ -499,7 +499,7 @@ def test_fetch_group(self): 'isCluster': IS_CLUSTER } - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) connection = client._connection = _Connection(GROUP) group = client.fetch_group(GROUP_ID) @@ -532,7 +532,7 @@ def test_list_groups(self): RESPONSE = { 'group': [GROUP], } - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) connection = client._connection = _Connection(RESPONSE) groups = client.list_groups() @@ -552,7 +552,7 @@ def test_list_groups(self): def test_write_time_series(self): PATH = '/projects/{project}/timeSeries/'.format(project=PROJECT) - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) RESOURCE_TYPE = 'gce_instance' RESOURCE_LABELS = { @@ -594,7 +594,7 @@ def test_write_time_series(self): def test_write_point(self): import datetime PATH = '/projects/{project}/timeSeries/'.format(project=PROJECT) - client = self._make_one(project=PROJECT, credentials=_Credentials()) + client = self._make_one(project=PROJECT, credentials=object()) RESOURCE_TYPE = 'gce_instance' RESOURCE_LABELS = { @@ -623,18 +623,6 @@ def test_write_point(self): self.assertEqual(request, expected_request) -class _Credentials(object): - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self - - class _Connection(object): def __init__(self, *responses): diff --git a/monitoring/unit_tests/test_connection.py b/monitoring/unit_tests/test_connection.py index 383cbad54274..e9d0c4e631ec 100644 --- a/monitoring/unit_tests/test_connection.py +++ b/monitoring/unit_tests/test_connection.py @@ -26,20 +26,6 @@ def _make_one(self, *args, **kwargs): return self._get_target_class()(*args, **kwargs) def test_constructor(self): - credentials = _Credentials() + credentials = object() connection = self._make_one(credentials) - self.assertEqual(connection.credentials._scopes, - self._get_target_class().SCOPE) - - -class _Credentials(object): - - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self + self.assertEqual(connection.credentials, credentials) diff --git a/pubsub/unit_tests/test__gax.py b/pubsub/unit_tests/test__gax.py index decf9a25c068..9f32d29a2f9a 100644 --- a/pubsub/unit_tests/test__gax.py +++ b/pubsub/unit_tests/test__gax.py @@ -430,7 +430,7 @@ def test_list_subscriptions_no_paging(self): push_config=push_cfg_pb) response = _GAXPageIterator([sub_pb]) gax_api = _GAXSubscriberAPI(_list_subscriptions_response=response) - creds = _Credentials() + creds = object() client = Client(project=self.PROJECT, credentials=creds) api = self._make_one(gax_api, client) @@ -476,7 +476,7 @@ def test_list_subscriptions_with_paging(self): response = _GAXPageIterator([sub_pb], page_token=NEW_TOKEN) gax_api = _GAXSubscriberAPI(_list_subscriptions_response=response) client = _Client(self.PROJECT) - creds = _Credentials() + creds = object() client = Client(project=self.PROJECT, credentials=creds) api = self._make_one(gax_api, client) @@ -914,7 +914,7 @@ def make_channel(*args): mock_publisher_api.SERVICE_ADDRESS = host - creds = _Credentials() + creds = object() connection = _Connection(in_emulator=False, credentials=creds) patch = mock.patch.multiple( @@ -986,7 +986,7 @@ def make_channel(*args): mock_subscriber_api.SERVICE_ADDRESS = host - creds = _Credentials() + creds = object() connection = _Connection(in_emulator=False, credentials=creds) patch = mock.patch.multiple( @@ -1216,10 +1216,3 @@ class _Client(object): def __init__(self, project): self.project = project - - -class _Credentials(object): - - @staticmethod - def create_scoped_required(): - return False diff --git a/pubsub/unit_tests/test__http.py b/pubsub/unit_tests/test__http.py index 3a0281a03eb2..be0f69835683 100644 --- a/pubsub/unit_tests/test__http.py +++ b/pubsub/unit_tests/test__http.py @@ -454,7 +454,7 @@ def test_list_subscriptions_no_paging(self): SUB_INFO = {'name': self.SUB_PATH, 'topic': self.TOPIC_PATH} RETURNED = {'subscriptions': [SUB_INFO]} connection = _Connection(RETURNED) - creds = _Credentials() + creds = object() client = Client(project=self.PROJECT, credentials=creds) client._connection = connection api = self._make_one(client) @@ -497,7 +497,7 @@ def test_list_subscriptions_with_paging(self): 'nextPageToken': 'TOKEN2', } connection = _Connection(RETURNED) - creds = _Credentials() + creds = object() client = Client(project=self.PROJECT, credentials=creds) client._connection = connection api = self._make_one(client) @@ -902,10 +902,3 @@ class _Client(object): def __init__(self, connection, project): self._connection = connection self.project = project - - -class _Credentials(object): - - @staticmethod - def create_scoped_required(): - return False diff --git a/pubsub/unit_tests/test_client.py b/pubsub/unit_tests/test_client.py index 5731f1082586..1e549f8f7f4b 100644 --- a/pubsub/unit_tests/test_client.py +++ b/pubsub/unit_tests/test_client.py @@ -33,7 +33,7 @@ def _make_one(self, *args, **kw): def test_publisher_api_wo_gax(self): from google.cloud.pubsub._http import _PublisherAPI - creds = _Credentials() + creds = object() client = self._make_one( project=self.PROJECT, credentials=creds, @@ -52,7 +52,7 @@ def test_no_gax_ctor(self): import mock from google.cloud.pubsub._http import _PublisherAPI - creds = _Credentials() + creds = object() with mock.patch('google.cloud.pubsub.client._USE_GAX', new=True): client = self._make_one(project=self.PROJECT, credentials=creds, @@ -78,7 +78,7 @@ def __init__(self, _wrapped, client): self._wrapped = _wrapped self._client = client - creds = _Credentials() + creds = object() client = self._make_one( project=self.PROJECT, credentials=creds, use_gax=True) @@ -102,7 +102,7 @@ def __init__(self, _wrapped, client): def test_subscriber_api_wo_gax(self): from google.cloud.pubsub._http import _SubscriberAPI - creds = _Credentials() + creds = object() client = self._make_one( project=self.PROJECT, credentials=creds, use_gax=False) @@ -132,7 +132,7 @@ def __init__(self, _wrapped, client): self._wrapped = _wrapped self._client = client - creds = _Credentials() + creds = object() client = self._make_one( project=self.PROJECT, credentials=creds, use_gax=True) @@ -155,7 +155,7 @@ def __init__(self, _wrapped, client): def test_iam_policy_api(self): from google.cloud.pubsub._http import _IAMPolicyAPI - creds = _Credentials() + creds = object() client = self._make_one(project=self.PROJECT, credentials=creds) conn = client._connection = object() api = client.iam_policy_api @@ -168,7 +168,7 @@ def test_iam_policy_api(self): def test_list_topics_no_paging(self): from google.cloud.pubsub.topic import Topic - creds = _Credentials() + creds = object() client = self._make_one(project=self.PROJECT, credentials=creds) client._connection = object() api = _FauxPublisherAPI(items=[Topic(self.TOPIC_NAME, client)]) @@ -191,7 +191,7 @@ def test_list_topics_with_paging(self): TOKEN1 = 'TOKEN1' TOKEN2 = 'TOKEN2' SIZE = 1 - creds = _Credentials() + creds = object() client = self._make_one(project=self.PROJECT, credentials=creds) client._connection = object() api = _FauxPublisherAPI([Topic(self.TOPIC_NAME, client)], TOKEN2) @@ -209,7 +209,7 @@ def test_list_topics_with_paging(self): self.assertEqual(api._listed_topics, (self.PROJECT, 1, TOKEN1)) def test_list_topics_missing_key(self): - creds = _Credentials() + creds = object() client = self._make_one(project=self.PROJECT, credentials=creds) client._connection = object() api = _FauxPublisherAPI() @@ -229,7 +229,7 @@ def test_list_subscriptions_no_paging(self): from google.cloud.pubsub.topic import Topic SUB_INFO = {'name': self.SUB_PATH, 'topic': self.TOPIC_PATH} - creds = _Credentials() + creds = object() client = self._make_one(project=self.PROJECT, credentials=creds, use_gax=False) returned = {'subscriptions': [SUB_INFO]} @@ -267,7 +267,7 @@ def test_list_subscriptions_with_paging(self): from google.cloud.pubsub.topic import Topic SUB_INFO = {'name': self.SUB_PATH, 'topic': self.TOPIC_PATH} - creds = _Credentials() + creds = object() client = self._make_one(project=self.PROJECT, credentials=creds, use_gax=False) @@ -320,7 +320,7 @@ def test_list_subscriptions_with_paging(self): def test_list_subscriptions_w_missing_key(self): PROJECT = 'PROJECT' - creds = _Credentials() + creds = object() client = self._make_one(project=PROJECT, credentials=creds) client._connection = object() @@ -338,7 +338,7 @@ def test_list_subscriptions_w_missing_key(self): def test_topic(self): PROJECT = 'PROJECT' TOPIC_NAME = 'TOPIC_NAME' - creds = _Credentials() + creds = object() client_obj = self._make_one(project=PROJECT, credentials=creds) new_topic = client_obj.topic(TOPIC_NAME) @@ -350,19 +350,6 @@ def test_topic(self): self.assertFalse(new_topic.timestamp_messages) -class _Credentials(object): - - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self - - class _Iterator(object): def __init__(self, items, token): diff --git a/resource_manager/unit_tests/test_client.py b/resource_manager/unit_tests/test_client.py index 1fa4229284fc..72464f085005 100644 --- a/resource_manager/unit_tests/test_client.py +++ b/resource_manager/unit_tests/test_client.py @@ -29,7 +29,7 @@ def test_constructor(self): from google.cloud.resource_manager.connection import Connection http = object() - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials, http=http) self.assertIsInstance(client._connection, Connection) self.assertEqual(client._connection._credentials, credentials) @@ -38,7 +38,7 @@ def test_constructor(self): def test_new_project_factory(self): from google.cloud.resource_manager.project import Project - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials) project_id = 'project_id' name = object() @@ -66,7 +66,7 @@ def test_fetch_project(self): 'lifecycleState': 'ACTIVE', } - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials) # Patch the connection with one we can easily control. client._connection = _Connection(project_resource) @@ -81,7 +81,7 @@ def test_fetch_project(self): def test_list_projects_return_type(self): from google.cloud.iterator import HTTPIterator - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials) # Patch the connection with one we can easily control. client._connection = _Connection({}) @@ -90,7 +90,7 @@ def test_list_projects_return_type(self): self.assertIsInstance(results, HTTPIterator) def test_list_projects_no_paging(self): - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials) PROJECT_ID = 'project-id' @@ -118,7 +118,7 @@ def test_list_projects_no_paging(self): self.assertEqual(project.status, STATUS) def test_list_projects_with_paging(self): - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials) PROJECT_ID1 = 'project-id' @@ -181,7 +181,7 @@ def test_list_projects_with_paging(self): }) def test_list_projects_with_filter(self): - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials) PROJECT_ID = 'project-id' @@ -220,7 +220,7 @@ def test_list_projects_with_filter(self): def test_page_empty_response(self): from google.cloud.iterator import Page - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials) iterator = client.list_projects() page = Page(iterator, (), None) @@ -246,7 +246,7 @@ def test_page_non_empty_response(self): 'lifecycleState': project_lifecycle_state, } response = {'projects': [api_resource]} - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials) def dummy_response(): @@ -268,19 +268,6 @@ def dummy_response(): self.assertEqual(project.status, project_lifecycle_state) -class _Credentials(object): - - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self - - class _Connection(object): def __init__(self, *responses): diff --git a/runtimeconfig/unit_tests/test_client.py b/runtimeconfig/unit_tests/test_client.py index 2f2be64ebe18..caecec3af843 100644 --- a/runtimeconfig/unit_tests/test_client.py +++ b/runtimeconfig/unit_tests/test_client.py @@ -28,7 +28,7 @@ def _make_one(self, *args, **kw): def test_config(self): PROJECT = 'PROJECT' CONFIG_NAME = 'config_name' - creds = _Credentials() + creds = object() client_obj = self._make_one(project=PROJECT, credentials=creds) new_config = client_obj.config(CONFIG_NAME) @@ -38,16 +38,3 @@ def test_config(self): self.assertEqual(new_config.full_name, 'projects/%s/configs/%s' % (PROJECT, CONFIG_NAME)) self.assertFalse(new_config.description) - - -class _Credentials(object): - - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self diff --git a/runtimeconfig/unit_tests/test_connection.py b/runtimeconfig/unit_tests/test_connection.py index 3d5d8277bd16..ca1a87efaa0c 100644 --- a/runtimeconfig/unit_tests/test_connection.py +++ b/runtimeconfig/unit_tests/test_connection.py @@ -26,20 +26,6 @@ def _make_one(self, *args, **kw): return self._get_target_class()(*args, **kw) def test_default_url(self): - creds = _Credentials() + creds = object() conn = self._make_one(creds) - klass = self._get_target_class() - self.assertEqual(conn.credentials._scopes, klass.SCOPE) - - -class _Credentials(object): - - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self + self.assertEqual(conn.credentials, creds) diff --git a/speech/unit_tests/test_client.py b/speech/unit_tests/test_client.py index 59769f259d45..0f33ab0c8d29 100644 --- a/speech/unit_tests/test_client.py +++ b/speech/unit_tests/test_client.py @@ -79,7 +79,7 @@ def _make_one(self, *args, **kw): def test_ctor(self): from google.cloud.speech.connection import Connection - creds = _Credentials() + creds = object() http = object() client = self._make_one(credentials=creds, http=http) self.assertIsInstance(client._connection, Connection) @@ -87,7 +87,7 @@ def test_ctor(self): self.assertTrue(client._connection.http is http) def test_ctor_use_gax_preset(self): - creds = _Credentials() + creds = object() http = object() client = self._make_one(credentials=creds, http=http, use_gax=True) self.assertTrue(client._use_gax) @@ -96,7 +96,7 @@ def test_create_sample_from_client(self): from google.cloud import speech from google.cloud.speech.sample import Sample - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials) sample = client.sample(source_uri=self.AUDIO_SOURCE_URI, @@ -144,7 +144,7 @@ def test_sync_recognize_content_with_optional_params_no_gax(self): 'content': _B64_AUDIO_CONTENT, } } - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials, use_gax=False) client._connection = _Connection(RETURNED) @@ -187,7 +187,7 @@ def test_sync_recognize_source_uri_without_optional_params_no_gax(self): 'uri': self.AUDIO_SOURCE_URI, } } - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials, use_gax=False) client._connection = _Connection(RETURNED) @@ -216,7 +216,7 @@ def test_sync_recognize_with_empty_results_no_gax(self): from google.cloud import speech from unit_tests._fixtures import SYNC_RECOGNIZE_EMPTY_RESPONSE - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials, use_gax=False) client._connection = _Connection(SYNC_RECOGNIZE_EMPTY_RESPONSE) @@ -233,7 +233,7 @@ def test_sync_recognize_with_empty_results_gax(self): from google.cloud import speech from google.cloud.speech import _gax - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials, use_gax=True) client._connection = _Connection() client._connection.credentials = credentials @@ -276,7 +276,7 @@ def test_sync_recognize_with_gax(self): from google.cloud import speech from google.cloud.speech import _gax - creds = _Credentials() + creds = object() client = self._make_one(credentials=creds, use_gax=True) client._connection = _Connection() client._connection.credentials = creds @@ -336,7 +336,7 @@ def speech_api(channel=None): def test_async_supported_encodings(self): from google.cloud import speech - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials) client._connection = _Connection({}) @@ -353,7 +353,7 @@ def test_async_recognize_no_gax(self): RETURNED = ASYNC_RECOGNIZE_RESPONSE - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials, use_gax=False) client._connection = _Connection(RETURNED) @@ -375,7 +375,7 @@ def test_async_recognize_with_gax(self): from google.cloud.speech import _gax from google.cloud.speech.operation import Operation - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials, use_gax=True) client._connection = _Connection() @@ -416,9 +416,8 @@ def speech_api(channel=None): def test_streaming_depends_on_gax(self): from google.cloud import speech - from google.cloud._testing import _Monkey - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials, use_gax=False) client.connection = _Connection() sample = client.sample(content=self.AUDIO_CONTENT, @@ -437,7 +436,7 @@ def test_streaming_closed_stream(self): from google.cloud.speech.encoding import Encoding stream = BytesIO(b'Some audio data...') - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials) client.connection = _Connection() client.connection.credentials = credentials @@ -478,7 +477,7 @@ def test_stream_recognize_interim_results(self): from google.cloud.speech.result import StreamingSpeechResult stream = BytesIO(b'Some audio data...') - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials) client.connection = _Connection() client.connection.credentials = credentials @@ -554,7 +553,7 @@ def test_stream_recognize(self): from google.cloud.speech.encoding import Encoding stream = BytesIO(b'Some audio data...') - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials) client.connection = _Connection() client.connection.credentials = credentials @@ -610,7 +609,7 @@ def test_stream_recognize_no_results(self): from google.cloud.speech.encoding import Encoding stream = BytesIO(b'Some audio data...') - credentials = _Credentials() + credentials = object() client = self._make_one(credentials=credentials) client.connection = _Connection() client.connection.credentials = credentials @@ -646,7 +645,7 @@ def test_speech_api_with_gax(self): from google.cloud.speech import _gax - creds = _Credentials() + creds = object() client = self._make_one(credentials=creds, use_gax=True) client._connection = _Connection() client._connection.credentials = creds @@ -679,14 +678,14 @@ def test_speech_api_without_gax(self): from google.cloud._http import Connection from google.cloud.speech.client import _JSONSpeechAPI - creds = _Credentials() + creds = object() client = self._make_one(credentials=creds, use_gax=False) self.assertIsNone(client._speech_api) self.assertIsInstance(client.speech_api, _JSONSpeechAPI) self.assertIsInstance(client.speech_api._connection, Connection) def test_speech_api_preset(self): - creds = _Credentials() + creds = object() client = self._make_one(credentials=creds) fake_api = object() client._speech_api = fake_api @@ -724,23 +723,6 @@ def streaming_recognize(self, requests): yield response -class _Credentials(object): - - _scopes = ('https://www.googleapis.com/auth/cloud-platform',) - - def __init__(self, authorized=None): - self._authorized = authorized - self._create_scoped_calls = 0 - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self - - class _Connection(object): def __init__(self, *responses): diff --git a/storage/unit_tests/test_batch.py b/storage/unit_tests/test_batch.py index 74d6cf155835..b0abea6dcc85 100644 --- a/storage/unit_tests/test_batch.py +++ b/storage/unit_tests/test_batch.py @@ -89,7 +89,7 @@ def test_ctor(self): def test_current(self): from google.cloud.storage.client import Client project = 'PROJECT' - credentials = _Credentials() + credentials = object() client = Client(project=project, credentials=credentials) batch1 = self._make_one(client) self.assertIsNone(batch1.current()) @@ -378,7 +378,7 @@ def test_as_context_mgr_wo_error(self): expected['content-type'] = 'multipart/mixed; boundary="DEADBEEF="' http = _HTTP((expected, _THREE_PART_MIME_RESPONSE)) project = 'PROJECT' - credentials = _Credentials() + credentials = object() client = Client(project=project, credentials=credentials) client._base_connection._http = http @@ -414,7 +414,7 @@ def test_as_context_mgr_w_error(self): http = _HTTP() connection = _Connection(http=http) project = 'PROJECT' - credentials = _Credentials() + credentials = object() client = Client(project=project, credentials=credentials) client._base_connection = connection @@ -599,16 +599,3 @@ class _Client(object): def __init__(self, connection): self._base_connection = connection - - -class _Credentials(object): - - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self diff --git a/storage/unit_tests/test_client.py b/storage/unit_tests/test_client.py index ad4eaff75567..8a6dcbfde0c6 100644 --- a/storage/unit_tests/test_client.py +++ b/storage/unit_tests/test_client.py @@ -29,7 +29,7 @@ def test_ctor_connection_type(self): from google.cloud.storage._http import Connection PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) self.assertEqual(client.project, PROJECT) @@ -42,7 +42,7 @@ def test__push_batch_and__pop_batch(self): from google.cloud.storage.batch import Batch PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) batch1 = Batch(client) @@ -61,7 +61,7 @@ def test__push_batch_and__pop_batch(self): def test__connection_setter(self): PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) client._base_connection = None # Unset the value from the constructor client._connection = connection = object() @@ -69,13 +69,13 @@ def test__connection_setter(self): def test__connection_setter_when_set(self): PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) self.assertRaises(ValueError, setattr, client, '_connection', None) def test__connection_getter_no_batch(self): PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) self.assertIs(client._connection, client._base_connection) self.assertIsNone(client.current_batch) @@ -83,7 +83,7 @@ def test__connection_getter_no_batch(self): def test__connection_getter_with_batch(self): from google.cloud.storage.batch import Batch PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) batch = Batch(client) client._push_batch(batch) @@ -95,7 +95,7 @@ def test_bucket(self): from google.cloud.storage.bucket import Bucket PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() BUCKET_NAME = 'BUCKET_NAME' client = self._make_one(project=PROJECT, credentials=CREDENTIALS) @@ -108,7 +108,7 @@ def test_batch(self): from google.cloud.storage.batch import Batch PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) batch = client.batch() @@ -119,7 +119,7 @@ def test_get_bucket_miss(self): from google.cloud.exceptions import NotFound PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) NONESUCH = 'nonesuch' @@ -142,7 +142,7 @@ def test_get_bucket_hit(self): from google.cloud.storage.bucket import Bucket PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) BLOB_NAME = 'blob-name' @@ -166,7 +166,7 @@ def test_get_bucket_hit(self): def test_lookup_bucket_miss(self): PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) NONESUCH = 'nonesuch' @@ -190,7 +190,7 @@ def test_lookup_bucket_hit(self): from google.cloud.storage.bucket import Bucket PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) BLOB_NAME = 'blob-name' @@ -216,7 +216,7 @@ def test_create_bucket_conflict(self): from google.cloud.exceptions import Conflict PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) BLOB_NAME = 'blob-name' @@ -239,7 +239,7 @@ def test_create_bucket_success(self): from google.cloud.storage.bucket import Bucket PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) BLOB_NAME = 'blob-name' @@ -265,7 +265,7 @@ def test_list_buckets_empty(self): from six.moves.urllib.parse import urlparse PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) EXPECTED_QUERY = { @@ -297,7 +297,7 @@ def test_list_buckets_non_empty(self): from six.moves.urllib.parse import urlencode from six.moves.urllib.parse import urlparse PROJECT = 'PROJECT' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) BUCKET_NAME = 'bucket-name' @@ -326,7 +326,7 @@ def test_list_buckets_all_arguments(self): from six.moves.urllib.parse import urlparse PROJECT = 'foo-bar' - CREDENTIALS = _Credentials() + CREDENTIALS = object() client = self._make_one(project=PROJECT, credentials=CREDENTIALS) MAX_RESULTS = 10 @@ -374,7 +374,7 @@ def test_page_empty_response(self): from google.cloud.iterator import Page project = 'PROJECT' - credentials = _Credentials() + credentials = object() client = self._make_one(project=project, credentials=credentials) iterator = client.list_buckets() page = Page(iterator, (), None) @@ -386,7 +386,7 @@ def test_page_non_empty_response(self): from google.cloud.storage.bucket import Bucket project = 'PROJECT' - credentials = _Credentials() + credentials = object() client = self._make_one(project=project, credentials=credentials) blob_name = 'blob-name' @@ -406,19 +406,6 @@ def dummy_response(): self.assertEqual(bucket.name, blob_name) -class _Credentials(object): - - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self - - class _Http(object): _called_with = None diff --git a/system_tests/attempt_system_tests.py b/system_tests/attempt_system_tests.py index c6e7297a5fa0..94546dca032e 100644 --- a/system_tests/attempt_system_tests.py +++ b/system_tests/attempt_system_tests.py @@ -50,7 +50,7 @@ import subprocess import sys -from google.cloud.environment_vars import CREDENTIALS +from google.auth.environment_vars import CREDENTIALS from run_system_test import FailedSystemTestModule from run_system_test import run_module_tests diff --git a/system_tests/system_test_utils.py b/system_tests/system_test_utils.py index 393bd4b5df8b..56e8a9203292 100644 --- a/system_tests/system_test_utils.py +++ b/system_tests/system_test_utils.py @@ -17,7 +17,7 @@ import sys import time -from google.cloud.environment_vars import CREDENTIALS as TEST_CREDENTIALS +from google.auth.environment_vars import CREDENTIALS as TEST_CREDENTIALS # From shell environ. May be None. diff --git a/vision/unit_tests/test_client.py b/vision/unit_tests/test_client.py index a7ff1cccd81f..0e279e19537f 100644 --- a/vision/unit_tests/test_client.py +++ b/vision/unit_tests/test_client.py @@ -35,7 +35,7 @@ def _make_one(self, *args, **kw): return self._get_target_class()(*args, **kw) def test_ctor(self): - creds = _Credentials() + creds = object() client = self._make_one(project=PROJECT, credentials=creds) self.assertEqual(client.project, PROJECT) @@ -59,7 +59,7 @@ def test_face_annotation(self): } ] } - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -75,7 +75,7 @@ def test_face_annotation(self): def test_image_with_client(self): from google.cloud.vision.image import Image - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) image = client.image(source_uri=IMAGE_SOURCE) @@ -92,7 +92,7 @@ def test_multiple_detection_from_content(self): logos = copy.deepcopy(LOGO_DETECTION_RESPONSE['responses'][0]) returned['responses'][0]['logoAnnotations'] = logos['logoAnnotations'] - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(returned) @@ -139,7 +139,7 @@ def test_face_detection_from_source(self): from google.cloud.vision.face import Face from unit_tests._fixtures import FACE_DETECTION_RESPONSE RETURNED = FACE_DETECTION_RESPONSE - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -156,7 +156,7 @@ def test_face_detection_from_content(self): from google.cloud.vision.face import Face from unit_tests._fixtures import FACE_DETECTION_RESPONSE RETURNED = FACE_DETECTION_RESPONSE - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -174,7 +174,7 @@ def test_face_detection_from_content_no_results(self): RETURNED = { 'responses': [{}] } - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -193,7 +193,7 @@ def test_label_detection_from_source(self): from unit_tests._fixtures import ( LABEL_DETECTION_RESPONSE as RETURNED) - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -214,7 +214,7 @@ def test_label_detection_no_results(self): RETURNED = { 'responses': [{}] } - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -228,7 +228,7 @@ def test_landmark_detection_from_source(self): from unit_tests._fixtures import ( LANDMARK_DETECTION_RESPONSE as RETURNED) - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -250,7 +250,7 @@ def test_landmark_detection_from_content(self): from unit_tests._fixtures import ( LANDMARK_DETECTION_RESPONSE as RETURNED) - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -267,7 +267,7 @@ def test_landmark_detection_no_results(self): RETURNED = { 'responses': [{}] } - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -280,7 +280,7 @@ def test_logo_detection_from_source(self): from google.cloud.vision.entity import EntityAnnotation from unit_tests._fixtures import LOGO_DETECTION_RESPONSE RETURNED = LOGO_DETECTION_RESPONSE - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -297,7 +297,7 @@ def test_logo_detection_from_content(self): from google.cloud.vision.entity import EntityAnnotation from unit_tests._fixtures import LOGO_DETECTION_RESPONSE RETURNED = LOGO_DETECTION_RESPONSE - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -315,7 +315,7 @@ def test_text_detection_from_source(self): from unit_tests._fixtures import ( TEXT_DETECTION_RESPONSE as RETURNED) - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -337,7 +337,7 @@ def test_safe_search_detection_from_source(self): from unit_tests._fixtures import SAFE_SEARCH_DETECTION_RESPONSE RETURNED = SAFE_SEARCH_DETECTION_RESPONSE - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -356,7 +356,7 @@ def test_safe_search_no_results(self): RETURNED = { 'responses': [{}] } - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -370,7 +370,7 @@ def test_image_properties_detection_from_source(self): from unit_tests._fixtures import IMAGE_PROPERTIES_RESPONSE RETURNED = IMAGE_PROPERTIES_RESPONSE - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -392,7 +392,7 @@ def test_image_properties_no_results(self): RETURNED = { 'responses': [{}] } - credentials = _Credentials() + credentials = object() client = self._make_one(project=PROJECT, credentials=credentials) client._connection = _Connection(RETURNED) @@ -426,19 +426,6 @@ def test_make_vision_request_with_bad_feature(self): self._make_one(IMAGE_CONTENT, 'nonsensefeature') -class _Credentials(object): - - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self - - class _Connection(object): def __init__(self, *responses): diff --git a/vision/unit_tests/test_connection.py b/vision/unit_tests/test_connection.py index 0a7643fc83d2..f00e81f3de90 100644 --- a/vision/unit_tests/test_connection.py +++ b/vision/unit_tests/test_connection.py @@ -26,20 +26,6 @@ def _make_one(self, *args, **kw): return self._get_target_class()(*args, **kw) def test_default_url(self): - creds = _Credentials() + creds = object() conn = self._make_one(creds) - klass = self._get_target_class() - self.assertEqual(conn.credentials._scopes, klass.SCOPE) - - -class _Credentials(object): - - _scopes = None - - @staticmethod - def create_scoped_required(): - return True - - def create_scoped(self, scope): - self._scopes = scope - return self + self.assertEqual(conn.credentials, creds)