Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 63 additions & 1 deletion gcloud/pubsub/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,66 @@
# See the License for the specific language governing permissions and
# limitations under the License.

"""GCloud Pubsub API wrapper."""
"""GCloud Pubsub API wrapper.


The main concepts with this API are:

- :class:`gcloud.pubsub.topic.Topic` represents an endpoint to which messages
can be published using the Cloud Storage Pubsub API.

- :class:`gcloud.pubsub.subscription.Subscription` represents a named
subscription (either pull or push) to a topic.
"""

from gcloud._helpers import get_default_project
from gcloud._helpers import set_default_project
from gcloud.connection import get_scoped_connection
from gcloud.pubsub import _implicit_environ
from gcloud.pubsub._implicit_environ import get_default_connection
from gcloud.pubsub.connection import Connection


SCOPE = ('https://www.googleapis.com/auth/pubsub',
'https://www.googleapis.com/auth/cloud-platform')


def set_default_connection(connection=None):
"""Set default connection either explicitly or implicitly as fall-back.

:type connection: :class:`gcloud.pubsub.connection.Connection`
:param connection: A connection provided to be the default.
"""
_implicit_environ._DEFAULTS.connection = connection or get_connection()


def set_defaults(project=None, connection=None):
"""Set defaults either explicitly or implicitly as fall-back.

Uses the arguments to call the individual default methods.

:type project: string
:param project: Optional. The name of the project to connect to.

:type connection: :class:`gcloud.pubsub.connection.Connection`
:param connection: Optional. A connection provided to be the default.
"""
set_default_project(project=project)
set_default_connection(connection=connection)


def get_connection():
"""Shortcut method to establish a connection to Cloud Storage.

Use this if you are going to access several buckets with the same
set of credentials:

>>> from gcloud import pubsub
>>> connection = pubsub.get_connection()
>>> bucket1 = pubsub.get_bucket('bucket1', connection=connection)
>>> bucket2 = pubsub.get_bucket('bucket2', connection=connection)

:rtype: :class:`gcloud.pubsub.connection.Connection`
:returns: A connection defined with the proper credentials.
"""
return get_scoped_connection(Connection, SCOPE)
41 changes: 41 additions & 0 deletions gcloud/pubsub/_implicit_environ.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Module to provide implicit behavior based on enviroment.

Allows the pubsub package to infer the default connection from the enviroment.
"""


class _DefaultsContainer(object):
"""Container for defaults.

:type connection: :class:`gcloud.pubsub.connection.Connection`
:param connection: Persistent implied connection from environment.
"""

def __init__(self, connection=None):
self.connection = connection


def get_default_connection():
"""Get default connection.

:rtype: :class:`gcloud.pubsub.connection.Connection` or ``NoneType``
:returns: The default connection if one has been set.
"""
return _DEFAULTS.connection


_DEFAULTS = _DefaultsContainer()
33 changes: 33 additions & 0 deletions gcloud/pubsub/_testing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright 2014 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Shared pubsub testing utilities."""

from gcloud._testing import _Monkey
from gcloud.pubsub import _implicit_environ
from gcloud.pubsub._implicit_environ import _DefaultsContainer


def _monkey_defaults(*args, **kwargs):
mock_defaults = _DefaultsContainer(*args, **kwargs)
return _Monkey(_implicit_environ, _DEFAULTS=mock_defaults)


def _setup_defaults(test_case, *args, **kwargs):
test_case._replaced_defaults = _implicit_environ._DEFAULTS
_implicit_environ._DEFAULTS = _DefaultsContainer(*args, **kwargs)


def _tear_down_defaults(test_case):
_implicit_environ._DEFAULTS = test_case._replaced_defaults
15 changes: 15 additions & 0 deletions gcloud/pubsub/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

""" Define API functions (not bound to classes)."""

from gcloud._helpers import get_default_project
from gcloud.pubsub._implicit_environ import get_default_connection


def list_topics(page_size=None, page_token=None,
project=None, connection=None):
Expand Down Expand Up @@ -45,6 +48,12 @@ def list_topics(page_size=None, page_token=None,
more topics can be retrieved with another call (pass that
value as ``page_token``).
"""
if project is None:
project = get_default_project()

if connection is None:
connection = get_default_connection()

params = {}

if page_size is not None:
Expand Down Expand Up @@ -93,6 +102,12 @@ def list_subscriptions(page_size=None, page_token=None, topic_name=None,
more topics can be retrieved with another call (pass that
value as ``page_token``).
"""
if project is None:
project = get_default_project()

if connection is None:
connection = get_default_connection()

params = {}

if page_size is not None:
Expand Down
114 changes: 114 additions & 0 deletions gcloud/pubsub/test___init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import unittest2


class Test_set_default_connection(unittest2.TestCase):

def setUp(self):
from gcloud.pubsub._testing import _setup_defaults
_setup_defaults(self)

def tearDown(self):
from gcloud.pubsub._testing import _tear_down_defaults
_tear_down_defaults(self)

def _callFUT(self, connection=None):
from gcloud.pubsub import set_default_connection
return set_default_connection(connection=connection)

def test_set_explicit(self):
from gcloud.pubsub import _implicit_environ

self.assertEqual(_implicit_environ.get_default_connection(), None)
fake_cnxn = object()
self._callFUT(connection=fake_cnxn)
self.assertEqual(_implicit_environ.get_default_connection(), fake_cnxn)

def test_set_implicit(self):
from gcloud._testing import _Monkey
from gcloud import pubsub
from gcloud.pubsub import _implicit_environ

self.assertEqual(_implicit_environ.get_default_connection(), None)

fake_cnxn = object()
_called_args = []
_called_kwargs = []

def mock_get_connection(*args, **kwargs):
_called_args.append(args)
_called_kwargs.append(kwargs)
return fake_cnxn

with _Monkey(pubsub, get_connection=mock_get_connection):
self._callFUT()

self.assertEqual(_implicit_environ.get_default_connection(), fake_cnxn)
self.assertEqual(_called_args, [()])
self.assertEqual(_called_kwargs, [{}])


class Test_set_defaults(unittest2.TestCase):

def _callFUT(self, project=None, connection=None):
from gcloud.pubsub import set_defaults
return set_defaults(project=project, connection=connection)

def test_it(self):
from gcloud._testing import _Monkey
from gcloud import pubsub

PROJECT = object()
CONNECTION = object()

SET_PROJECT_CALLED = []

def call_set_project(project=None):
SET_PROJECT_CALLED.append(project)

SET_CONNECTION_CALLED = []

def call_set_connection(connection=None):
SET_CONNECTION_CALLED.append(connection)

with _Monkey(pubsub,
set_default_connection=call_set_connection,
set_default_project=call_set_project):
self._callFUT(project=PROJECT, connection=CONNECTION)

self.assertEqual(SET_PROJECT_CALLED, [PROJECT])
self.assertEqual(SET_CONNECTION_CALLED, [CONNECTION])


class Test_get_connection(unittest2.TestCase):

def _callFUT(self, *args, **kw):
from gcloud.pubsub import get_connection
return get_connection(*args, **kw)

def test_it(self):
from gcloud import credentials
from gcloud.pubsub import SCOPE
from gcloud.pubsub.connection import Connection
from gcloud.test_credentials import _Client
from gcloud._testing import _Monkey
client = _Client()
with _Monkey(credentials, client=client):
found = self._callFUT()
self.assertTrue(isinstance(found, Connection))
self.assertTrue(found._credentials is client._signed)
self.assertEqual(found._credentials._scopes, SCOPE)
self.assertTrue(client._get_app_default_called)
25 changes: 25 additions & 0 deletions gcloud/pubsub/test__implicit_environ.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2014 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import unittest2


class Test_get_default_connection(unittest2.TestCase):

def _callFUT(self):
from gcloud.storage._implicit_environ import get_default_connection
return get_default_connection()

def test_wo_override(self):
self.assertTrue(self._callFUT() is None)
34 changes: 30 additions & 4 deletions gcloud/pubsub/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,29 @@ def test_w_explicit_connection_no_paging(self):
self.assertEqual(req['path'], '/projects/%s/topics' % PROJECT)
self.assertEqual(req['query_params'], {})

def test_w_explicit_connection_w_paging(self):
def test_w_implicit_connection_and_project_wo_paging(self):
from gcloud._testing import _monkey_defaults as _monkey_base_defaults
from gcloud.pubsub._testing import _monkey_defaults
TOPIC_NAME = 'topic_name'
PROJECT = 'PROJECT'
TOKEN = 'TOKEN'
returned = {'topics': [{'name': TOPIC_NAME}],
'nextPageToken': TOKEN}
conn = _Connection(returned)
with _monkey_base_defaults(project=PROJECT):
with _monkey_defaults(connection=conn):
response = self._callFUT()
topics = response['topics']
self.assertEqual(len(topics), 1)
self.assertEqual(topics[0], {'name': TOPIC_NAME})
self.assertEqual(response['nextPageToken'], TOKEN)
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/projects/%s/topics' % PROJECT)
self.assertEqual(req['query_params'], {})

def test_w_explicit_connection_and_project_w_paging(self):
TOPIC_NAME = 'topic_name'
PROJECT = 'PROJECT'
TOKEN1 = 'TOKEN1'
Expand Down Expand Up @@ -67,7 +89,9 @@ def _callFUT(self, *args, **kw):
from gcloud.pubsub.api import list_subscriptions
return list_subscriptions(*args, **kw)

def test_w_explicit_connection_no_paging(self):
def test_w_implicit_connection_wo_paging(self):
from gcloud._testing import _monkey_defaults as _monkey_base_defaults
from gcloud.pubsub._testing import _monkey_defaults
PROJECT = 'PROJECT'
SUB_NAME = 'topic_name'
SUB_PATH = 'projects/%s/subscriptions/%s' % (PROJECT, SUB_NAME)
Expand All @@ -77,7 +101,9 @@ def test_w_explicit_connection_no_paging(self):
returned = {'subscriptions': [{'name': SUB_PATH, 'topic': TOPIC_PATH}],
'nextPageToken': TOKEN}
conn = _Connection(returned)
response = self._callFUT(project=PROJECT, connection=conn)
with _monkey_base_defaults(project=PROJECT):
with _monkey_defaults(connection=conn):
response = self._callFUT()
subscriptions = response['subscriptions']
self.assertEqual(len(subscriptions), 1)
self.assertEqual(subscriptions[0],
Expand All @@ -89,7 +115,7 @@ def test_w_explicit_connection_no_paging(self):
self.assertEqual(req['path'], '/projects/%s/subscriptions' % PROJECT)
self.assertEqual(req['query_params'], {})

def test_w_explicit_connection_w_paging(self):
def test_w_explicit_connection_and_project_w_paging(self):
PROJECT = 'PROJECT'
SUB_NAME = 'topic_name'
SUB_PATH = 'projects/%s/subscriptions/%s' % (PROJECT, SUB_NAME)
Expand Down
Loading