PageRenderTime 59ms CodeModel.GetById 13ms app.highlight 30ms RepoModel.GetById 5ms app.codeStats 0ms

/boto-2.5.2/boto/sqs/connection.py

#
Python | 414 lines | 384 code | 6 blank | 24 comment | 4 complexity | ce2eeb87076fe411e9e96a51250fda08 MD5 | raw file
  1# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
  2#
  3# Permission is hereby granted, free of charge, to any person obtaining a
  4# copy of this software and associated documentation files (the
  5# "Software"), to deal in the Software without restriction, including
  6# without limitation the rights to use, copy, modify, merge, publish, dis-
  7# tribute, sublicense, and/or sell copies of the Software, and to permit
  8# persons to whom the Software is furnished to do so, subject to the fol-
  9# lowing conditions:
 10#
 11# The above copyright notice and this permission notice shall be included
 12# in all copies or substantial portions of the Software.
 13#
 14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 15# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
 16# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
 17# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 18# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 19# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 20# IN THE SOFTWARE.
 21
 22from boto.connection import AWSQueryConnection
 23from boto.sqs.regioninfo import SQSRegionInfo
 24from boto.sqs.queue import Queue
 25from boto.sqs.message import Message
 26from boto.sqs.attributes import Attributes
 27from boto.sqs.batchresults import BatchResults
 28from boto.exception import SQSError, BotoServerError
 29
 30
 31class SQSConnection(AWSQueryConnection):
 32    """
 33    A Connection to the SQS Service.
 34    """
 35    DefaultRegionName = 'us-east-1'
 36    DefaultRegionEndpoint = 'sqs.us-east-1.amazonaws.com'
 37    APIVersion = '2011-10-01'
 38    DefaultContentType = 'text/plain'
 39    ResponseError = SQSError
 40
 41    def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
 42                 is_secure=True, port=None, proxy=None, proxy_port=None,
 43                 proxy_user=None, proxy_pass=None, debug=0,
 44                 https_connection_factory=None, region=None, path='/',
 45                 security_token=None):
 46        if not region:
 47            region = SQSRegionInfo(self, self.DefaultRegionName,
 48                                   self.DefaultRegionEndpoint)
 49        self.region = region
 50        AWSQueryConnection.__init__(self, aws_access_key_id,
 51                                    aws_secret_access_key,
 52                                    is_secure, port,
 53                                    proxy, proxy_port,
 54                                    proxy_user, proxy_pass,
 55                                    self.region.endpoint, debug,
 56                                    https_connection_factory, path,
 57                                    security_token=security_token)
 58
 59    def _required_auth_capability(self):
 60        return ['sqs']
 61
 62    def _credentials_expired(self, response):
 63        if response.status != 401:
 64            return False
 65        error = BotoServerError('', '', body=response.read())
 66        return error.error_code == 'InvalidAccessKeyId'
 67
 68    def create_queue(self, queue_name, visibility_timeout=None):
 69        """
 70        Create an SQS Queue.
 71
 72        :type queue_name: str or unicode
 73        :param queue_name: The name of the new queue.  Names are
 74            scoped to an account and need to be unique within that
 75            account.  Calling this method on an existing queue name
 76            will not return an error from SQS unless the value for
 77            visibility_timeout is different than the value of the
 78            existing queue of that name.  This is still an expensive
 79            operation, though, and not the preferred way to check for
 80            the existence of a queue.  See the
 81            :func:`boto.sqs.connection.SQSConnection.lookup` method.
 82
 83        :type visibility_timeout: int
 84        :param visibility_timeout: The default visibility timeout for
 85            all messages written in the queue.  This can be overridden
 86            on a per-message.
 87
 88        :rtype: :class:`boto.sqs.queue.Queue`
 89        :return: The newly created queue.
 90
 91        """
 92        params = {'QueueName': queue_name}
 93        if visibility_timeout:
 94            params['Attribute.1.Name'] = 'VisibilityTimeout'
 95            params['Attribute.1.Value'] = int(visibility_timeout)
 96        return self.get_object('CreateQueue', params, Queue)
 97
 98    def delete_queue(self, queue, force_deletion=False):
 99        """
100        Delete an SQS Queue.
101
102        :type queue: A Queue object
103        :param queue: The SQS queue to be deleted
104
105        :type force_deletion: Boolean
106        :param force_deletion: Normally, SQS will not delete a queue
107            that contains messages.  However, if the force_deletion
108            argument is True, the queue will be deleted regardless of
109            whether there are messages in the queue or not.  USE WITH
110            CAUTION.  This will delete all messages in the queue as
111            well.
112
113        :rtype: bool
114        :return: True if the command succeeded, False otherwise
115        """
116        return self.get_status('DeleteQueue', None, queue.id)
117
118    def get_queue_attributes(self, queue, attribute='All'):
119        """
120        Gets one or all attributes of a Queue
121
122        :type queue: A Queue object
123        :param queue: The SQS queue to be deleted
124
125        :type attribute: str
126        :type attribute: The specific attribute requested.  If not
127            supplied, the default is to return all attributes.  Valid
128            attributes are:
129
130            * ApproximateNumberOfMessages|
131            * ApproximateNumberOfMessagesNotVisible|
132            * VisibilityTimeout|
133            * CreatedTimestamp|
134            * LastModifiedTimestamp|
135            * Policy
136
137        :rtype: :class:`boto.sqs.attributes.Attributes`
138        :return: An Attributes object containing request value(s).
139        """
140        params = {'AttributeName' : attribute}
141        return self.get_object('GetQueueAttributes', params,
142                               Attributes, queue.id)
143
144    def set_queue_attribute(self, queue, attribute, value):
145        params = {'Attribute.Name' : attribute, 'Attribute.Value' : value}
146        return self.get_status('SetQueueAttributes', params, queue.id)
147
148    def receive_message(self, queue, number_messages=1,
149                        visibility_timeout=None, attributes=None):
150        """
151        Read messages from an SQS Queue.
152
153        :type queue: A Queue object
154        :param queue: The Queue from which messages are read.
155
156        :type number_messages: int
157        :param number_messages: The maximum number of messages to read
158                                (default=1)
159
160        :type visibility_timeout: int
161        :param visibility_timeout: The number of seconds the message should
162            remain invisible to other queue readers
163            (default=None which uses the Queues default)
164
165        :type attributes: str
166        :param attributes: The name of additional attribute to return
167            with response or All if you want all attributes.  The
168            default is to return no additional attributes.  Valid
169            values:
170            * All
171            * SenderId
172            * SentTimestamp
173            * ApproximateReceiveCount
174            * ApproximateFirstReceiveTimestamp
175
176        :rtype: list
177        :return: A list of :class:`boto.sqs.message.Message` objects.
178        """
179        params = {'MaxNumberOfMessages' : number_messages}
180        if visibility_timeout:
181            params['VisibilityTimeout'] = visibility_timeout
182        if attributes:
183            self.build_list_params(params, attributes, 'AttributeName')
184        return self.get_list('ReceiveMessage', params,
185                             [('Message', queue.message_class)],
186                             queue.id, queue)
187
188    def delete_message(self, queue, message):
189        """
190        Delete a message from a queue.
191
192        :type queue: A :class:`boto.sqs.queue.Queue` object
193        :param queue: The Queue from which messages are read.
194
195        :type message: A :class:`boto.sqs.message.Message` object
196        :param message: The Message to be deleted
197
198        :rtype: bool
199        :return: True if successful, False otherwise.
200        """
201        params = {'ReceiptHandle' : message.receipt_handle}
202        return self.get_status('DeleteMessage', params, queue.id)
203
204    def delete_message_batch(self, queue, messages):
205        """
206        Deletes a list of messages from a queue in a single request.
207
208        :type queue: A :class:`boto.sqs.queue.Queue` object.
209        :param queue: The Queue to which the messages will be written.
210
211        :type messages: List of :class:`boto.sqs.message.Message` objects.
212        :param messages: A list of message objects.
213        """
214        params = {}
215        for i, msg in enumerate(messages):
216            prefix = 'DeleteMessageBatchRequestEntry'
217            p_name = '%s.%i.Id' % (prefix, (i+1))
218            params[p_name] = msg.id
219            p_name = '%s.%i.ReceiptHandle' % (prefix, (i+1))
220            params[p_name] = msg.receipt_handle
221        return self.get_object('DeleteMessageBatch', params, BatchResults,
222                               queue.id, verb='POST')
223
224    def delete_message_from_handle(self, queue, receipt_handle):
225        """
226        Delete a message from a queue, given a receipt handle.
227
228        :type queue: A :class:`boto.sqs.queue.Queue` object
229        :param queue: The Queue from which messages are read.
230
231        :type receipt_handle: str
232        :param receipt_handle: The receipt handle for the message
233
234        :rtype: bool
235        :return: True if successful, False otherwise.
236        """
237        params = {'ReceiptHandle' : receipt_handle}
238        return self.get_status('DeleteMessage', params, queue.id)
239
240    def send_message(self, queue, message_content, delay_seconds=None):
241        params = {'MessageBody' : message_content}
242        if delay_seconds:
243            params['DelaySeconds'] = int(delay_seconds)
244        return self.get_object('SendMessage', params, Message,
245                               queue.id, verb='POST')
246
247    def send_message_batch(self, queue, messages):
248        """
249        Delivers up to 10 messages to a queue in a single request.
250
251        :type queue: A :class:`boto.sqs.queue.Queue` object.
252        :param queue: The Queue to which the messages will be written.
253
254        :type messages: List of lists.
255        :param messages: A list of lists or tuples.  Each inner
256            tuple represents a single message to be written
257            and consists of and ID (string) that must be unique
258            within the list of messages, the message body itself
259            which can be a maximum of 64K in length, and an
260            integer which represents the delay time (in seconds)
261            for the message (0-900) before the message will
262            be delivered to the queue.
263        """
264        params = {}
265        for i, msg in enumerate(messages):
266            p_name = 'SendMessageBatchRequestEntry.%i.Id' % (i+1)
267            params[p_name] = msg[0]
268            p_name = 'SendMessageBatchRequestEntry.%i.MessageBody' % (i+1)
269            params[p_name] = msg[1]
270            p_name = 'SendMessageBatchRequestEntry.%i.DelaySeconds' % (i+1)
271            params[p_name] = msg[2]
272        return self.get_object('SendMessageBatch', params, BatchResults,
273                               queue.id, verb='POST')
274
275    def change_message_visibility(self, queue, receipt_handle,
276                                  visibility_timeout):
277        """
278        Extends the read lock timeout for the specified message from
279        the specified queue to the specified value.
280
281        :type queue: A :class:`boto.sqs.queue.Queue` object
282        :param queue: The Queue from which messages are read.
283
284        :type receipt_handle: str
285        :param queue: The receipt handle associated with the message whose
286                      visibility timeout will be changed.
287
288        :type visibility_timeout: int
289        :param visibility_timeout: The new value of the message's visibility
290                                   timeout in seconds.
291        """
292        params = {'ReceiptHandle' : receipt_handle,
293                  'VisibilityTimeout' : visibility_timeout}
294        return self.get_status('ChangeMessageVisibility', params, queue.id)
295
296    def change_message_visibility_batch(self, queue, messages):
297        """
298        A batch version of change_message_visibility that can act
299        on up to 10 messages at a time.
300
301        :type queue: A :class:`boto.sqs.queue.Queue` object.
302        :param queue: The Queue to which the messages will be written.
303
304        :type messages: List of tuples.
305        :param messages: A list of tuples where each tuple consists
306            of a :class:`boto.sqs.message.Message` object and an integer
307            that represents the new visibility timeout for that message.
308        """
309        params = {}
310        for i, t in enumerate(messages):
311            prefix = 'ChangeMessageVisibilityBatchRequestEntry'
312            p_name = '%s.%i.Id' % (prefix, (i+1))
313            params[p_name] = t[0].id
314            p_name = '%s.%i.ReceiptHandle' % (prefix, (i+1))
315            params[p_name] = t[0].receipt_handle
316            p_name = '%s.%i.VisibilityTimeout' % (prefix, (i+1))
317            params[p_name] = t[1]
318        return self.get_object('ChangeMessageVisibilityBatch',
319                               params, BatchResults,
320                               queue.id, verb='POST')
321
322    def get_all_queues(self, prefix=''):
323        """
324        Retrieves all queues.
325
326        :keyword str prefix: Optionally, only return queues that start with
327            this value.
328        :rtype: list
329        :returns: A list of :py:class:`boto.sqs.queue.Queue` instances.
330        """
331        params = {}
332        if prefix:
333            params['QueueNamePrefix'] = prefix
334        return self.get_list('ListQueues', params, [('QueueUrl', Queue)])
335
336    def get_queue(self, queue_name):
337        """
338        Retrieves the queue with the given name, or ``None`` if no match
339        was found.
340
341        :param str queue_name: The name of the queue to retrieve.
342        :rtype: :py:class:`boto.sqs.queue.Queue` or ``None``
343        :returns: The requested queue, or ``None`` if no match was found.
344        """
345        params = {'QueueName': queue_name}
346        try:
347            return self.get_object('GetQueueUrl', params, Queue)
348        except SQSError:
349            return None
350
351    lookup = get_queue
352
353    #
354    # Permissions methods
355    #
356
357    def add_permission(self, queue, label, aws_account_id, action_name):
358        """
359        Add a permission to a queue.
360
361        :type queue: :class:`boto.sqs.queue.Queue`
362        :param queue: The queue object
363
364        :type label: str or unicode
365        :param label: A unique identification of the permission you are setting.
366            Maximum of 80 characters ``[0-9a-zA-Z_-]``
367            Example, AliceSendMessage
368
369        :type aws_account_id: str or unicode
370        :param principal_id: The AWS account number of the principal
371            who will be given permission.  The principal must have an
372            AWS account, but does not need to be signed up for Amazon
373            SQS. For information about locating the AWS account
374            identification.
375
376        :type action_name: str or unicode
377        :param action_name: The action.  Valid choices are:
378            * *
379            * SendMessage
380            * ReceiveMessage
381            * DeleteMessage
382            * ChangeMessageVisibility
383            * GetQueueAttributes
384
385        :rtype: bool
386        :return: True if successful, False otherwise.
387
388        """
389        params = {'Label': label,
390                  'AWSAccountId' : aws_account_id,
391                  'ActionName' : action_name}
392        return self.get_status('AddPermission', params, queue.id)
393
394    def remove_permission(self, queue, label):
395        """
396        Remove a permission from a queue.
397
398        :type queue: :class:`boto.sqs.queue.Queue`
399        :param queue: The queue object
400
401        :type label: str or unicode
402        :param label: The unique label associated with the permission
403                      being removed.
404
405        :rtype: bool
406        :return: True if successful, False otherwise.
407        """
408        params = {'Label': label}
409        return self.get_status('RemovePermission', params, queue.id)
410
411
412
413
414