Repository: googleapis/google-cloud-python

Issue:
PubSub: Got unbound method error when calling the class method from_service_account_json
I am using the service account for authentication. By following the example in [here](https://googlecloudplatform.github.io/google-cloud-python/latest/core/auth.html#service-accounts)
, I create the following code:

```
from google.cloud import pubsub
logging.debug(dir(pubsub.PublisherClient))
pubsub_publisher_client = pubsub.PublisherClient.from_service_account_json(key_path)
```

The output:

```
DEBUG:root:['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'batch', 'create_topic', 'delete_topic', 'from_service_account_file', 'from_service_account_json', 'get_iam_policy', 'get_topic', 'list_topic_subscriptions', 'list_topics', 'project_path', 'publish', 'set_iam_policy', 'target', 'test_iam_permissions', 'topic_path', 'update_topic']
Traceback (most recent call last):
  File "main.py", line 81, in <module>
    pubsub_publisher_client = pubsub.PublisherClient.from_service_account_json(key_path)
TypeError: unbound method from_service_account_file() must be called with PublisherClient instance as first argument (got str instance instead)
```

However, when I use similar code to create datastore client with the service account JSON file, it works. E.g.

```
from google.cloud import datastore
datastore_client = datastore.Client.from_service_account_json(key_path)
```

After checking the source code, perhaps the decorator in `pubsub/google/cloud pubsub_v1/_gapic.py` failed to create the class method properly.



Discussion:
Weird, @lukesneeringer @andreamlin can you take a look?
The bug is almost certainly in [`google.cloud.pubsub_v1._gapic.add_methods`](https://github.com/GoogleCloudPlatform/google-cloud-python/blob/75de6a53c9feee1bc37ee4bfd1369b3010403194/pubsub/google/cloud/pubsub_v1/_gapic.py#L35), which is not detecting that `from_service_account_file` (aliased to `from_service_account_json`) is a classmethod.

Resolving patch:
diff --git a/pubsub/google/cloud/pubsub_v1/_gapic.py b/pubsub/google/cloud/pubsub_v1/_gapic.py
--- a/pubsub/google/cloud/pubsub_v1/_gapic.py
+++ b/pubsub/google/cloud/pubsub_v1/_gapic.py
@@ -32,6 +32,8 @@ def wrap(wrapped_fx):
         # Similarly, for instance methods, we need to send self.api rather
         # than self, since that is where the actual methods were declared.
         instance_method = True
+
+        # If this is a bound method it's a classmethod.
         self = getattr(wrapped_fx, '__self__', None)
         if issubclass(type(self), type):
             instance_method = False
@@ -41,8 +43,9 @@ def wrap(wrapped_fx):
         if instance_method:
             fx = lambda self, *a, **kw: wrapped_fx(self.api, *a, **kw)  # noqa
             return functools.wraps(wrapped_fx)(fx)
-        fx = lambda self, *a, **kw: wrapped_fx(*a, **kw)  # noqa
-        return functools.wraps(wrapped_fx)(fx)
+
+        fx = lambda *a, **kw: wrapped_fx(*a, **kw)  # noqa
+        return staticmethod(functools.wraps(wrapped_fx)(fx))
 
     def actual_decorator(cls):
         # Reflectively iterate over most of the methods on the source class


Test patch: