api/rest.py | 21 +++++++++++---------- mbox.py | 18 ++++++++++++++++++ tests/test_mbox.py | 19 +++++++++++++++++++ 3 files changed, 48 insertions(+), 10 deletions(-)
- Mbox would now return a dictionary object which would help REST API deserialize easily into model object.
[WIP] POST endpoint for messages.
- It's a work in progress for creating new message which is improvement of legacy endpoint: "import"
Message-Id: <20180424160400.29938-1-shubhamjain7495@gmail.com>
POST endpoint for messages
- Added test for text to json converter of Mbox
- Removed extra field from the dictionary object
---
api/rest.py | 21 +++++++++++----------
mbox.py | 18 ++++++++++++++++++
tests/test_mbox.py | 19 +++++++++++++++++++
3 files changed, 48 insertions(+), 10 deletions(-)
diff --git a/api/rest.py b/api/rest.py
index 381b569..917ed22 100644
--- a/api/rest.py
+++ b/api/rest.py
@@ -125,8 +125,8 @@ class BaseMessageSerializer(serializers.ModelSerializer):
resource_uri = HyperlinkedMessageField(view_name='messages-detail')
- recipients = SerializerMethodField()
- sender = SerializerMethodField()
+ # recipients = SerializerMethodField()
+ # sender = SerializerMethodField()
def format_name_addr(self, name, addr):
d = {}
@@ -135,12 +135,12 @@ class BaseMessageSerializer(serializers.ModelSerializer):
d['address'] = addr
return d
- def get_recipients(self, obj):
- return [self.format_name_addr(*x) for x in obj.get_recipients()]
+ # def get_recipients(self, obj):
+ # return [self.format_name_addr(*x) for x in obj.get_recipients()]
- def get_sender(self, obj):
- name, addr = obj.get_sender()
- return self.format_name_addr(*obj.get_sender())
+ # def get_sender(self, obj):
+ # name, addr = obj.get_sender()
+ # return self.format_name_addr(*obj.get_sender())
# a message_id is *not* unique, so we can only list
class BaseMessageViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
@@ -285,7 +285,8 @@ class ProjectSeriesViewSet(ProjectMessagesViewSetMixin,
class MessageSerializer(BaseMessageSerializer):
class Meta:
model = Message
- fields = BaseMessageSerializer.Meta.fields + ('mbox', )
+ # fields = BaseMessageSerializer.Meta.fields + ('mbox', )
+ fields = '__all__'
def get_mbox(self, obj):
return obj.get_mbox()
@@ -311,9 +312,9 @@ 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/mbox.py b/mbox.py
index fe108f3..00336ba 100644
--- a/mbox.py
+++ b/mbox.py
@@ -13,6 +13,7 @@ import email.utils
import email.header
import datetime
import re
+import json
def _parse_header(header):
r = ''
@@ -269,3 +270,20 @@ class MboxMessage(object):
if c == 0:
return True
return False
+
+ def get_json(self):
+ """Return the JSON format of the mbox """
+ msg = {}
+ msg['message_id'] = self.get_message_id()
+ msg['in_reply_to'] = self.get_in_reply_to() or ""
+ msg['date'] = self.get_date()
+ msg['subject'] = self.get_subject()
+ msg['stripped_subject'] = self.get_subject(strip_tags=True)
+ msg['version'] = self.get_version()
+ msg['sender'] = json.dumps(self.get_from())
+ msg['recipients'] = json.dumps(self.get_to() + self.get_cc())
+ msg['prefixes']=json.dumps(self.get_prefixes())
+ msg['is_series_head'] = self.is_series_head()
+ msg['is_patch'] = self.is_patch()
+ msg['patch_num'] = self.get_num()[0]
+ return msg
diff --git a/tests/test_mbox.py b/tests/test_mbox.py
index 8493df7..e4d69d2 100755
--- a/tests/test_mbox.py
+++ b/tests/test_mbox.py
@@ -13,6 +13,7 @@ import sys
import mbox
sys.path.append(os.path.dirname(__file__))
from patchewtest import PatchewTestCase, main
+import datetime
class MboxTest(PatchewTestCase):
@@ -52,5 +53,23 @@ Virtualization: qemu.org | libvirt.org
msg = mbox.MboxMessage(f.read())
self.assertTrue(msg.is_patch())
+ def test_get_json(self):
+ expected = {'message_id': '20160628014747.20971-1-famz@redhat.com',
+ 'in_reply_to': '',
+ 'date': datetime.datetime(2016, 6, 28, 1, 47, 47),
+ 'subject': '[Qemu-devel] [PATCH] quorum: Only compile when supported',
+ 'stripped_subject': 'quorum: Only compile when supported',
+ 'version': 1,
+ 'sender': '["Fam Zheng", "famz@redhat.com"]',
+ 'recipients': '[["qemu-devel@nongnu.org", "qemu-devel@nongnu.org"], ["Kevin Wolf", "kwolf@redhat.com"], ["Alberto Garcia", "berto@igalia.com"], ["qemu-block@nongnu.org", "qemu-block@nongnu.org"], ["Max Reitz", "mreitz@redhat.com"]]',
+ 'prefixes': '["Qemu-devel", "PATCH"]',
+ 'is_series_head': True,
+ 'is_patch': True,
+ 'patch_num': None }
+ dp = self.get_data_path("0001-simple-patch.mbox.gz")
+ with open(dp, "r") as f:
+ msg = mbox.MboxMessage(f.read()).get_json()
+ self.assertEqual(msg, expected)
+
if __name__ == '__main__':
main()
--
2.14.3 (Apple Git-98)
_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
Very good progress, thanks!
On 27/04/2018 13:53, Shubham Jain wrote:
> class BaseMessageViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
> @@ -285,7 +285,8 @@ class ProjectSeriesViewSet(ProjectMessagesViewSetMixin,
> class MessageSerializer(BaseMessageSerializer):
> class Meta:
> model = Message
> - fields = BaseMessageSerializer.Meta.fields + ('mbox', )
> + # fields = BaseMessageSerializer.Meta.fields + ('mbox', )
> + fields = '__all__'
What is fields = '__all__'? :)
> def get_mbox(self, obj):
> return obj.get_mbox()
As far as I understand, read_only=True is used to make fields that are
included in the API output, but should not be included in the
POST/PUT/PATCH input. I thought SerializerMethodField had
read_only=True automatically, but maybe it doesn't?
> @@ -311,9 +312,9 @@ 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()
Can you also write a testcase for the POST operation? You can create a
new file 0001-simple-patch.json.gz to keep the testcase code simple.
> + msg['sender'] = json.dumps(self.get_from())
> + msg['recipients'] = json.dumps(self.get_to() + self.get_cc())
The json.dumps of course is only temporary; it can be removed when my
JSONField patch is applied and the sender/recipients
SerializerMethodFields are replaced by a Serializer.
> + 'sender': '["Fam Zheng", "famz@redhat.com"]',
> + 'recipients': '[["qemu-devel@nongnu.org", "qemu-devel@nongnu.org"], ["Kevin Wolf", "kwolf@redhat.com"], ["Alberto Garcia", "berto@igalia.com"], ["qemu-block@nongnu.org", "qemu-block@nongnu.org"], ["Max Reitz", "mreitz@redhat.com"]]',
So that these also becomes arrays rather than strings, and the
individual pairs use {'name': ..., 'address': ...} as in the GET output.
Thanks,
Paolo
_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
On Fri, Apr 27, 2018 at 5:37 PM Paolo Bonzini <pbonzini@redhat.com> wrote:
> Very good progress, thanks!
>
> On 27/04/2018 13:53, Shubham Jain wrote:
> > class BaseMessageViewSet(mixins.ListModelMixin,
> viewsets.GenericViewSet):
> > @@ -285,7 +285,8 @@ class
> ProjectSeriesViewSet(ProjectMessagesViewSetMixin,
> > class MessageSerializer(BaseMessageSerializer):
> > class Meta:
> > model = Message
> > - fields = BaseMessageSerializer.Meta.fields + ('mbox', )
> > + # fields = BaseMessageSerializer.Meta.fields + ('mbox', )
> > + fields = '__all__'
>
> What is fields = '__all__'? :)
>
Since you mentioned to use browsable api "form" to check for POST. The
"__all__" helps to get all the fields in the model. This would help with
the fields which were dependent on mbox since we are not providing any
mbox.
>
> > def get_mbox(self, obj):
> > return obj.get_mbox()
>
> As far as I understand, read_only=True is used to make fields that are
> included in the API output, but should not be included in the
> POST/PUT/PATCH input. I thought SerializerMethodField had
read_only=True automatically, but maybe it doesn't?
>
Yeah this won't work with POST/PUT/PATCH (
https://github.com/encode/django-rest-framework/blob/master/rest_framework/fields.py
)
> @@ -311,9 +312,9 @@ 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()
>
> Can you also write a testcase for the POST operation? You can create a
> new file 0001-simple-patch.json.gz to keep the testcase code simple.
>
Yes :)
> > + msg['sender'] = json.dumps(self.get_from())
> > + msg['recipients'] = json.dumps(self.get_to() + self.get_cc())
>
> The json.dumps of course is only temporary; it can be removed when my
> JSONField patch is applied and the sender/recipients
> SerializerMethodFields are replaced by a Serializer.
>
> > + 'sender': '["Fam Zheng", "famz@redhat.com"]',
> > + 'recipients': '[["qemu-devel@nongnu.org", "
> qemu-devel@nongnu.org"], ["Kevin Wolf", "kwolf@redhat.com"], ["Alberto
> Garcia", "berto@igalia.com"], ["qemu-block@nongnu.org", "
> qemu-block@nongnu.org"], ["Max Reitz", "mreitz@redhat.com"]]',
>
> So that these also becomes arrays rather than strings, and the
> individual pairs use {'name': ..., 'address': ...} as in the GET output.
>
> Thanks,
>
> Paolo
>
_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
On 27/04/2018 14:32, Shubham Jain wrote:
>
>
> On Fri, Apr 27, 2018 at 5:37 PM Paolo Bonzini <pbonzini@redhat.com
> <mailto:pbonzini@redhat.com>> wrote:
>
> Very good progress, thanks!
>
> On 27/04/2018 13:53, Shubham Jain wrote:
> > class BaseMessageViewSet(mixins.ListModelMixin,
> viewsets.GenericViewSet):
> > @@ -285,7 +285,8 @@ class
> ProjectSeriesViewSet(ProjectMessagesViewSetMixin,
> > class MessageSerializer(BaseMessageSerializer):
> > class Meta:
> > model = Message
> > - fields = BaseMessageSerializer.Meta.fields + ('mbox', )
> > + # fields = BaseMessageSerializer.Meta.fields + ('mbox', )
> > + fields = '__all__'
>
> What is fields = '__all__'? :)
>
> Since you mentioned to use browsable api "form" to check for POST. The
> "__all__" helps to get all the fields in the model. This would help with
> the fields which were dependent on mbox since we are not providing any
> mbox.
Ok, one thing at a time. First of all let's apply the mbox.py and
tests/test_mbox.py parts. That's ready except that msg['mbox'] should
be populated as well.
Second, you can apply the JSONField patch locally, and use it to define
a custom serializer for names and addresses. This will get all fields
right except mbox.
Finally, we need to get the mbox field right. The "best" way would be
to define a custom Django Field class. A slightly simpler way would be to:
- rename the existing "mbox" field to e.g. "mbox_blob"
- add getters and setters for "mbox".
- override "save" for Message so that it calls save_mbox() if creating a
new message ("self.pk is None":
https://stackoverflow.com/questions/907695/in-a-django-model-custom-save-method-how-should-you-identify-a-new-object)
I placed a checklist for this at
https://github.com/patchew-project/patchew/issues/75. Each item can be
a separate patch. If you have a GitHub account we can give you edit access.
Paolo
>
>
> > def get_mbox(self, obj):
> > return obj.get_mbox()
>
> As far as I understand, read_only=True is used to make fields that are
> included in the API output, but should not be included in the
> POST/PUT/PATCH input. I thought SerializerMethodField had
>
> read_only=True automatically, but maybe it doesn't?
>
> Yeah this won't work with POST/PUT/PATCH
> (https://github.com/encode/django-rest-framework/blob/master/rest_framework/fields.py)
>
> > @@ -311,9 +312,9 @@ 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()
>
> Can you also write a testcase for the POST operation? You can create a
> new file 0001-simple-patch.json.gz to keep the testcase code simple.
>
> Yes :)
>
> > + msg['sender'] = json.dumps(self.get_from())
> > + msg['recipients'] = json.dumps(self.get_to() + self.get_cc())
>
> The json.dumps of course is only temporary; it can be removed when my
> JSONField patch is applied and the sender/recipients
> SerializerMethodFields are replaced by a Serializer.
>
> > + 'sender': '["Fam Zheng", "famz@redhat.com
> <mailto:famz@redhat.com>"]',
> > + 'recipients': '[["qemu-devel@nongnu.org
> <mailto:qemu-devel@nongnu.org>", "qemu-devel@nongnu.org
> <mailto:qemu-devel@nongnu.org>"], ["Kevin Wolf", "kwolf@redhat.com
> <mailto:kwolf@redhat.com>"], ["Alberto Garcia", "berto@igalia.com
> <mailto:berto@igalia.com>"], ["qemu-block@nongnu.org
> <mailto:qemu-block@nongnu.org>", "qemu-block@nongnu.org
> <mailto:qemu-block@nongnu.org>"], ["Max Reitz", "mreitz@redhat.com
> <mailto:mreitz@redhat.com>"]]',
>
> So that these also becomes arrays rather than strings, and the
> individual pairs use {'name': ..., 'address': ...} as in the GET output.
>
> Thanks,
>
> Paolo
>
_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
On Fri, Apr 27, 2018 at 9:35 PM Paolo Bonzini <pbonzini@redhat.com> wrote:
> On 27/04/2018 14:32, Shubham Jain wrote:
> >
> >
> > On Fri, Apr 27, 2018 at 5:37 PM Paolo Bonzini <pbonzini@redhat.com
> > <mailto:pbonzini@redhat.com>> wrote:
> >
> > Very good progress, thanks!
> >
> > On 27/04/2018 13:53, Shubham Jain wrote:
> > > class BaseMessageViewSet(mixins.ListModelMixin,
> > viewsets.GenericViewSet):
> > > @@ -285,7 +285,8 @@ class
> > ProjectSeriesViewSet(ProjectMessagesViewSetMixin,
> > > class MessageSerializer(BaseMessageSerializer):
> > > class Meta:
> > > model = Message
> > > - fields = BaseMessageSerializer.Meta.fields + ('mbox', )
> > > + # fields = BaseMessageSerializer.Meta.fields + ('mbox', )
> > > + fields = '__all__'
> >
> > What is fields = '__all__'? :)
> >
> > Since you mentioned to use browsable api "form" to check for POST. The
> > "__all__" helps to get all the fields in the model. This would help with
> > the fields which were dependent on mbox since we are not providing any
> > mbox.
>
> Ok, one thing at a time. First of all let's apply the mbox.py and
> tests/test_mbox.py parts. That's ready except that msg['mbox'] should
> be populated as well.
>
Why should be mbox populated? Aren't we trying to convert the content in
mbox from text to son?
> Second, you can apply the JSONField patch locally, and use it to define
> a custom serializer for names and addresses. This will get all fields
> right except mbox.
>
> Finally, we need to get the mbox field right. The "best" way would be
> to define a custom Django Field class. A slightly simpler way would be to:
>
> - rename the existing "mbox" field to e.g. "mbox_blob"
>
> - add getters and setters for "mbox".
>
> - override "save" for Message so that it calls save_mbox() if creating a
> new message ("self.pk is None":
>
> https://stackoverflow.com/questions/907695/in-a-django-model-custom-save-method-how-should-you-identify-a-new-object
> )
>
> I placed a checklist for this at
> https://github.com/patchew-project/patchew/issues/75. Each item can be
> a separate patch. If you have a GitHub account we can give you edit
> access.
>
My GitHub handle is shubhamdotjain
> Paolo
> >
> >
> > > def get_mbox(self, obj):
> > > return obj.get_mbox()
> >
> > As far as I understand, read_only=True is used to make fields that
> are
> > included in the API output, but should not be included in the
> > POST/PUT/PATCH input. I thought SerializerMethodField had
> >
> > read_only=True automatically, but maybe it doesn't?
> >
> > Yeah this won't work with POST/PUT/PATCH
> > (
> https://github.com/encode/django-rest-framework/blob/master/rest_framework/fields.py
> )
> >
> > > @@ -311,9 +312,9 @@ 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()
> >
> > Can you also write a testcase for the POST operation? You can
> create a
> > new file 0001-simple-patch.json.gz to keep the testcase code simple.
> >
> > Yes :)
> >
> > > + msg['sender'] = json.dumps(self.get_from())
> > > + msg['recipients'] = json.dumps(self.get_to() +
> self.get_cc())
> >
> > The json.dumps of course is only temporary; it can be removed when my
> > JSONField patch is applied and the sender/recipients
> > SerializerMethodFields are replaced by a Serializer.
> >
> > > + 'sender': '["Fam Zheng", "famz@redhat.com
> > <mailto:famz@redhat.com>"]',
> > > + 'recipients': '[["qemu-devel@nongnu.org
> > <mailto:qemu-devel@nongnu.org>", "qemu-devel@nongnu.org
> > <mailto:qemu-devel@nongnu.org>"], ["Kevin Wolf", "kwolf@redhat.com
> > <mailto:kwolf@redhat.com>"], ["Alberto Garcia", "berto@igalia.com
> > <mailto:berto@igalia.com>"], ["qemu-block@nongnu.org
> > <mailto:qemu-block@nongnu.org>", "qemu-block@nongnu.org
> > <mailto:qemu-block@nongnu.org>"], ["Max Reitz", "mreitz@redhat.com
> > <mailto:mreitz@redhat.com>"]]',
> >
> > So that these also becomes arrays rather than strings, and the
> > individual pairs use {'name': ..., 'address': ...} as in the GET
> output.
> >
> > Thanks,
> >
> > Paolo
> >
>
>
_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
On 27/04/2018 18:10, Shubham Jain wrote:
>
>
> On Fri, Apr 27, 2018 at 9:35 PM Paolo Bonzini <pbonzini@redhat.com
> <mailto:pbonzini@redhat.com>> wrote:
>
> On 27/04/2018 14:32, Shubham Jain wrote:
> >
> >
> > On Fri, Apr 27, 2018 at 5:37 PM Paolo Bonzini <pbonzini@redhat.com
> <mailto:pbonzini@redhat.com>
> > <mailto:pbonzini@redhat.com <mailto:pbonzini@redhat.com>>> wrote:
> >
> > Very good progress, thanks!
> >
> > On 27/04/2018 13:53, Shubham Jain wrote:
> > > class BaseMessageViewSet(mixins.ListModelMixin,
> > viewsets.GenericViewSet):
> > > @@ -285,7 +285,8 @@ class
> > ProjectSeriesViewSet(ProjectMessagesViewSetMixin,
> > > class MessageSerializer(BaseMessageSerializer):
> > > class Meta:
> > > model = Message
> > > - fields = BaseMessageSerializer.Meta.fields + ('mbox', )
> > > + # fields = BaseMessageSerializer.Meta.fields +
> ('mbox', )
> > > + fields = '__all__'
> >
> > What is fields = '__all__'? :)
> >
> > Since you mentioned to use browsable api "form" to check for POST. The
> > "__all__" helps to get all the fields in the model. This would
> help with
> > the fields which were dependent on mbox since we are not providing any
> > mbox.
>
> Ok, one thing at a time. First of all let's apply the mbox.py and
> tests/test_mbox.py parts. That's ready except that msg['mbox'] should
> be populated as well.
>
> Why should be mbox populated? Aren't we trying to convert the content in
> mbox from text to son?
Yes, but the mbox can be re-exported so it is stored in the database.
> I placed a checklist for this at
> https://github.com/patchew-project/patchew/issues/75. Each item can be
> a separate patch. If you have a GitHub account we can give you edit
> access.
>
> My GitHub handle is shubhamdotjain
Ah no, I cannot. Fam, I would like to add Shubham to the
patchew-project github organization at least during summer of code. Do
you agree?
Thanks,
Paolo
_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
© 2016 - 2026 Red Hat, Inc.