From 7ee22e73f8373bafd7d13db64350bd7c296dd9ad Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 8 Nov 2018 14:11:00 -0500 Subject: [PATCH] Override client classmethod factories inherited from GAPIC. The '_gapic.add_methods' decorator doesn't quite get them right, so blacklist them from it and create them locally. Closes #5903. --- .../cloud/pubsub_v1/publisher/client.py | 32 ++++++++++++++++++- .../cloud/pubsub_v1/subscriber/client.py | 31 ++++++++++++++++-- .../publisher/test_publisher_client.py | 10 ++++++ .../subscriber/test_subscriber_client.py | 10 ++++++ 4 files changed, 80 insertions(+), 3 deletions(-) diff --git a/pubsub/google/cloud/pubsub_v1/publisher/client.py b/pubsub/google/cloud/pubsub_v1/publisher/client.py index 910ebc5fbada..670000f7fc69 100644 --- a/pubsub/google/cloud/pubsub_v1/publisher/client.py +++ b/pubsub/google/cloud/pubsub_v1/publisher/client.py @@ -22,6 +22,7 @@ import six from google.api_core import grpc_helpers +from google.oauth2 import service_account from google.cloud.pubsub_v1 import _gapic from google.cloud.pubsub_v1 import types @@ -31,8 +32,15 @@ __version__ = pkg_resources.get_distribution('google-cloud-pubsub').version +_BLACKLISTED_METHODS = ( + 'publish', + 'from_service_account_file', + 'from_service_account_json', +) -@_gapic.add_methods(publisher_client.PublisherClient, blacklist=('publish',)) + +@_gapic.add_methods( + publisher_client.PublisherClient, blacklist=_BLACKLISTED_METHODS) class Client(object): """A publisher client for Google Cloud Pub/Sub. @@ -86,6 +94,28 @@ def __init__(self, batch_settings=(), **kwargs): self._batch_lock = self._batch_class.make_lock() self._batches = {} + @classmethod + def from_service_account_file(cls, filename, batch_settings=(), **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + batch_settings (~google.cloud.pubsub_v1.types.BatchSettings): The + settings for batch publishing. + kwargs: Additional arguments to pass to the constructor. + + Returns: + PublisherClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file( + filename) + kwargs['credentials'] = credentials + return cls(batch_settings, **kwargs) + + from_service_account_json = from_service_account_file + @property def target(self): """Return the target (where the API is). diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/client.py b/pubsub/google/cloud/pubsub_v1/subscriber/client.py index 817ef80a97eb..226b7bf344f8 100644 --- a/pubsub/google/cloud/pubsub_v1/subscriber/client.py +++ b/pubsub/google/cloud/pubsub_v1/subscriber/client.py @@ -20,6 +20,7 @@ import grpc from google.api_core import grpc_helpers +from google.oauth2 import service_account from google.cloud.pubsub_v1 import _gapic from google.cloud.pubsub_v1 import types @@ -30,9 +31,15 @@ __version__ = pkg_resources.get_distribution('google-cloud-pubsub').version +_BLACKLISTED_METHODS = ( + 'publish', + 'from_service_account_file', + 'from_service_account_json', +) -@_gapic.add_methods(subscriber_client.SubscriberClient, - blacklist=('streaming_pull',)) + +@_gapic.add_methods( + subscriber_client.SubscriberClient, blacklist=_BLACKLISTED_METHODS) class Client(object): """A subscriber client for Google Cloud Pub/Sub. @@ -75,6 +82,26 @@ def __init__(self, **kwargs): # client. self._api = subscriber_client.SubscriberClient(**kwargs) + @classmethod + def from_service_account_file(cls, filename, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + kwargs: Additional arguments to pass to the constructor. + + Returns: + PublisherClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file( + filename) + kwargs['credentials'] = credentials + return cls(**kwargs) + + from_service_account_json = from_service_account_file + @property def target(self): """Return the target (where the API is). diff --git a/pubsub/tests/unit/pubsub_v1/publisher/test_publisher_client.py b/pubsub/tests/unit/pubsub_v1/publisher/test_publisher_client.py index 9b15e6d4777d..523dbe855fd1 100644 --- a/pubsub/tests/unit/pubsub_v1/publisher/test_publisher_client.py +++ b/pubsub/tests/unit/pubsub_v1/publisher/test_publisher_client.py @@ -221,6 +221,16 @@ def test_gapic_class_method_on_class(): assert answer == 'projects/foo/topics/bar' +def test_class_method_factory(): + patch = mock.patch( + 'google.oauth2.service_account.Credentials.from_service_account_file') + + with patch: + client = publisher.Client.from_service_account_file('filename.json') + + assert isinstance(client, publisher.Client) + + def test_gapic_class_method_on_instance(): creds = mock.Mock(spec=credentials.Credentials) client = publisher.Client(credentials=creds) diff --git a/pubsub/tests/unit/pubsub_v1/subscriber/test_subscriber_client.py b/pubsub/tests/unit/pubsub_v1/subscriber/test_subscriber_client.py index 35487c1a6a8d..86297d31cd96 100644 --- a/pubsub/tests/unit/pubsub_v1/subscriber/test_subscriber_client.py +++ b/pubsub/tests/unit/pubsub_v1/subscriber/test_subscriber_client.py @@ -40,6 +40,16 @@ def test_init_emulator(monkeypatch): assert channel.target().decode('utf8') == '/baz/bacon/' +def test_class_method_factory(): + patch = mock.patch( + 'google.oauth2.service_account.Credentials.from_service_account_file') + + with patch: + client = subscriber.Client.from_service_account_file('filename.json') + + assert isinstance(client, subscriber.Client) + + @mock.patch( 'google.cloud.pubsub_v1.subscriber._protocol.streaming_pull_manager.' 'StreamingPullManager.open', autospec=True)