1. Jason Pellerin
  2. python-stomp

Commits

Benjamin Smith  committed 91ac9df

Create error exception. Raised when broker returns an error frame. Pep8 Cleanup.

  • Participants
  • Parent commits 2cfdc97
  • Branches default

Comments (0)

Files changed (5)

File stompy/frame.py

View file
 from Queue import Queue
 from Queue import Empty as QueueEmpty
 
+
 class UnknownBrokerResponseError(Exception):
     """An unexpected response was received from the broker."""
 
 
+class BrokerErrorResponse(Exception):
+    """Received error from the broker."""
+
+
 class IntermediateMessageQueue(object):
     """Internal message queue that holds messages received by the server.
 
         """
         self.sock = sock
         if username and password:
-            frame = self.build_frame({"command": "CONNECT", 
+            frame = self.build_frame({"command": "CONNECT",
                                       "headers": {'login': username,
                                                   'passcode': password}})
         else:
         if 'content-length' in headers:
             headers['bytes_message'] = True
 
+        if command == 'ERROR':
+            raise BrokerErrorResponse(
+                    "Broker Returned Error: %s" % body)
+
         frame = Frame(self.sock)
         return frame.build_frame({'command': command,
                                   'headers': headers,
         # There may be a left over newline
         # RabbitMQ doesn't have a newline after \x00
         # ActiveMQ does.  This is a hack around that.
-        # http://stomp.codehaus.org/Protocol mentions 
+        # http://stomp.codehaus.org/Protocol mentions
         # nothing about a newline following the NULL (^@)
         if buffer[:1] == '\n':
             return buffer[1:-1]

File stompy/simple.py

View file
         if frame is None and not block:
             raise self.Empty()
         return frame
-    
+
     def get_nowait(self):
         """Remove and return an item from the queue without blocking.
-    
+
         Only get an item if one is immediately available. Otherwise
         raise the :exc:`Empty` exception.
 
                                persistent=persistent)
 
         return self.stomp.send(conf)
-    
+
     def connect(self, username=None, password=None):
         """Connect to the broker.
 
         :keyword username: Username for connection
         :keyword password: Password for connection
 
-        :raises :exc:`stompy.stomp.ConnectionError`: if the connection was unsuccessful.
-        :raises :exc:`stompy.stomp.ConnectionTimeoutError`: if the connection timed out.
+        :raises :exc:`stompy.stomp.ConnectionError`:
+            if the connection was unsuccessful.
+        :raises :exc:`stompy.stomp.ConnectionTimeoutError`:
+            if the connection timed out.
 
         """
         self.stomp.connect(username=username, password=password)
 
     def unsubscribe(self, destination, conf=None):
         """Unsubscribe from topic/queue previously subscribed to.
-       
+
         :param destination: The destination queue/topic to unsubscribe from.
         :keyword conf: Additional headers to send with the unsubscribe
             request.
         """
         conf = self._make_conf(conf, destination=destination)
         return self.stomp.unsubscribe(conf)
-    
+
     def begin(self, transaction):
         """Begin transaction.
-       
+
         Every :meth:`ack` and :meth:`send` will be affected by this
         transaction and won't be real until a :meth:`commit` is issued.
         To roll-back any changes since the transaction started use
             raise TransactionError("Not in transaction")
         self.stomp.commit({"transaction": self._current_transaction})
         self._current_transaction = None
-    
 
     def abort(self):
         """Roll-back current transaction."""
 
     def ack(self, frame):
         """Acknowledge message.
-        
+
         :param frame: The message to acknowledge.
-        
+
         """
         return self.stomp.ack(frame)
 

File tests/test_frame.py

View file
 import sys
 import socket
 from stompy import frame
-from stompy.frame import Frame, IntermediateMessageQueue, UnknownBrokerResponseError
+from stompy.frame import Frame, IntermediateMessageQueue, \
+        UnknownBrokerResponseError, BrokerErrorResponse
 from Queue import Empty as QueueEmpty
 
 
         self.frame._getline = Dingus()
         self.frame._getline.return_value = \
             'CONNECTED\nsession:ID:nose-session123\n\n\x00\n'
-        self.frame.connect(self.sockobj.connect('localhost', 99999), 
+        self.frame.connect(self.sockobj.connect('localhost', 99999),
                                                 username="test",
                                                 password="test")
         sendall = self.frame.sock.calls('sendall', DontCare).one().args[0]
 
         assert self.frame.session is not None
         assert 'CONNECT' in sendall
- 
+
 
 class WhenSendingFrames(DingusTestCase(Frame)):
 
         assert 'content-length:%i' % len(body) in this_frame.as_string()
 
 
-class WhenUsingIntermediateMQueue(DingusTestCase(IntermediateMessageQueue, 'Queue', 'QueueEmpty')):
-    
+class WhenUsingIntermediateMQueue(DingusTestCase(IntermediateMessageQueue,
+    'Queue', 'QueueEmpty')):
+
     def setup(self):
         super(WhenUsingIntermediateMQueue, self).setup()
         self.queue = IntermediateMessageQueue()
         self.frame = Frame()
         self.frame.sock = Dingus()
- 
+
     def should_put_into_queue_and_get(self):
         headers = {'destination': '/queue/nose_test',
                    'persistent': 'true',
                    'persistent': 'true',
                    'bytes_message': 'true'}
         body = 'Testing'
- 
+
         this_frame = self.frame.build_frame({'command': 'SEND',
                                              'headers': headers,
                                              'body': body})
         my_frame._getline = Dingus()
         command = 'MESSAGE'
         body = 'Test 1'
-        headers = {'session':'ID:nose-session123',
-                   'content-length':'%d' %len(body)}
+        headers = {'session': 'ID:nose-session123',
+                   'content-length': '%d' %len(body)}
         my_frame.parse_frame = Dingus()
         this_frame = my_frame.build_frame({'command': command,
                                            'headers': headers,
         my_frame.parse_frame.return_value = this_frame
         my_frame.rqueue.put_nowait(my_frame)
         ret_frame = my_frame.get_reply(nb=True)
-        assert isinstance(ret_frame, Frame) 
+        assert isinstance(ret_frame, Frame)
 
     def should_not_get_reply(self):
         my_frame = Frame()
         assert ret_frame is None
 
 
-
-class WhenParsingFrames(DingusTestCase(Frame,"UnknownBrokerResponseError")):
+class WhenParsingFrames(DingusTestCase(Frame, "UnknownBrokerResponseError",
+        "BrokerErrorResponse")):
 
     def setup(self):
         super(WhenParsingFrames, self).setup()
         my_frame._getline.return_value = \
                 'RECEIPTreceipt-id:ID:nose-receipt123'
 
-        nose_tools.assert_raises(UnknownBrokerResponseError, my_frame.parse_frame) 
+        nose_tools.assert_raises(UnknownBrokerResponseError,
+            my_frame.parse_frame)
+
+    def should_get_error_from_broker(self):
+        my_frame = Frame()
+        my_frame._getline = Dingus()
+        command = 'ERROR'
+        header = 'message:Illegal command'
+        body = 'Error Message'
+        my_frame._getline.return_value = \
+            '%s\n%s\ncontent-length:%d\n\n%s\n\x00' % (command,
+                                                       header,
+                                                       len(body),
+                                                       body)
+
+        nose_tools.assert_raises(BrokerErrorResponse, my_frame.parse_frame)
 
     def should_return_frame_repr(self):
         my_frame = Frame()

File tests/test_simple.py

View file
 #!/usr/bin/env python
 from dingus import Dingus, DingusTestCase, DontCare
-import nose.tools as nose_tools                                                                                               
+import nose.tools as nose_tools
 import sys
 import socket
 from stompy import simple
 from stompy.simple import Client, TransactionError
 
-class WhenUsingSimpleClient(DingusTestCase(Client, 'TransactionError', 'Empty')):
+
+class WhenUsingSimpleClient(DingusTestCase(Client, 'TransactionError',
+    'Empty')):
 
     def setup(self):
         super(WhenUsingSimpleClient, self).setup()
 
     def should_connect(self):
         self.client.connect()
-        assert self.client.stomp.calls('connect') 
+        assert self.client.stomp.calls('connect')
 
     def should_disconnect(self):
         self.client.disconnect()
     def should_subscribe(self):
         self.client.subscribe('/queue/nose_test')
         print self.client.stomp.calls
-        assert self.client.stomp.calls('subscribe', 
-                {'ack':'auto','destination':'/queue/nose_test'})
+        assert self.client.stomp.calls('subscribe',
+                {'ack': 'auto', 'destination': '/queue/nose_test'})
 
     def should_unsubscribe(self):
         self.client.unsubscribe('/queue/nose_test')
-        assert self.client.stomp.calls('unsubscribe', 
+        assert self.client.stomp.calls('unsubscribe',
                 {'destination': '/queue/nose_test'})
 
     def should_begin_transaction(self):
         self.client.begin('bah')
-        assert self.client.stomp.calls('begin', {"transaction": self.client._current_transaction})
+        assert self.client.stomp.calls('begin',
+            {"transaction": self.client._current_transaction})
 
     def should_fail_to_begin_already_in_transaction(self):
         self.client._current_transaction = "meh"
         assert self.client.stomp.calls('ack', "fake_frame")
 
     def should_make_conf(self):
-        conf = self.client._make_conf(None, destination='/queue/nose_test', ack='auto')
+        conf = self.client._make_conf(None,
+            destination='/queue/nose_test', ack='auto')
         assert isinstance(conf, type({}))
 
     def should_make_conf_with_transaction(self):
         self.client._current_transaction = 'meh'
-        conf = self.client._make_conf({}, destination='/queue/nose_test', ack='auto')
+        conf = self.client._make_conf({},
+            destination='/queue/nose_test', ack='auto')
         assert isinstance(conf, type({}))
 
     def should_put_item_into_queue(self):
         self.client.put('bah', '/queue/nose_test')
-        conf = self.client._make_conf(None, body='bah', destination='/queue/nose_test',
-                                      persistent='true')
+        conf = self.client._make_conf(None, body='bah',
+            destination='/queue/nose_test',
+            persistent='true')
 
         assert self.client.stomp.calls('send', conf)
 
 
     def should_not_get_message(self):
         self.client.stomp.receive_frame.return_value = None
-        nose_tools.assert_raises(self.client.Empty, self.client.get, block=False) 
+        nose_tools.assert_raises(self.client.Empty,
+            self.client.get, block=False)

File tests/test_stomp.py

View file
 
     def should_raise_not_connected_error(self):
         self.stomp.disconnect()
-        
+
 
 class WhenProducingMessages(DingusTestCase(Stomp)):
 
         mystomp.disconnect()
         assert not mystomp.connected
 
+
 class WhenSocketCantConnect(TestCase):
 
     def should_fail_connect(self):
         import socket
         socket.setdefaulttimeout(.5)
         self.stomp = Stomp('10.10.0.0', 99999)
-        self.failUnlessRaises(self.stomp.ConnectionTimeoutError, self.stomp.connect)
+        self.failUnlessRaises(self.stomp.ConnectionTimeoutError,
+            self.stomp.connect)