[Patchew-devel] [PATCH v3] rest: POST for message endpoint

Shubham Jain posted 1 patch 5 years, 11 months ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/patchew-ci tags/patchew/20180507195553.51784-1-shubhamjain7495@gmail.com
api/models.py      |  40 +++++++++++---
api/rest.py        |  20 ++++---
tests/test_rest.py | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 197 insertions(+), 17 deletions(-)
[Patchew-devel] [PATCH v3] rest: POST for message endpoint
Posted by Shubham Jain 5 years, 11 months ago
This commit allows to create/POST message from browser
- Add "create" method to MessageManager so that it calls save_mbox()
- Add getter and setter for mbox
- Rename the existing "mbox" field to e.g. "mbox_blob"
- Fix nested writable serializer issue

Message-Id: <20180505070956.6665-1-shubhamjain7495@gmail.com>
---
 api/models.py      |  40 +++++++++++---
 api/rest.py        |  20 ++++---
 tests/test_rest.py | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 197 insertions(+), 17 deletions(-)

diff --git a/api/models.py b/api/models.py
index 504f2c7..a97c217 100644
--- a/api/models.py
+++ b/api/models.py
@@ -247,6 +247,25 @@ class MessageManager(models.Manager):
             self.delete_subthread(r)
         msg.delete()
 
+    def create(self,project, **validated_data):
+        mbox = validated_data.pop('mbox')
+        m = MboxMessage(mbox)
+        msg = Message(**validated_data)
+        if 'in_reply_to' not in validated_data:
+            msg.in_reply_to = m.get_in_reply_to() or ""
+        msg.stripped_subject = m.get_subject(strip_tags=True)
+        msg.version = m.get_version()
+        msg.prefixes = m.get_prefixes()
+        msg.is_series_head = m.is_series_head()
+        msg.is_patch = m.is_patch()
+        msg.patch_num = m.get_num()[0]
+        msg.project = project
+        msg.mbox = mbox
+        msg.save_mbox(mbox)
+        msg.save()
+        emit_event("MessageAdded", message=msg)
+        return msg
+
     def add_message_from_mbox(self, mbox, user, project_name=None):
 
         def find_message_projects(m):
@@ -321,20 +340,25 @@ class Message(models.Model):
 
     objects = MessageManager()
 
-    def save_mbox(self, mbox):
-        save_blob(mbox, self.message_id)
+    def save_mbox(self, mbox_blob):
+        save_blob(mbox_blob, self.message_id)
 
     def get_mbox_obj(self):
         self.get_mbox()
         return self._mbox_obj
 
     def get_mbox(self):
-        if hasattr(self, "mbox"):
-            return self.mbox
-        self.mbox = load_blob(self.message_id)
-        self._mbox_obj = MboxMessage(self.mbox)
-        return self.mbox
-
+        if hasattr(self, "mbox_blob"):
+            return self.mbox_blob
+        self.mbox_blob = load_blob(self.message_id)
+        self._mbox_obj = MboxMessage(self.mbox_blob)
+        return self.mbox_blob
+    
+    mbox = property(get_mbox)
+    @mbox.setter
+    def mbox(self,value):
+        self.mbox_blob = value
+    
     def get_num(self):
         assert self.is_patch or self.is_series_head
         cur, total = 1, 1
diff --git a/api/rest.py b/api/rest.py
index fc10b46..73fe2e6 100644
--- a/api/rest.py
+++ b/api/rest.py
@@ -140,9 +140,13 @@ class BaseMessageSerializer(serializers.ModelSerializer):
         fields = ('resource_uri', 'message_id', 'subject', 'date', 'sender', 'recipients')
 
     resource_uri = HyperlinkedMessageField(view_name='messages-detail')
-
     recipients = AddressSerializer(many=True)
     sender = AddressSerializer()
+   
+    def create(self, validated_data):
+        validated_data['recipients'] = self.fields['recipients'].create(validated_data['recipients'])
+        validated_data['sender'] = self.fields['sender'].create(validated_data['sender'])
+        return Message.objects.create(project=self.context['project'], **validated_data)
 
 # a message_id is *not* unique, so we can only list
 class BaseMessageViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
@@ -156,7 +160,11 @@ class BaseMessageViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
 class ProjectMessagesViewSetMixin(mixins.RetrieveModelMixin):
     def get_queryset(self):
         return self.queryset.filter(project=self.kwargs['projects_pk'])
-
+    def get_serializer_context(self):
+        try:
+            return {'project': Project.objects.get(id=self.kwargs['projects_pk']), 'request': self.request}
+        except: 
+            return Http404
 # Series
 
 class ReplySerializer(BaseMessageSerializer):
@@ -287,10 +295,7 @@ class MessageSerializer(BaseMessageSerializer):
     class Meta:
         model = Message
         fields = BaseMessageSerializer.Meta.fields + ('mbox', )
-
-    def get_mbox(self, obj):
-        return obj.get_mbox()
-    mbox = SerializerMethodField()
+    mbox = CharField()
 
     def get_fields(self):
         fields = super(MessageSerializer, self).get_fields()
@@ -312,9 +317,8 @@ class StaticTextRenderer(renderers.BaseRenderer):
             return data
 
 class MessagesViewSet(ProjectMessagesViewSetMixin,
-                      BaseMessageViewSet):
+                      BaseMessageViewSet, mixins.CreateModelMixin):
     serializer_class = MessageSerializer
-
     @detail_route(renderer_classes=[StaticTextRenderer])
     def mbox(self, request, *args, **kwargs):
         message = self.get_object()
diff --git a/tests/test_rest.py b/tests/test_rest.py
index 21bc2b9..c8024e2 100755
--- a/tests/test_rest.py
+++ b/tests/test_rest.py
@@ -18,7 +18,7 @@ from patchewtest import PatchewTestCase, main
 from api.models import Message
 from api.rest import AddressSerializer
 from collections import OrderedDict
-
+import json
 class RestTest(PatchewTestCase):
     def setUp(self):
         self.create_superuser()
@@ -256,6 +256,158 @@ class RestTest(PatchewTestCase):
         self.assertEqual(resp_after.status_code, 404)
         self.assertEqual(resp_reply_after.status_code, 404)
 
+    def test_create_message(self):
+        data = {
+                "message_id": "20171023201055.21973-11-andrew.smirnov@gmail.com",
+                "subject": "[Qemu-devel] [PATCH v2 10/27] imx_fec: Reserve full 4K "
+                           "page for the register file",
+                "date": "2017-10-23T20:10:38",
+                "sender": {
+                    "name": "Andrey Smirnov",
+                    "address": "andrew.smirnov@gmail.com"
+                },
+                "recipients": [
+                    {
+                    "address": "qemu-arm@nongnu.org"
+                     },
+                    {
+                    "name": "Peter Maydell",
+                    "address": "peter.maydell@linaro.org"
+                    },
+                    {
+                    "name": "Andrey Smirnov",
+                    "address": "andrew.smirnov@gmail.com"
+                    },
+                    {
+                    "name": "Jason Wang",
+                    "address": "jasowang@redhat.com"
+                    },
+                    {
+                    "name": "Philippe Mathieu-Daudé",
+                    "address": "f4bug@amsat.org"
+                    },
+                    {
+                    "address": "qemu-devel@nongnu.org"
+                    },
+                    {
+                    "address": "yurovsky@gmail.com"
+                    }
+                ],
+                "mbox": "From andrew.smirnov@gmail.com Mon Oct 23 20:10:38 2017\nDelivered"
+                        "-To: importer@patchew.org\nReceived-SPF: temperror (zoho.com: Err"
+                        "or in retrieving data from DNS) client-ip=208.118.235.17; envelop"
+                        "e-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=l"
+                        "ists.gnu.org;\nAuthentication-Results: mx.zohomail.com;\n\tdkim=f"
+                        "ail;\n\tspf=temperror (zoho.com: Error in retrieving data from DN"
+                        "S)  smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu."
+                        "org\nReturn-Path: <qemu-devel-bounces+importer=patchew.org@nongnu"
+                        ".org>\nReceived: from lists.gnu.org (208.118.235.17 [208.118.235."
+                        "17]) by mx.zohomail.com\n\twith SMTPS id 1508790023478635.2925706"
+                        "919272; Mon, 23 Oct 2017 13:20:23 -0700 (PDT)\nReceived: from loc"
+                        "alhost ([::1]:40414 helo=lists.gnu.org)\n\tby lists.gnu.org with "
+                        "esmtp (Exim 4.71)\n\t(envelope-from <qemu-devel-bounces+importer="
+                        "patchew.org@nongnu.org>)\n\tid 1e6jCo-0007Cr-Ed\n\tfor importer@p"
+                        "atchew.org; Mon, 23 Oct 2017 16:20:14 -0400\nReceived: from eggs."
+                        "gnu.org ([2001:4830:134:3::10]:46254)\n\tby lists.gnu.org with es"
+                        "mtp (Exim 4.71)\n\t(envelope-from <andrew.smirnov@gmail.com>) id "
+                        "1e6j4M-0000Ia-AF\n\tfor qemu-devel@nongnu.org; Mon, 23 Oct 2017 1"
+                        "6:11:32 -0400\nReceived: from Debian-exim by eggs.gnu.org with sp"
+                        "am-scanned (Exim 4.71)\n\t(envelope-from <andrew.smirnov@gmail.co"
+                        "m>) id 1e6j4L-0002WU-ES\n\tfor qemu-devel@nongnu.org; Mon, 23 Oct"
+                        " 2017 16:11:30 -0400\nReceived: from mail-pf0-x241.google.com ([2"
+                        "607:f8b0:400e:c00::241]:47361)\n\tby eggs.gnu.org with esmtps (TL"
+                        "S1.0:RSA_AES_128_CBC_SHA1:16)\n\t(Exim 4.71) (envelope-from <andr"
+                        "ew.smirnov@gmail.com>)\n\tid 1e6j4J-0002VQ-5h; Mon, 23 Oct 2017 1"
+                        "6:11:27 -0400\nReceived: by mail-pf0-x241.google.com with SMTP id"
+                        " z11so17896780pfk.4;\n\tMon, 23 Oct 2017 13:11:27 -0700 (PDT)\nRe"
+                        "ceived: from squirtle.westlake.spaceflightindustries.com ([173.22"
+                        "6.206.194])\n\tby smtp.gmail.com with ESMTPSA id\n\tj1sm15181623p"
+                        "fj.108.2017.10.23.13.11.24\n\t(version=TLS1_2 cipher=ECDHE-RSA-CH"
+                        "ACHA20-POLY1305 bits=256/256);\n\tMon, 23 Oct 2017 13:11:25 -0700"
+                        " (PDT)\nDKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=g"
+                        "mail.com; s=20161025;\n\th=from:to:cc:subject:date:message-id:in-"
+                        "reply-to:references\n\t:mime-version:content-transfer-encoding;\n"
+                        "\tbh=zmFol33kPLVHCkj7Ro+lVg1LTAQod/G9dNqJXtckibI=;\n\tb=D49+KCtse"
+                        "bdshdA2kxqNqCWLEOTSRXI61CbfBrS3YYbGspt/3vTIRCLSKNhICr2UOc\n\t7BhL"
+                        "XRtMKhn2gomHPqqSHOSp+hB5XtMmBNpBpkQyXMHoGkgmjg0IIF02Vzn4i2QzP8C9"
+                        "\n\t0SDZb6VYnz70J5HY0KZwVfQ+Rc5qgJEfcTHzuzZ4qHcbXxPHYCGYo1yDG6bEU"
+                        "LNp2sRB\n\tGekoCKine5V1Uc+8aKmIeQA3zTXj2BLYqIQFi3UdiEemj94Gs3UFkE"
+                        "kV3kTtCBwBVYep\n\tCvtbjBMI4Kb2Rcyb7taNS1PwjoXo4nzyPqSftf5CtxE3FYQ"
+                        "6pSHkU8H1cqi4os4RgACQ\n\t6rrA==\nX-Google-DKIM-Signature: v=1; a="
+                        "rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x"
+                        "-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to"
+                        "\n\t:references:mime-version:content-transfer-encoding;\n\tbh=zmF"
+                        "ol33kPLVHCkj7Ro+lVg1LTAQod/G9dNqJXtckibI=;\n\tb=kG94Z4+JpBMpVNtWI"
+                        "ASASHAaqcxeUgqF149vlfmPjsUsUZoE69zK/Xq8lz25p+TskP\n\tu+sFtsuT//gI"
+                        "M/gFEeFYPBUEECFh+cSu6vYqjvy7W+o1dt0CkQS0K4sG2a6PDeXTc7Dw\n\tYOmEE"
+                        "gzEW+JtEp27yE8L5Yiur7k9cMnq6AGsLtrNa4leHN8KfnBLpZDJ1w2BTVAST/Mt\n"
+                        "\tp5OmcBALM2s2PfVxV2AqFIC03+BUkFo78Yl0dJkT95uUWQvXOrYnhrJGikBOpxf"
+                        "e2GEl\n\tdX/N0knNvw1ILQigiiD7mTg2pWBXXdi9ncxWFbWGav3NFgMuMj9Le7dh"
+                        "Merg+f0Pqzqq\n\tuMRw==\nX-Gm-Message-State: AMCzsaVtdnaUNbjj5huOS"
+                        "I8ibhSVAiVnF57PiIS4oVle1IVoBcH6i/W4\n\tsAtvFi/nF5bYIYfQxgZMU93rvm"
+                        "Mn\nX-Google-Smtp-Source: ABhQp+Tw1GtSPaSw51tZkI3AfiuyluStPI8C5/3"
+                        "esBqFkirOMfsjtlRNoBcr8lgEf/55RwhQLiI5mQ==\nX-Received: by 10.98.6"
+                        "5.218 with SMTP id g87mr14269292pfd.105.1508789486104;\n\tMon, 23"
+                        " Oct 2017 13:11:26 -0700 (PDT)\nFrom: Andrey Smirnov <andrew.smir"
+                        "nov@gmail.com>\nTo: qemu-arm@nongnu.org\nDate: Mon, 23 Oct 2017 1"
+                        "3:10:38 -0700\nMessage-Id: <20171023201055.21973-11-andrew.smirno"
+                        "v@gmail.com>\nX-Mailer: git-send-email 2.13.5\nIn-Reply-To: <2017"
+                        "1023201055.21973-1-andrew.smirnov@gmail.com>\nReferences: <201710"
+                        "23201055.21973-1-andrew.smirnov@gmail.com>\nMIME-Version: 1.0\nCo"
+                        "ntent-Type: text/plain; charset=\"utf-8\"\nContent-Transfer-Encod"
+                        "ing: base64\nX-detected-operating-system: by eggs.gnu.org: Genre "
+                        "and OS details not\n\trecognized.\nX-Received-From: 2607:f8b0:400"
+                        "e:c00::241\nSubject: [Qemu-devel] [PATCH v2 10/27] imx_fec: Reser"
+                        "ve full 4K page for the\n register file\nX-BeenThere: qemu-devel@"
+                        "nongnu.org\nX-Mailman-Version: 2.1.21\nPrecedence: list\nList-Id:"
+                        " <qemu-devel.nongnu.org>\nList-Unsubscribe: <https://lists.nongnu"
+                        ".org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@n"
+                        "ongnu.org?subject=unsubscribe>\nList-Archive: <http://lists.nongn"
+                        "u.org/archive/html/qemu-devel/>\nList-Post: <mailto:qemu-devel@no"
+                        "ngnu.org>\nList-Help: <mailto:qemu-devel-request@nongnu.org?subje"
+                        "ct=help>\nList-Subscribe: <https://lists.nongnu.org/mailman/listi"
+                        "nfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject"
+                        "=subscribe>\nCc: Peter Maydell <peter.maydell@linaro.org>,\n\tAnd"
+                        "rey Smirnov <andrew.smirnov@gmail.com>,\n\tJason Wang <jasowang@r"
+                        "edhat.com>,\n\t=?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <f4bug@a"
+                        "msat.org>,\n\tqemu-devel@nongnu.org, yurovsky@gmail.com\nErrors-T"
+                        "o: qemu-devel-bounces+importer=patchew.org@nongnu.org\nSender: \""
+                        "Qemu-devel\" <qemu-devel-bounces+importer=patchew.org@nongnu.org>"
+                        "\nX-ZohoMail-DKIM: fail (Header signature does not verify)\nX-Zoh"
+                        "oMail: RDKM_2  RSF_6  Z_629925259 SPT_0\n\nU29tZSBpLk1YIFNvQ3MgKG"
+                        "UuZy4gaS5NWDcpIGhhdmUgRkVDIHJlZ2lzdGVycyBnb2luZyBhcyBm\nYXIgYXMgb"
+                        "2Zmc2V0CjB4NjE0LCBzbyB0byBhdm9pZCBnZXR0aW5nIGFib3J0cyB3aGVuIGFjY2"
+                        "Vz\nc2luZyB0aG9zZSBvbiBRRU1VLCBleHRlbmQKdGhlIHJlZ2lzdGVyIGZpbGUgd"
+                        "G8gY292ZXIgNEtC\nIG9mIGFkZHJlc3Mgc3BhY2UgaW5zdGVhZCBvZiBqdXN0IDFL"
+                        "LgoKQ2M6IFBldGVyIE1heWRlbGwg\nPHBldGVyLm1heWRlbGxAbGluYXJvLm9yZz4"
+                        "KQ2M6IEphc29uIFdhbmcgPGphc293YW5nQHJlZGhh\ndC5jb20+CkNjOiBQaGlsaX"
+                        "BwZSBNYXRoaWV1LURhdWTDqSA8ZjRidWdAYW1zYXQub3JnPgpDYzog\ncWVtdS1kZ"
+                        "XZlbEBub25nbnUub3JnCkNjOiBxZW11LWFybUBub25nbnUub3JnCkNjOiB5dXJvdn"
+                        "Nr\neUBnbWFpbC5jb20KU2lnbmVkLW9mZi1ieTogQW5kcmV5IFNtaXJub3YgPGFuZ"
+                        "HJldy5zbWlybm92\nQGdtYWlsLmNvbT4KLS0tCiBody9uZXQvaW14X2ZlYy5jIHwg"
+                        "MiArLQogMSBmaWxlIGNoYW5nZWQs\nIDEgaW5zZXJ0aW9uKCspLCAxIGRlbGV0aW9"
+                        "uKC0pCgpkaWZmIC0tZ2l0IGEvaHcvbmV0L2lteF9m\nZWMuYyBiL2h3L25ldC9pbX"
+                        "hfZmVjLmMKaW5kZXggNDhkMDEyY2FkNi4uZTIzNmJjOTMzYyAxMDA2\nNDQKLS0tI"
+                        "GEvaHcvbmV0L2lteF9mZWMuYworKysgYi9ody9uZXQvaW14X2ZlYy5jCkBAIC0xMj"
+                        "Uy\nLDcgKzEyNTIsNyBAQCBzdGF0aWMgdm9pZCBpbXhfZXRoX3JlYWxpemUoRGV2a"
+                        "WNlU3RhdGUgKmRl\ndiwgRXJyb3IgKiplcnJwKQogICAgIFN5c0J1c0RldmljZSAq"
+                        "c2JkID0gU1lTX0JVU19ERVZJQ0Uo\nZGV2KTsKIAogICAgIG1lbW9yeV9yZWdpb25"
+                        "faW5pdF9pbygmcy0+aW9tZW0sIE9CSkVDVChkZXYp\nLCAmaW14X2V0aF9vcHMsIH"
+                        "MsCi0gICAgICAgICAgICAgICAgICAgICAgICAgIFRZUEVfSU1YX0ZF\nQywgMHg0M"
+                        "DApOworICAgICAgICAgICAgICAgICAgICAgICAgICBUWVBFX0lNWF9GRUMsIDB4MT"
+                        "Aw\nMCk7CiAgICAgc3lzYnVzX2luaXRfbW1pbyhzYmQsICZzLT5pb21lbSk7CiAgI"
+                        "CAgc3lzYnVzX2lu\naXRfaXJxKHNiZCwgJnMtPmlycVswXSk7CiAgICAgc3lzYnVz"
+                        "X2luaXRfaXJxKHNiZCwgJnMtPmly\ncVsxXSk7Ci0tIAoyLjEzLjUKCgo=\n\n"
+                }
+             
+        resp = self.api_client.post(self.PROJECT_BASE + "messages/", json.dumps(data), content_type='application/json')
+        self.assertEqual(resp.status_code,201)
+        resp_get = self.api_client.get(self.PROJECT_BASE + "messages/20171023201055.21973-11-andrew.smirnov@gmail.com/")
+        self.assertEqual(resp_get.status_code,200)
+        self.assertEqual(resp.data['subject'],"[Qemu-devel] [PATCH v2 10/27] imx_fec: Reserve full 4K "
+                        "page for the register file")
+
+
     def test_message(self):
         series = self.apply_and_retrieve('0001-simple-patch.mbox.gz',
                                          self.p.id, '20160628014747.20971-1-famz@redhat.com')
-- 
2.14.3 (Apple Git-98)

_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
Re: [Patchew-devel] [PATCH v3] rest: POST for message endpoint
Posted by Fam Zheng 5 years, 11 months ago
On Tue, 05/08 01:25, Shubham Jain wrote:
> This commit allows to create/POST message from browser
> - Add "create" method to MessageManager so that it calls save_mbox()
> - Add getter and setter for mbox
> - Rename the existing "mbox" field to e.g. "mbox_blob"

This can be a separate patch, next time.

> - Fix nested writable serializer issue
> 
> Message-Id: <20180505070956.6665-1-shubhamjain7495@gmail.com>

I think you want the Signed-off-by: line rather than the Message-Id: one. In
Patchew we don't have a hard requirement for Signed-off-by so it is okay to omit
it, but Message-Id tags are usually only added when merging a patch (git am -m).

> ---

Under this "---" line, please add "what is different in v3 from v2", aka patch
revision history.  Or you could write that in the commit message, following a
--- line after Signed-off-by and other tag lines.

>  api/models.py      |  40 +++++++++++---
>  api/rest.py        |  20 ++++---
>  tests/test_rest.py | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 197 insertions(+), 17 deletions(-)
> 
> diff --git a/api/models.py b/api/models.py
> index 504f2c7..a97c217 100644
> --- a/api/models.py
> +++ b/api/models.py
> @@ -247,6 +247,25 @@ class MessageManager(models.Manager):
>              self.delete_subthread(r)
>          msg.delete()
>  
> +    def create(self,project, **validated_data):

s/self,project/self, project/

> +        mbox = validated_data.pop('mbox')
> +        m = MboxMessage(mbox)
> +        msg = Message(**validated_data)
> +        if 'in_reply_to' not in validated_data:
> +            msg.in_reply_to = m.get_in_reply_to() or ""
> +        msg.stripped_subject = m.get_subject(strip_tags=True)
> +        msg.version = m.get_version()
> +        msg.prefixes = m.get_prefixes()
> +        msg.is_series_head = m.is_series_head()
> +        msg.is_patch = m.is_patch()
> +        msg.patch_num = m.get_num()[0]
> +        msg.project = project
> +        msg.mbox = mbox
> +        msg.save_mbox(mbox)
> +        msg.save()
> +        emit_event("MessageAdded", message=msg)
> +        return msg
> +
>      def add_message_from_mbox(self, mbox, user, project_name=None):
>  
>          def find_message_projects(m):
> @@ -321,20 +340,25 @@ class Message(models.Model):
>  
>      objects = MessageManager()
>  
> -    def save_mbox(self, mbox):
> -        save_blob(mbox, self.message_id)
> +    def save_mbox(self, mbox_blob):
> +        save_blob(mbox_blob, self.message_id)
>  
>      def get_mbox_obj(self):
>          self.get_mbox()
>          return self._mbox_obj
>  
>      def get_mbox(self):
> -        if hasattr(self, "mbox"):
> -            return self.mbox
> -        self.mbox = load_blob(self.message_id)
> -        self._mbox_obj = MboxMessage(self.mbox)
> -        return self.mbox
> -
> +        if hasattr(self, "mbox_blob"):
> +            return self.mbox_blob
> +        self.mbox_blob = load_blob(self.message_id)
> +        self._mbox_obj = MboxMessage(self.mbox_blob)
> +        return self.mbox_blob
> +    
> +    mbox = property(get_mbox)
> +    @mbox.setter
> +    def mbox(self,value):

Should we name this method set_mbox(self)? Also a comma is missing between
"self" and "value":
       def set_mbox(self, value):

> +        self.mbox_blob = value
> +    
>      def get_num(self):
>          assert self.is_patch or self.is_series_head
>          cur, total = 1, 1
> diff --git a/api/rest.py b/api/rest.py
> index fc10b46..73fe2e6 100644
> --- a/api/rest.py
> +++ b/api/rest.py
> @@ -140,9 +140,13 @@ class BaseMessageSerializer(serializers.ModelSerializer):
>          fields = ('resource_uri', 'message_id', 'subject', 'date', 'sender', 'recipients')
>  
>      resource_uri = HyperlinkedMessageField(view_name='messages-detail')
> -
>      recipients = AddressSerializer(many=True)
>      sender = AddressSerializer()
> +   
> +    def create(self, validated_data):
> +        validated_data['recipients'] = self.fields['recipients'].create(validated_data['recipients'])
> +        validated_data['sender'] = self.fields['sender'].create(validated_data['sender'])
> +        return Message.objects.create(project=self.context['project'], **validated_data)
>  
>  # a message_id is *not* unique, so we can only list
>  class BaseMessageViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
> @@ -156,7 +160,11 @@ class BaseMessageViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
>  class ProjectMessagesViewSetMixin(mixins.RetrieveModelMixin):
>      def get_queryset(self):
>          return self.queryset.filter(project=self.kwargs['projects_pk'])
> -
> +    def get_serializer_context(self):
> +        try:
> +            return {'project': Project.objects.get(id=self.kwargs['projects_pk']), 'request': self.request}
> +        except: 
> +            return Http404
>  # Series
>  
>  class ReplySerializer(BaseMessageSerializer):
> @@ -287,10 +295,7 @@ class MessageSerializer(BaseMessageSerializer):
>      class Meta:
>          model = Message
>          fields = BaseMessageSerializer.Meta.fields + ('mbox', )
> -
> -    def get_mbox(self, obj):
> -        return obj.get_mbox()
> -    mbox = SerializerMethodField()
> +    mbox = CharField()
>  
>      def get_fields(self):
>          fields = super(MessageSerializer, self).get_fields()
> @@ -312,9 +317,8 @@ class StaticTextRenderer(renderers.BaseRenderer):
>              return data
>  
>  class MessagesViewSet(ProjectMessagesViewSetMixin,
> -                      BaseMessageViewSet):
> +                      BaseMessageViewSet, mixins.CreateModelMixin):
>      serializer_class = MessageSerializer
> -
>      @detail_route(renderer_classes=[StaticTextRenderer])
>      def mbox(self, request, *args, **kwargs):
>          message = self.get_object()
> diff --git a/tests/test_rest.py b/tests/test_rest.py
> index 21bc2b9..c8024e2 100755
> --- a/tests/test_rest.py
> +++ b/tests/test_rest.py
> @@ -18,7 +18,7 @@ from patchewtest import PatchewTestCase, main
>  from api.models import Message
>  from api.rest import AddressSerializer
>  from collections import OrderedDict
> -
> +import json

The blank line was good, please keep it if you repsin.

>  class RestTest(PatchewTestCase):
>      def setUp(self):
>          self.create_superuser()
> @@ -256,6 +256,158 @@ class RestTest(PatchewTestCase):
>          self.assertEqual(resp_after.status_code, 404)
>          self.assertEqual(resp_reply_after.status_code, 404)
>  
> +    def test_create_message(self):
> +        data = {
> +                "message_id": "20171023201055.21973-11-andrew.smirnov@gmail.com",
> +                "subject": "[Qemu-devel] [PATCH v2 10/27] imx_fec: Reserve full 4K "
> +                           "page for the register file",
> +                "date": "2017-10-23T20:10:38",
> +                "sender": {
> +                    "name": "Andrey Smirnov",
> +                    "address": "andrew.smirnov@gmail.com"
> +                },
> +                "recipients": [
> +                    {
> +                    "address": "qemu-arm@nongnu.org"
> +                     },
                       ^
                       misaligned.

> +                    {
> +                    "name": "Peter Maydell",
> +                    "address": "peter.maydell@linaro.org"
> +                    },
> +                    {
> +                    "name": "Andrey Smirnov",
> +                    "address": "andrew.smirnov@gmail.com"
> +                    },
> +                    {
> +                    "name": "Jason Wang",
> +                    "address": "jasowang@redhat.com"
> +                    },
> +                    {
> +                    "name": "Philippe Mathieu-Daudé",
> +                    "address": "f4bug@amsat.org"
> +                    },
> +                    {
> +                    "address": "qemu-devel@nongnu.org"
> +                    },
> +                    {
> +                    "address": "yurovsky@gmail.com"
> +                    }
> +                ],
> +                "mbox": "From andrew.smirnov@gmail.com Mon Oct 23 20:10:38 2017\nDelivered"
> +                        "-To: importer@patchew.org\nReceived-SPF: temperror (zoho.com: Err"
> +                        "or in retrieving data from DNS) client-ip=208.118.235.17; envelop"
> +                        "e-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=l"
> +                        "ists.gnu.org;\nAuthentication-Results: mx.zohomail.com;\n\tdkim=f"
> +                        "ail;\n\tspf=temperror (zoho.com: Error in retrieving data from DN"
> +                        "S)  smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu."
> +                        "org\nReturn-Path: <qemu-devel-bounces+importer=patchew.org@nongnu"
> +                        ".org>\nReceived: from lists.gnu.org (208.118.235.17 [208.118.235."
> +                        "17]) by mx.zohomail.com\n\twith SMTPS id 1508790023478635.2925706"
> +                        "919272; Mon, 23 Oct 2017 13:20:23 -0700 (PDT)\nReceived: from loc"
> +                        "alhost ([::1]:40414 helo=lists.gnu.org)\n\tby lists.gnu.org with "
> +                        "esmtp (Exim 4.71)\n\t(envelope-from <qemu-devel-bounces+importer="
> +                        "patchew.org@nongnu.org>)\n\tid 1e6jCo-0007Cr-Ed\n\tfor importer@p"
> +                        "atchew.org; Mon, 23 Oct 2017 16:20:14 -0400\nReceived: from eggs."
> +                        "gnu.org ([2001:4830:134:3::10]:46254)\n\tby lists.gnu.org with es"
> +                        "mtp (Exim 4.71)\n\t(envelope-from <andrew.smirnov@gmail.com>) id "
> +                        "1e6j4M-0000Ia-AF\n\tfor qemu-devel@nongnu.org; Mon, 23 Oct 2017 1"
> +                        "6:11:32 -0400\nReceived: from Debian-exim by eggs.gnu.org with sp"
> +                        "am-scanned (Exim 4.71)\n\t(envelope-from <andrew.smirnov@gmail.co"
> +                        "m>) id 1e6j4L-0002WU-ES\n\tfor qemu-devel@nongnu.org; Mon, 23 Oct"
> +                        " 2017 16:11:30 -0400\nReceived: from mail-pf0-x241.google.com ([2"
> +                        "607:f8b0:400e:c00::241]:47361)\n\tby eggs.gnu.org with esmtps (TL"
> +                        "S1.0:RSA_AES_128_CBC_SHA1:16)\n\t(Exim 4.71) (envelope-from <andr"
> +                        "ew.smirnov@gmail.com>)\n\tid 1e6j4J-0002VQ-5h; Mon, 23 Oct 2017 1"
> +                        "6:11:27 -0400\nReceived: by mail-pf0-x241.google.com with SMTP id"
> +                        " z11so17896780pfk.4;\n\tMon, 23 Oct 2017 13:11:27 -0700 (PDT)\nRe"
> +                        "ceived: from squirtle.westlake.spaceflightindustries.com ([173.22"
> +                        "6.206.194])\n\tby smtp.gmail.com with ESMTPSA id\n\tj1sm15181623p"
> +                        "fj.108.2017.10.23.13.11.24\n\t(version=TLS1_2 cipher=ECDHE-RSA-CH"
> +                        "ACHA20-POLY1305 bits=256/256);\n\tMon, 23 Oct 2017 13:11:25 -0700"
> +                        " (PDT)\nDKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=g"
> +                        "mail.com; s=20161025;\n\th=from:to:cc:subject:date:message-id:in-"
> +                        "reply-to:references\n\t:mime-version:content-transfer-encoding;\n"
> +                        "\tbh=zmFol33kPLVHCkj7Ro+lVg1LTAQod/G9dNqJXtckibI=;\n\tb=D49+KCtse"
> +                        "bdshdA2kxqNqCWLEOTSRXI61CbfBrS3YYbGspt/3vTIRCLSKNhICr2UOc\n\t7BhL"
> +                        "XRtMKhn2gomHPqqSHOSp+hB5XtMmBNpBpkQyXMHoGkgmjg0IIF02Vzn4i2QzP8C9"
> +                        "\n\t0SDZb6VYnz70J5HY0KZwVfQ+Rc5qgJEfcTHzuzZ4qHcbXxPHYCGYo1yDG6bEU"
> +                        "LNp2sRB\n\tGekoCKine5V1Uc+8aKmIeQA3zTXj2BLYqIQFi3UdiEemj94Gs3UFkE"
> +                        "kV3kTtCBwBVYep\n\tCvtbjBMI4Kb2Rcyb7taNS1PwjoXo4nzyPqSftf5CtxE3FYQ"
> +                        "6pSHkU8H1cqi4os4RgACQ\n\t6rrA==\nX-Google-DKIM-Signature: v=1; a="
> +                        "rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x"
> +                        "-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to"
> +                        "\n\t:references:mime-version:content-transfer-encoding;\n\tbh=zmF"
> +                        "ol33kPLVHCkj7Ro+lVg1LTAQod/G9dNqJXtckibI=;\n\tb=kG94Z4+JpBMpVNtWI"
> +                        "ASASHAaqcxeUgqF149vlfmPjsUsUZoE69zK/Xq8lz25p+TskP\n\tu+sFtsuT//gI"
> +                        "M/gFEeFYPBUEECFh+cSu6vYqjvy7W+o1dt0CkQS0K4sG2a6PDeXTc7Dw\n\tYOmEE"
> +                        "gzEW+JtEp27yE8L5Yiur7k9cMnq6AGsLtrNa4leHN8KfnBLpZDJ1w2BTVAST/Mt\n"
> +                        "\tp5OmcBALM2s2PfVxV2AqFIC03+BUkFo78Yl0dJkT95uUWQvXOrYnhrJGikBOpxf"
> +                        "e2GEl\n\tdX/N0knNvw1ILQigiiD7mTg2pWBXXdi9ncxWFbWGav3NFgMuMj9Le7dh"
> +                        "Merg+f0Pqzqq\n\tuMRw==\nX-Gm-Message-State: AMCzsaVtdnaUNbjj5huOS"
> +                        "I8ibhSVAiVnF57PiIS4oVle1IVoBcH6i/W4\n\tsAtvFi/nF5bYIYfQxgZMU93rvm"
> +                        "Mn\nX-Google-Smtp-Source: ABhQp+Tw1GtSPaSw51tZkI3AfiuyluStPI8C5/3"
> +                        "esBqFkirOMfsjtlRNoBcr8lgEf/55RwhQLiI5mQ==\nX-Received: by 10.98.6"
> +                        "5.218 with SMTP id g87mr14269292pfd.105.1508789486104;\n\tMon, 23"
> +                        " Oct 2017 13:11:26 -0700 (PDT)\nFrom: Andrey Smirnov <andrew.smir"
> +                        "nov@gmail.com>\nTo: qemu-arm@nongnu.org\nDate: Mon, 23 Oct 2017 1"
> +                        "3:10:38 -0700\nMessage-Id: <20171023201055.21973-11-andrew.smirno"
> +                        "v@gmail.com>\nX-Mailer: git-send-email 2.13.5\nIn-Reply-To: <2017"
> +                        "1023201055.21973-1-andrew.smirnov@gmail.com>\nReferences: <201710"
> +                        "23201055.21973-1-andrew.smirnov@gmail.com>\nMIME-Version: 1.0\nCo"
> +                        "ntent-Type: text/plain; charset=\"utf-8\"\nContent-Transfer-Encod"
> +                        "ing: base64\nX-detected-operating-system: by eggs.gnu.org: Genre "
> +                        "and OS details not\n\trecognized.\nX-Received-From: 2607:f8b0:400"
> +                        "e:c00::241\nSubject: [Qemu-devel] [PATCH v2 10/27] imx_fec: Reser"
> +                        "ve full 4K page for the\n register file\nX-BeenThere: qemu-devel@"
> +                        "nongnu.org\nX-Mailman-Version: 2.1.21\nPrecedence: list\nList-Id:"
> +                        " <qemu-devel.nongnu.org>\nList-Unsubscribe: <https://lists.nongnu"
> +                        ".org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@n"
> +                        "ongnu.org?subject=unsubscribe>\nList-Archive: <http://lists.nongn"
> +                        "u.org/archive/html/qemu-devel/>\nList-Post: <mailto:qemu-devel@no"
> +                        "ngnu.org>\nList-Help: <mailto:qemu-devel-request@nongnu.org?subje"
> +                        "ct=help>\nList-Subscribe: <https://lists.nongnu.org/mailman/listi"
> +                        "nfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject"
> +                        "=subscribe>\nCc: Peter Maydell <peter.maydell@linaro.org>,\n\tAnd"
> +                        "rey Smirnov <andrew.smirnov@gmail.com>,\n\tJason Wang <jasowang@r"
> +                        "edhat.com>,\n\t=?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <f4bug@a"
> +                        "msat.org>,\n\tqemu-devel@nongnu.org, yurovsky@gmail.com\nErrors-T"
> +                        "o: qemu-devel-bounces+importer=patchew.org@nongnu.org\nSender: \""
> +                        "Qemu-devel\" <qemu-devel-bounces+importer=patchew.org@nongnu.org>"
> +                        "\nX-ZohoMail-DKIM: fail (Header signature does not verify)\nX-Zoh"
> +                        "oMail: RDKM_2  RSF_6  Z_629925259 SPT_0\n\nU29tZSBpLk1YIFNvQ3MgKG"
> +                        "UuZy4gaS5NWDcpIGhhdmUgRkVDIHJlZ2lzdGVycyBnb2luZyBhcyBm\nYXIgYXMgb"
> +                        "2Zmc2V0CjB4NjE0LCBzbyB0byBhdm9pZCBnZXR0aW5nIGFib3J0cyB3aGVuIGFjY2"
> +                        "Vz\nc2luZyB0aG9zZSBvbiBRRU1VLCBleHRlbmQKdGhlIHJlZ2lzdGVyIGZpbGUgd"
> +                        "G8gY292ZXIgNEtC\nIG9mIGFkZHJlc3Mgc3BhY2UgaW5zdGVhZCBvZiBqdXN0IDFL"
> +                        "LgoKQ2M6IFBldGVyIE1heWRlbGwg\nPHBldGVyLm1heWRlbGxAbGluYXJvLm9yZz4"
> +                        "KQ2M6IEphc29uIFdhbmcgPGphc293YW5nQHJlZGhh\ndC5jb20+CkNjOiBQaGlsaX"
> +                        "BwZSBNYXRoaWV1LURhdWTDqSA8ZjRidWdAYW1zYXQub3JnPgpDYzog\ncWVtdS1kZ"
> +                        "XZlbEBub25nbnUub3JnCkNjOiBxZW11LWFybUBub25nbnUub3JnCkNjOiB5dXJvdn"
> +                        "Nr\neUBnbWFpbC5jb20KU2lnbmVkLW9mZi1ieTogQW5kcmV5IFNtaXJub3YgPGFuZ"
> +                        "HJldy5zbWlybm92\nQGdtYWlsLmNvbT4KLS0tCiBody9uZXQvaW14X2ZlYy5jIHwg"
> +                        "MiArLQogMSBmaWxlIGNoYW5nZWQs\nIDEgaW5zZXJ0aW9uKCspLCAxIGRlbGV0aW9"
> +                        "uKC0pCgpkaWZmIC0tZ2l0IGEvaHcvbmV0L2lteF9m\nZWMuYyBiL2h3L25ldC9pbX"
> +                        "hfZmVjLmMKaW5kZXggNDhkMDEyY2FkNi4uZTIzNmJjOTMzYyAxMDA2\nNDQKLS0tI"
> +                        "GEvaHcvbmV0L2lteF9mZWMuYworKysgYi9ody9uZXQvaW14X2ZlYy5jCkBAIC0xMj"
> +                        "Uy\nLDcgKzEyNTIsNyBAQCBzdGF0aWMgdm9pZCBpbXhfZXRoX3JlYWxpemUoRGV2a"
> +                        "WNlU3RhdGUgKmRl\ndiwgRXJyb3IgKiplcnJwKQogICAgIFN5c0J1c0RldmljZSAq"
> +                        "c2JkID0gU1lTX0JVU19ERVZJQ0Uo\nZGV2KTsKIAogICAgIG1lbW9yeV9yZWdpb25"
> +                        "faW5pdF9pbygmcy0+aW9tZW0sIE9CSkVDVChkZXYp\nLCAmaW14X2V0aF9vcHMsIH"
> +                        "MsCi0gICAgICAgICAgICAgICAgICAgICAgICAgIFRZUEVfSU1YX0ZF\nQywgMHg0M"
> +                        "DApOworICAgICAgICAgICAgICAgICAgICAgICAgICBUWVBFX0lNWF9GRUMsIDB4MT"
> +                        "Aw\nMCk7CiAgICAgc3lzYnVzX2luaXRfbW1pbyhzYmQsICZzLT5pb21lbSk7CiAgI"
> +                        "CAgc3lzYnVzX2lu\naXRfaXJxKHNiZCwgJnMtPmlycVswXSk7CiAgICAgc3lzYnVz"
> +                        "X2luaXRfaXJxKHNiZCwgJnMtPmly\ncVsxXSk7Ci0tIAoyLjEzLjUKCgo=\n\n"
> +                }
> +             
> +        resp = self.api_client.post(self.PROJECT_BASE + "messages/", json.dumps(data), content_type='application/json')
> +        self.assertEqual(resp.status_code,201)

s/,201/, 201/

> +        resp_get = self.api_client.get(self.PROJECT_BASE + "messages/20171023201055.21973-11-andrew.smirnov@gmail.com/")
> +        self.assertEqual(resp_get.status_code,200)

Likewise.

> +        self.assertEqual(resp.data['subject'],"[Qemu-devel] [PATCH v2 10/27] imx_fec: Reserve full 4K "

Likewise, again.

> +                        "page for the register file")
> +
> +
>      def test_message(self):
>          series = self.apply_and_retrieve('0001-simple-patch.mbox.gz',
>                                           self.p.id, '20160628014747.20971-1-famz@redhat.com')
> -- 
> 2.14.3 (Apple Git-98)
> 
> _______________________________________________
> Patchew-devel mailing list
> Patchew-devel@redhat.com
> https://www.redhat.com/mailman/listinfo/patchew-devel

_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel