Skip to content

Commit 1f80e36

Browse files
committed
Addressing review comments in PR #910.
In particular: - Renaming `with_service_...` methods to `from_service_...` on `pubsub.Client`. - Implementing `topic.subscription` factory. - Using `topic.subscription` factory in docs and regression tests instead of instantiating a `Subscription`. - Updating docstring for `http` on `pubsub.Client` to describe the default behavior when no value is passed. - Making `client` a required / positional argument in `pubsub.Topic` (and ditching a test in the process). - Renaming `test_make_topic` as `test_topic`.
1 parent 29f35d0 commit 1f80e36

File tree

7 files changed

+66
-33
lines changed

7 files changed

+66
-33
lines changed

docs/pubsub-usage.rst

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ Authorization / Configuration
1212

1313
- The authentication credentials can be implicitly determined from the
1414
environment or directly via
15-
:meth:`with_service_account_json <gcloud.pubsub.client.Client.with_service_account_json>`
15+
:meth:`from_service_account_json <gcloud.pubsub.client.Client.from_service_account_json>`
1616
and
17-
:meth:`with_service_account_p12 <gcloud.pubsub.client.Client.with_service_account_p12>`.
17+
:meth:`from_service_account_p12 <gcloud.pubsub.client.Client.from_service_account_p12>`.
1818

1919
- After setting ``GOOGLE_APPLICATION_CREDENTIALS`` and ``GCLOUD_PROJECT``
2020
environment variables, create a :class:`Client <gcloud.pubsub.client.Client>`
@@ -121,7 +121,7 @@ Create a new pull subscription for a topic:
121121
>>> from gcloud import pubsub
122122
>>> client = pubsub.Client()
123123
>>> topic = client.topic('topic_name')
124-
>>> subscription = pubsub.Subscription('subscription_name', topic)
124+
>>> subscription = topic.subscription('subscription_name')
125125
>>> subscription.create() # API request
126126

127127
Create a new pull subscription for a topic with a non-default ACK deadline:
@@ -131,7 +131,7 @@ Create a new pull subscription for a topic with a non-default ACK deadline:
131131
>>> from gcloud import pubsub
132132
>>> client = pubsub.Client()
133133
>>> topic = client.topic('topic_name')
134-
>>> subscription = pubsub.Subscription('subscription_name', ack_deadline=90)
134+
>>> subscription = topic.subscription('subscription_name', ack_deadline=90)
135135
>>> subscription.create() # API request
136136

137137
Create a new push subscription for a topic:
@@ -142,8 +142,8 @@ Create a new push subscription for a topic:
142142
>>> ENDPOINT = 'https://example.com/hook'
143143
>>> client = pubsub.Client()
144144
>>> topic = client.topic('topic_name')
145-
>>> subscription = pubsub.Subscription('subscription_name',
146-
... push_endpoint=ENDPOINT)
145+
>>> subscription = topic.subscription('subscription_name',
146+
... push_endpoint=ENDPOINT)
147147
>>> subscription.create() # API request
148148

149149
Check for the existence of a subscription:
@@ -153,7 +153,7 @@ Check for the existence of a subscription:
153153
>>> from gcloud import pubsub
154154
>>> client = pubsub.Client()
155155
>>> topic = client.topic('topic_name')
156-
>>> subscription = pubsub.Subscription('subscription_name', topic)
156+
>>> subscription = topic.subscription('subscription_name')
157157
>>> subscription.exists() # API request
158158
True
159159

@@ -165,7 +165,7 @@ Convert a pull subscription to push:
165165
>>> ENDPOINT = 'https://example.com/hook'
166166
>>> client = pubsub.Client()
167167
>>> topic = client.topic('topic_name')
168-
>>> subscription = pubsub.Subscription('subscription_name', topic)
168+
>>> subscription = topic.subscription('subscription_name')
169169
>>> subscription.modify_push_configuration(push_endpoint=ENDPOINT) # API request
170170

171171
Convert a push subscription to pull:
@@ -176,8 +176,8 @@ Convert a push subscription to pull:
176176
>>> ENDPOINT = 'https://example.com/hook'
177177
>>> client = pubsub.Client()
178178
>>> topic = client.topic('topic_name')
179-
>>> subscription = pubusb.Subscription('subscription_name', topic,
180-
... push_endpoint=ENDPOINT)
179+
>>> subscription = topic.subscription('subscription_name',
180+
... push_endpoint=ENDPOINT)
181181
>>> subscription.modify_push_configuration(push_endpoint=None) # API request
182182

183183
List subscriptions for a topic:
@@ -208,7 +208,7 @@ Delete a subscription:
208208
>>> from gcloud import pubsub
209209
>>> client = pubsub.Client()
210210
>>> topic = client.topic('topic_name')
211-
>>> subscription = pubsub.Subscription('subscription_name', topic)
211+
>>> subscription = topic.subscription('subscription_name')
212212
>>> subscription.delete() # API request
213213

214214

@@ -222,7 +222,7 @@ Fetch pending messages for a pull subscription:
222222
>>> from gcloud import pubsub
223223
>>> client = pubsub.Client()
224224
>>> topic = client.topic('topic_name')
225-
>>> subscription = pubsub.Subscription('subscription_name', topic)
225+
>>> subscription = topic.subscription('subscription_name')
226226
>>> with topic.batch() as batch:
227227
... batch.publish('this is the first message_payload')
228228
... batch.publish('this is the second message_payload',
@@ -251,7 +251,7 @@ Fetch a limited number of pending messages for a pull subscription:
251251
>>> from gcloud import pubsub
252252
>>> client = pubsub.Client()
253253
>>> topic = client.topic('topic_name')
254-
>>> subscription = pubsub.Subscription('subscription_name', topic)
254+
>>> subscription = topic.subscription('subscription_name')
255255
>>> with topic.batch() as batch:
256256
... batch.publish('this is the first message_payload')
257257
... batch.publish('this is the second message_payload',
@@ -267,7 +267,7 @@ Fetch messages for a pull subscription without blocking (none pending):
267267
>>> from gcloud import pubsub
268268
>>> client = pubsub.Client()
269269
>>> topic = client.topic('topic_name')
270-
>>> subscription = pubsub.Subscription('subscription_name', topic)
270+
>>> subscription = topic.subscription('subscription_name')
271271
>>> received = subscription.pull(max_messages=1) # API request
272272
>>> messages = [recv[1] for recv in received]
273273
>>> [message.id for message in messages]

gcloud/pubsub/client.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ class Client(object):
4040
from the environment.
4141
4242
:type http: :class:`httplib2.Http` or class that defines ``request()``.
43-
:param http: An optional HTTP object to make requests.
43+
:param http: An optional HTTP object to make requests. If not passed, an
44+
``http`` object is created that is bound to the
45+
``credentials`` for the current object.
4446
4547
:raises: :class:`ValueError` if the project is neither passed in nor
4648
set in the environment.
@@ -58,7 +60,7 @@ def __init__(self, project=None, credentials=None, http=None):
5860
self.connection = Connection(credentials=credentials, http=http)
5961

6062
@classmethod
61-
def with_service_account_json(cls, json_credentials_path, project=None):
63+
def from_service_account_json(cls, json_credentials_path, project=None):
6264
"""Factory to retrieve JSON credentials while creating client.
6365
6466
:type json_credentials_path: string
@@ -81,7 +83,7 @@ def with_service_account_json(cls, json_credentials_path, project=None):
8183
return cls(project=project, credentials=credentials)
8284

8385
@classmethod
84-
def with_service_account_p12(cls, client_email, private_key_path,
86+
def from_service_account_p12(cls, client_email, private_key_path,
8587
project=None):
8688
"""Factory to retrieve P12 credentials while creating client.
8789

gcloud/pubsub/subscription.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
from gcloud.exceptions import NotFound
1818
from gcloud.pubsub.message import Message
19-
from gcloud.pubsub.topic import Topic
2019

2120

2221
class Subscription(object):
@@ -63,6 +62,9 @@ def from_api_repr(cls, resource, client, topics=None):
6362
:rtype: :class:`gcloud.pubsub.subscription.Subscription`
6463
:returns: Subscription parsed from ``resource``.
6564
"""
65+
# pylint: disable=cyclic-import
66+
from gcloud.pubsub.topic import Topic
67+
# pylint: enable=cyclic-import
6668
if topics is None:
6769
topics = {}
6870
t_name = resource['topic']

gcloud/pubsub/test_client.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def test_ctor_explicit(self):
8282
self.assertTrue(client_obj.connection._credentials is CREDS)
8383
self.assertEqual(CREDS._scopes, SCOPE)
8484

85-
def test_with_service_account_json(self):
85+
def test_from_service_account_json(self):
8686
from gcloud._testing import _Monkey
8787
from gcloud.pubsub import client
8888
from gcloud.pubsub.connection import Connection
@@ -98,15 +98,15 @@ def mock_creds(arg1):
9898

9999
BOGUS_ARG = object()
100100
with _Monkey(client, get_for_service_account_json=mock_creds):
101-
client_obj = KLASS.with_service_account_json(
101+
client_obj = KLASS.from_service_account_json(
102102
BOGUS_ARG, project=PROJECT)
103103

104104
self.assertEqual(client_obj.project, PROJECT)
105105
self.assertTrue(isinstance(client_obj.connection, Connection))
106106
self.assertTrue(client_obj.connection._credentials is CREDS)
107107
self.assertEqual(_CALLED, [(BOGUS_ARG,)])
108108

109-
def test_with_service_account_p12(self):
109+
def test_from_service_account_p12(self):
110110
from gcloud._testing import _Monkey
111111
from gcloud.pubsub import client
112112
from gcloud.pubsub.connection import Connection
@@ -123,7 +123,7 @@ def mock_creds(arg1, arg2):
123123
BOGUS_ARG1 = object()
124124
BOGUS_ARG2 = object()
125125
with _Monkey(client, get_for_service_account_p12=mock_creds):
126-
client_obj = KLASS.with_service_account_p12(
126+
client_obj = KLASS.from_service_account_p12(
127127
BOGUS_ARG1, BOGUS_ARG2, project=PROJECT)
128128

129129
self.assertEqual(client_obj.project, PROJECT)
@@ -302,7 +302,7 @@ def test_list_subscriptions_with_topic_name(self):
302302
% (PROJECT, TOPIC_NAME))
303303
self.assertEqual(req['query_params'], {})
304304

305-
def test_make_topic(self):
305+
def test_topic(self):
306306
PROJECT = 'PROJECT'
307307
TOPIC_NAME = 'TOPIC_NAME'
308308
CREDS = _Credentials()

gcloud/pubsub/test_topic.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ def _getTargetClass(self):
2424
def _makeOne(self, *args, **kw):
2525
return self._getTargetClass()(*args, **kw)
2626

27-
def test_ctor_wo_client(self):
28-
self.assertRaises(ValueError, self._makeOne, 'TOPIC_NAME', client=None)
29-
3027
def test_ctor_w_explicit_timestamp(self):
3128
TOPIC_NAME = 'topic_name'
3229
PROJECT = 'PROJECT'
@@ -334,6 +331,20 @@ def test_delete_w_alternate_client(self):
334331
self.assertEqual(req['method'], 'DELETE')
335332
self.assertEqual(req['path'], '/%s' % PATH)
336333

334+
def test_subscription(self):
335+
from gcloud.pubsub.subscription import Subscription
336+
TOPIC_NAME = 'topic_name'
337+
PROJECT = 'PROJECT'
338+
CLIENT = _Client(project=PROJECT)
339+
topic = self._makeOne(TOPIC_NAME,
340+
client=CLIENT)
341+
342+
SUBSCRIPTION_NAME = 'subscription_name'
343+
subscription = topic.subscription(SUBSCRIPTION_NAME)
344+
self.assertTrue(isinstance(subscription, Subscription))
345+
self.assertEqual(subscription.name, SUBSCRIPTION_NAME)
346+
self.assertTrue(subscription.topic is topic)
347+
337348

338349
class TestBatch(unittest2.TestCase):
339350

gcloud/pubsub/topic.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,32 @@ class Topic(object):
4343
to the attributes of each published message:
4444
the value will be an RFC 3339 timestamp.
4545
"""
46-
def __init__(self, name, client=None, timestamp_messages=False):
46+
def __init__(self, name, client, timestamp_messages=False):
4747
self.name = name
48-
if client is None:
49-
raise ValueError('Topic constructor requires a client.')
5048
self._client = client
5149
self.timestamp_messages = timestamp_messages
5250

51+
def subscription(self, name, ack_deadline=None, push_endpoint=None):
52+
"""Creates a subscription bound to the current topic.
53+
54+
:type name: string
55+
:param name: the name of the subscription
56+
57+
:type ack_deadline: int
58+
:param ack_deadline: the deadline (in seconds) by which messages pulled
59+
from the back-end must be acknowledged.
60+
61+
:type push_endpoint: string
62+
:param push_endpoint: URL to which messages will be pushed by the
63+
back-end. If not set, the application must pull
64+
messages.
65+
"""
66+
# pylint: disable=cyclic-import
67+
from gcloud.pubsub.subscription import Subscription
68+
# pylint: enable=cyclic-import
69+
return Subscription(name, self, ack_deadline=ack_deadline,
70+
push_endpoint=push_endpoint)
71+
5372
@classmethod
5473
def from_api_repr(cls, resource, client):
5574
"""Factory: construct a topic given its API representation

regression/pubsub.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
from gcloud import _helpers
2020
from gcloud import pubsub
21-
from gcloud.pubsub.subscription import Subscription
2221

2322

2423
_helpers._PROJECT_ENV_VAR_NAME = 'GCLOUD_TESTS_PROJECT_ID'
@@ -68,7 +67,7 @@ def test_create_subscription(self):
6867
topic.create()
6968
self.to_delete.append(topic)
7069
SUBSCRIPTION_NAME = 'subscribing-now'
71-
subscription = Subscription(SUBSCRIPTION_NAME, topic)
70+
subscription = topic.subscription(SUBSCRIPTION_NAME)
7271
self.assertFalse(subscription.exists())
7372
subscription.create()
7473
self.to_delete.append(subscription)
@@ -88,7 +87,7 @@ def test_list_subscriptions(self):
8887
'newest%d' % (1000 * time.time(),),
8988
]
9089
for subscription_name in subscriptions_to_create:
91-
subscription = Subscription(subscription_name, topic)
90+
subscription = topic.subscription(subscription_name)
9291
subscription.create()
9392
self.to_delete.append(subscription)
9493

@@ -106,7 +105,7 @@ def test_message_pull_mode_e2e(self):
106105
topic.create()
107106
self.to_delete.append(topic)
108107
SUBSCRIPTION_NAME = 'subscribing-now'
109-
subscription = Subscription(SUBSCRIPTION_NAME, topic)
108+
subscription = topic.subscription(SUBSCRIPTION_NAME)
110109
self.assertFalse(subscription.exists())
111110
subscription.create()
112111
self.to_delete.append(subscription)

0 commit comments

Comments
 (0)