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 - 2024 Red Hat, Inc.