Repository: googleapis/google-cloud-python

Issue:
Pubsub: clients emit pending deprecation warnings
(See [Google Group](https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/cloud-pubsub-discuss/A53nuoc3Eb4/LH6gwaXfDgAJ) )

With the Python pubsub package v 0.39.0,  a simple call to pubsub_v1.SubscriberClient() gives  warnings from deep in Google code
```
             
 publisher/client.py:89: PendingDeprecationWarning: The `channel` argument is deprecated; use `transport` instead.
  ...
  subscriber/client.py:83: PendingDeprecationWarning: The `channel` argument is deprecated; use `transport` instead.
  ...

```
This apparently incorrect channel is created inside Google code, e.g.  `google.cloud.pubsub_v1.subscriber.client.Client#__init__`

Although keeping ahead of deprecation can be challenging, Google's _own_ code  should avoid warnings and do whatever Google says is the official way.
 


Discussion:
@theacodes Both the [publisher client](https://github.com/googleapis/google-cloud-python/blob/33eb5b5894427c839bd091d1af39a54186acc410/pubsub/google/cloud/pubsub_v1/publisher/client.py#L73-L85) and the [subscriber client](https://github.com/googleapis/google-cloud-python/blob/33eb5b5894427c839bd091d1af39a54186acc410/pubsub/google/cloud/pubsub_v1/subscriber/client.py#L66-L79) have comments which specify that they are passing a custom client in order to override maximum message size and keepalive options.  Should those fixes still be needed?  I guess we could add synth replacements to the `*_grpc_transport.py` files such that the local `create_channel` method passed along appropriate values.

@lukesneeringer I've asked elsewhere, but have no idea why the GAPIC generator is deprecating passing a channel:  can you explain here?

Resolving patch:
diff --git a/pubsub/google/cloud/pubsub_v1/publisher/client.py b/pubsub/google/cloud/pubsub_v1/publisher/client.py
--- a/pubsub/google/cloud/pubsub_v1/publisher/client.py
+++ b/pubsub/google/cloud/pubsub_v1/publisher/client.py
@@ -27,6 +27,7 @@
 from google.cloud.pubsub_v1 import _gapic
 from google.cloud.pubsub_v1 import types
 from google.cloud.pubsub_v1.gapic import publisher_client
+from google.cloud.pubsub_v1.gapic.transports import publisher_grpc_transport
 from google.cloud.pubsub_v1.publisher._batch import thread
 
 
@@ -73,16 +74,22 @@ def __init__(self, batch_settings=(), **kwargs):
         # Use a custom channel.
         # We need this in order to set appropriate default message size and
         # keepalive options.
-        if "channel" not in kwargs:
-            kwargs["channel"] = grpc_helpers.create_channel(
-                credentials=kwargs.pop("credentials", None),
-                target=self.target,
-                scopes=publisher_client.PublisherClient._DEFAULT_SCOPES,
-                options={
-                    "grpc.max_send_message_length": -1,
-                    "grpc.max_receive_message_length": -1,
-                }.items(),
-            )
+        if "transport" not in kwargs:
+            channel = kwargs.pop("channel", None)
+            if channel is None:
+                channel = grpc_helpers.create_channel(
+                    credentials=kwargs.pop("credentials", None),
+                    target=self.target,
+                    scopes=publisher_client.PublisherClient._DEFAULT_SCOPES,
+                    options={
+                        "grpc.max_send_message_length": -1,
+                        "grpc.max_receive_message_length": -1,
+                    }.items(),
+                )
+            # cannot pass both 'channel' and 'credentials'
+            kwargs.pop("credentials", None)
+            transport = publisher_grpc_transport.PublisherGrpcTransport(channel=channel)
+            kwargs["transport"] = transport
 
         # Add the metrics headers, and instantiate the underlying GAPIC
         # client.
diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/client.py b/pubsub/google/cloud/pubsub_v1/subscriber/client.py
--- a/pubsub/google/cloud/pubsub_v1/subscriber/client.py
+++ b/pubsub/google/cloud/pubsub_v1/subscriber/client.py
@@ -25,6 +25,7 @@
 from google.cloud.pubsub_v1 import _gapic
 from google.cloud.pubsub_v1 import types
 from google.cloud.pubsub_v1.gapic import subscriber_client
+from google.cloud.pubsub_v1.gapic.transports import subscriber_grpc_transport
 from google.cloud.pubsub_v1.subscriber import futures
 from google.cloud.pubsub_v1.subscriber._protocol import streaming_pull_manager
 
@@ -66,17 +67,25 @@ def __init__(self, **kwargs):
         # Use a custom channel.
         # We need this in order to set appropriate default message size and
         # keepalive options.
-        if "channel" not in kwargs:
-            kwargs["channel"] = grpc_helpers.create_channel(
-                credentials=kwargs.pop("credentials", None),
-                target=self.target,
-                scopes=subscriber_client.SubscriberClient._DEFAULT_SCOPES,
-                options={
-                    "grpc.max_send_message_length": -1,
-                    "grpc.max_receive_message_length": -1,
-                    "grpc.keepalive_time_ms": 30000,
-                }.items(),
+        if "transport" not in kwargs:
+            channel = kwargs.pop("channel", None)
+            if channel is None:
+                channel = grpc_helpers.create_channel(
+                    credentials=kwargs.pop("credentials", None),
+                    target=self.target,
+                    scopes=subscriber_client.SubscriberClient._DEFAULT_SCOPES,
+                    options={
+                        "grpc.max_send_message_length": -1,
+                        "grpc.max_receive_message_length": -1,
+                        "grpc.keepalive_time_ms": 30000,
+                    }.items(),
+                )
+            # cannot pass both 'channel' and 'credentials'
+            kwargs.pop("credentials", None)
+            transport = subscriber_grpc_transport.SubscriberGrpcTransport(
+                channel=channel
             )
+            kwargs["transport"] = transport
 
         # Add the metrics headers, and instantiate the underlying GAPIC
         # client.


Test patch:
diff --git a/pubsub/tests/unit/pubsub_v1/publisher/test_publisher_client.py b/pubsub/tests/unit/pubsub_v1/publisher/test_publisher_client.py
--- a/pubsub/tests/unit/pubsub_v1/publisher/test_publisher_client.py
+++ b/pubsub/tests/unit/pubsub_v1/publisher/test_publisher_client.py
@@ -36,6 +36,19 @@ def test_init():
     assert client.batch_settings.max_messages == 1000
 
 
+def test_init_w_custom_transport():
+    transport = object()
+    client = publisher.Client(transport=transport)
+
+    # A plain client should have an `api` (the underlying GAPIC) and a
+    # batch settings object, which should have the defaults.
+    assert isinstance(client.api, publisher_client.PublisherClient)
+    assert client.api.transport is transport
+    assert client.batch_settings.max_bytes == 10 * 1000 * 1000
+    assert client.batch_settings.max_latency == 0.05
+    assert client.batch_settings.max_messages == 1000
+
+
 def test_init_emulator(monkeypatch):
     monkeypatch.setenv("PUBSUB_EMULATOR_HOST", "/foo/bar/")
     # NOTE: When the emulator host is set, a custom channel will be used, so
diff --git a/pubsub/tests/unit/pubsub_v1/subscriber/test_subscriber_client.py b/pubsub/tests/unit/pubsub_v1/subscriber/test_subscriber_client.py
--- a/pubsub/tests/unit/pubsub_v1/subscriber/test_subscriber_client.py
+++ b/pubsub/tests/unit/pubsub_v1/subscriber/test_subscriber_client.py
@@ -16,6 +16,7 @@
 import mock
 
 from google.cloud.pubsub_v1 import subscriber
+from google.cloud.pubsub_v1.gapic import subscriber_client
 from google.cloud.pubsub_v1 import types
 from google.cloud.pubsub_v1.subscriber import futures
 
@@ -23,7 +24,14 @@
 def test_init():
     creds = mock.Mock(spec=credentials.Credentials)
     client = subscriber.Client(credentials=creds)
-    assert client.api is not None
+    assert isinstance(client.api, subscriber_client.SubscriberClient)
+
+
+def test_init_w_custom_transport():
+    transport = object()
+    client = subscriber.Client(transport=transport)
+    assert isinstance(client.api, subscriber_client.SubscriberClient)
+    assert client.api.transport is transport
 
 
 def test_init_emulator(monkeypatch):