From 89f0d7efc6da45577006e2fe6fd7b400dcc62d52 Mon Sep 17 00:00:00 2001 From: JJ Geewax Date: Sun, 12 Oct 2014 13:09:23 -0400 Subject: [PATCH] First pass at stubbing out gcloud.pubsub. --- gcloud/pubsub/__init__.py | 59 +++++++++++++++++++++++++++++++++ gcloud/pubsub/connection.py | 62 +++++++++++++++++++++++++++++++++++ gcloud/pubsub/subscription.py | 21 ++++++++++++ gcloud/pubsub/topic.py | 23 +++++++++++++ 4 files changed, 165 insertions(+) create mode 100644 gcloud/pubsub/__init__.py create mode 100644 gcloud/pubsub/connection.py create mode 100644 gcloud/pubsub/subscription.py create mode 100644 gcloud/pubsub/topic.py diff --git a/gcloud/pubsub/__init__.py b/gcloud/pubsub/__init__.py new file mode 100644 index 000000000000..eecb481e6239 --- /dev/null +++ b/gcloud/pubsub/__init__.py @@ -0,0 +1,59 @@ +"""Shortcut methods for getting set up with Google Cloud Pub/Sub. + +You'll typically use these to get started with the API: + +>>> from gcloud import pubsub +>>> connection = pubsub.get_connection('long-email@googleapis.com', +... '/path/to/private.key') +>>> # Then do other things... +>>> topic = connection.create_topic('topic-name-here') +>>> topic.publish_message('My message', labels=['label1', 1234, 'label2'] + +The main concepts with this API are: + +- :class:`gcloud.pubsub.connection.Connection` + which represents a connection between your machine and Cloud Pub/Sub. + +- :class:`gcloud.pubsub.topic.Topic` + which represents a particular topic. + +- :class:`gcloud.pubsub.subscription.Subscription` + which represents a subscription to a topic. + +- :class:`gcloud.pubsub.message.Message` + which represents a message pulled from a Subscription. +""" + +__version__ = '0.0.1' + +SCOPE = ('https://www.googleapis.com/auth/pubsub', + 'https://www.googleapis.com/auth/cloud-platform') +"""The scope required for authenticating as a Cloud Pub/Sub consumer.""" + + +def get_connection(client_email, private_key_path): + """Shortcut method to establish a connection to Cloud Pub/Sub. + + Use this to quickly establish a connection to the Pub/Sub API. + + >>> from gcloud import pubsub + >>> connection = pubsub.get_connection(email, key_path) + >>> topic = connection.get_topic('topic-name') + + :type client_email: string + :param client_email: The e-mail attached to the service account. + + :type private_key_path: string + :param private_key_path: The path to a private key file (this file was + given to you when you created the service + account). + + :rtype: :class:`gcloud.pubsub.connection.Connection` + :returns: A connection defined with the proper credentials. + """ + from gcloud.credentials import Credentials + from gcloud.pubsub.connection import Connection + + credentials = Credentials.get_for_service_account( + client_email, private_key_path, scope=SCOPE) + return Connection(credentials=credentials) diff --git a/gcloud/pubsub/connection.py b/gcloud/pubsub/connection.py new file mode 100644 index 000000000000..873c8ac576c9 --- /dev/null +++ b/gcloud/pubsub/connection.py @@ -0,0 +1,62 @@ +from gcloud import connection + + +class Connection(connection.JsonConnection): + """""" + + API_VERSION = 'v1beta1' + """""" + + API_URL_TEMPLATE = '{api_base}/pubsub/{api_version}' + """""" + + @classmethod + def build_api_url(cls, resource_type, resource_id=None, method=None, base_url=None, + api_version-None): + """""" + + api_url_base = cls.API_URL_TEMPLATE.format( + api_base=(base_url or cls.API_BASE_URL), + api_version=(api_version or cls.API_VERSION), + resouce_type=resource_type, resource_id=resource_id, + method=method) + + # TODO: Do some error checking and throw a ValueError if the + # parameters are invalid. + + pieces = list(filter(None, resource_type, resource_id, method)) + return '/'.join([api_url_base] + pieces) + + + def create_topic(self, name): + pass + + def delete_topic(self, name): + pass + + def get_topic(self, name): + pass + + def get_topics(self): + pass + + def create_subscription(self, topic_name, name, push_endpoint=None, ack_deadline=None): + pass + + def delete_subscription(self, name): + pass + + def get_subscription(self, name): + pass + + def get_subscriptions(self, query): + pass + + def publish_message(self, topic_name, message, labels=None): + pass + + def get_message(self, subscription_name): + pass + + # TODO: Figure out how we're going to handle async subscriptions... + # asyncio.Future (Python 3)? multiprocessing.Pool (Python 2)? diff --git a/gcloud/pubsub/subscription.py b/gcloud/pubsub/subscription.py new file mode 100644 index 000000000000..6494a7067ab5 --- /dev/null +++ b/gcloud/pubsub/subscription.py @@ -0,0 +1,21 @@ +class Subscription(object): + + def __init__(self, connection=None, topic=None, name=None): + self.connection = connection + self.topic = topic + self.name = name + + @classmethod + def from_dict(cls, subscription_dict, connection=None): + return cls(connection=connection, topic=subscription_dict['topic'], + name=subscription_dict['name']) + + def __repr__(self): # pragma NO COVER + topic_name = self.topic.name if self.topic else None + return '' % (self.name, topic_name) + + def delete(self): + pass + + def get_message(self): + return self.connection.get_message(self.name) diff --git a/gcloud/pubsub/topic.py b/gcloud/pubsub/topic.py new file mode 100644 index 000000000000..d8258f47eefb --- /dev/null +++ b/gcloud/pubsub/topic.py @@ -0,0 +1,23 @@ +class Topic(object): + + def __init__(self, connection=None, name=None): + self.connection = connection + self.name = name + + @classmethod + def from_dict(cls, topic_dict, connection=None): + return cls(connection=connection, name=topic_dict['name']) + + def __repr__(self): # pragma NO COVER + return '' % self.name + + def delete(self): + pass + + def subscribe(self, name, *args, **kwargs): + return self.connection.create_subscription(topic_name=self.name, + name=name, *args, **kwargs) + + def publish(self, message, labels=None): + return self.connection.publish_message(topic_name=self.name, + message=message, labels=labels)