← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wallyworld/launchpad/enum-serializable-972998 into lp:launchpad

 

Ian Booth has proposed merging lp:~wallyworld/launchpad/enum-serializable-972998 into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #972998 in Launchpad itself: "TypeError: <DBItem InformationType> is not JSON serializable"
  https://bugs.launchpad.net/launchpad/+bug/972998

For more details, see:
https://code.launchpad.net/~wallyworld/launchpad/enum-serializable-972998/+merge/102639

== Implementation ==

This branch requires an updated lazr.enum egg (1.1.4) and a new lazr.json egg (0.1). These provide the core infrastructure needed. The change in this branch simply use the json serialisation support in those eggs when it sends stuff to/from rabbit.

== Tests ==

Add new test to TestRabbitQueue
- test_complex_objcts

== Lint ==

Checking for conflicts and issues in changed files.

Linting changed files:
  setup.py
  versions.cfg
  lib/lp/services/messaging/rabbit.py
  lib/lp/services/messaging/tests/test_rabbit.py

-- 
https://code.launchpad.net/~wallyworld/launchpad/enum-serializable-972998/+merge/102639
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wallyworld/launchpad/enum-serializable-972998 into lp:launchpad.
=== modified file 'lib/lp/services/messaging/rabbit.py'
--- lib/lp/services/messaging/rabbit.py	2011-12-29 05:29:36 +0000
+++ lib/lp/services/messaging/rabbit.py	2012-04-19 06:59:18 +0000
@@ -19,6 +19,10 @@
 import time
 
 from amqplib import client_0_8 as amqp
+from lazr.json import (
+    custom_type_decoder,
+    CustomTypeEncoder,
+    )
 import transaction
 from transaction._transaction import Status as TransactionStatus
 from zope.interface import implements
@@ -247,7 +251,7 @@
 
     def sendNow(self, data):
         """Immediately send a message to the broker."""
-        json_data = json.dumps(data)
+        json_data = json.dumps(data, cls=CustomTypeEncoder)
         msg = amqp.Message(json_data)
         self.channel.basic_publish(
             exchange=self.session.exchange,
@@ -280,7 +284,8 @@
                     time.sleep(0.1)
                 else:
                     self.channel.basic_ack(message.delivery_tag)
-                    return json.loads(message.body)
+                    return json.loads(
+                        message.body, object_hook=custom_type_decoder)
             except amqp.AMQPChannelException, error:
                 if error.amqp_reply_code == 404:
                     raise QueueNotFound()

=== modified file 'lib/lp/services/messaging/tests/test_rabbit.py'
--- lib/lp/services/messaging/tests/test_rabbit.py	2012-01-01 02:58:52 +0000
+++ lib/lp/services/messaging/tests/test_rabbit.py	2012-04-19 06:59:18 +0000
@@ -9,6 +9,10 @@
 from itertools import count
 import thread
 
+from lazr.enum import (
+    DBEnumeratedType,
+    DBItem,
+    )
 from testtools.testcase import ExpectedException
 import transaction
 from transaction._transaction import Status as TransactionStatus
@@ -364,6 +368,25 @@
         routing_key.associateConsumerNow(consumer)
         self.assertRaises(QueueEmpty, consumer.receive, timeout=2)
 
+    def test_complex_objcts(self):
+        # Test that objects using custom json encoders and decoders are able to
+        # be sent and received. We'll use a lazr.enum since the lazr.json
+        # library supports those out-of-the-box.
+        consumer = RabbitQueue(global_session, next(queue_names))
+        routing_key = RabbitRoutingKey(global_session, next(key_names))
+        routing_key.associateConsumerNow(consumer)
+
+        class SomeEnumType(DBEnumeratedType):
+            A = DBItem(1, "A", "Item A")
+            B = DBItem(2, "B", "Item B")
+
+        for sent in [SomeEnumType.A, SomeEnumType.B]:
+            routing_key.sendNow(sent)
+            self.assertEqual(sent, consumer.receive(timeout=2))
+
+        # All the messages received were consumed.
+        self.assertRaises(QueueEmpty, consumer.receive, timeout=2)
+
     def test_does_not_connect_session_immediately(self):
         # RabbitQueue does not connect the session until necessary.
         RabbitQueue(global_session, next(queue_names))

=== modified file 'setup.py'
--- setup.py	2012-03-14 16:32:59 +0000
+++ setup.py	2012-04-19 06:59:18 +0000
@@ -45,6 +45,7 @@
         'lazr.config',
         'lazr.delegates',
         'lazr.enum',
+        'lazr.json',
         'lazr.lifecycle',
         'lazr.restful',
         'lazr.jobrunner',

=== modified file 'versions.cfg'
--- versions.cfg	2012-04-16 03:38:00 +0000
+++ versions.cfg	2012-04-19 06:59:18 +0000
@@ -41,8 +41,9 @@
 lazr.batchnavigator = 1.2.10
 lazr.config = 1.1.3
 lazr.delegates = 1.2.0
-lazr.enum = 1.1.3
+lazr.enum = 1.1.4
 lazr.jobrunner = 0.2
+lazr.json = 0.1
 lazr.lifecycle = 1.1
 lazr.restful = 0.19.6
 lazr.restfulclient = 0.12.2


Follow ups