[PATCH] Add comments REST API
vkabatov at redhat.com
vkabatov at redhat.com
Fri Mar 23 23:33:38 AEDT 2018
From: Veronika Kabatova <vkabatov at redhat.com>
Signed-off-by: Veronika Kabatova <vkabatov at redhat.com>
---
docs/api/rest.rst | 6 +-
patchwork/api/comment.py | 117 +++++++++++++++++++++
patchwork/api/filters.py | 16 +++
patchwork/api/index.py | 1 +
patchwork/models.py | 3 +
patchwork/urls.py | 10 ++
.../notes/comments-api-b7dff6ee4ce04c9b.yaml | 10 ++
7 files changed, 161 insertions(+), 2 deletions(-)
create mode 100644 patchwork/api/comment.py
create mode 100644 releasenotes/notes/comments-api-b7dff6ee4ce04c9b.yaml
diff --git a/docs/api/rest.rst b/docs/api/rest.rst
index d526b27..e33aefc 100644
--- a/docs/api/rest.rst
+++ b/docs/api/rest.rst
@@ -48,7 +48,8 @@ Patchwork instance hosted at `patchwork.example.com`, run:
"people": "https://patchwork.example.com/api/1.0/people/",
"projects": "https://patchwork.example.com/api/1.0/projects/",
"series": "https://patchwork.example.com/api/1.0/series/",
- "users": "https://patchwork.example.com/api/1.0/users/"
+ "users": "https://patchwork.example.com/api/1.0/users/",
+ "comments": "https://patchwork.example.com/api/1.0/comments/"
}
@@ -71,7 +72,8 @@ well-supported. To repeat the above example using `requests`:, run
"people": "https://patchwork.example.com/api/1.0/people/",
"projects": "https://patchwork.example.com/api/1.0/projects/",
"series": "https://patchwork.example.com/api/1.0/series/",
- "users": "https://patchwork.example.com/api/1.0/users/"
+ "users": "https://patchwork.example.com/api/1.0/users/",
+ "comments": "https://patchwork.example.com/api/1.0/comments/"
}
Tools like `curl` and libraries like `requests` can be used to build anything
diff --git a/patchwork/api/comment.py b/patchwork/api/comment.py
new file mode 100644
index 0000000..4252ecd
--- /dev/null
+++ b/patchwork/api/comment.py
@@ -0,0 +1,117 @@
+# Patchwork - automated patch tracking system
+# Copyright (C) 2018 Red Hat
+#
+# This file is part of the Patchwork package.
+#
+# Patchwork is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Patchwork is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Patchwork; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import email.parser
+
+from rest_framework.generics import ListAPIView
+from rest_framework.generics import RetrieveUpdateAPIView
+from rest_framework.reverse import reverse
+from rest_framework.serializers import HyperlinkedModelSerializer
+from rest_framework.serializers import SerializerMethodField
+
+from patchwork.api.base import PatchworkPermission
+from patchwork.api.filters import CommentFilter
+from patchwork.api.embedded import PersonSerializer
+from patchwork.api.embedded import ProjectSerializer
+from patchwork.models import Comment
+
+
+class CommentListSerializer(HyperlinkedModelSerializer):
+
+ submitter = PersonSerializer(read_only=True)
+ tags = SerializerMethodField()
+ subject = SerializerMethodField()
+ parent = SerializerMethodField(source='submission')
+
+ def get_parent(self, instance):
+ attrs = {'subject': instance.submission.name,
+ 'msgid': instance.submission.msgid,
+ 'date': instance.submission.date}
+
+ if hasattr(instance.submission, 'patch'):
+ attrs['url'] = self.context.get('request').build_absolute_uri(
+ reverse('api-patch-detail', args=[instance.submission.id]))
+ else:
+ attrs['url'] = self.context.get('request').build_absolute_uri(
+ reverse('api-cover-detail', args=[instance.submission.id]))
+
+ return attrs
+
+ def get_subject(self, instance):
+ return email.parser.Parser().parsestr(instance.headers,
+ True).get('Subject', '')
+
+ def get_tags(self, instance):
+ # TODO implement after we get support for tags on comments
+ return {}
+
+ class Meta:
+ model = Comment
+ fields = ('id', 'url', 'msgid', 'date', 'subject', 'submitter',
+ 'parent', 'tags')
+ read_only_fields = fields
+ extra_kwargs = {
+ 'url': {'view_name': 'api-comment-detail'},
+ }
+
+
+class CommentDetailSerializer(CommentListSerializer):
+
+ headers = SerializerMethodField()
+ project = ProjectSerializer(source='submission.project', read_only=True)
+
+ def get_headers(self, comment):
+ if comment.headers:
+ return email.parser.Parser().parsestr(comment.headers, True)
+
+ class Meta:
+ model = Comment
+ fields = CommentListSerializer.Meta.fields + (
+ 'content', 'headers', 'project'
+ )
+ read_only_fields = fields
+ extra_kwargs = CommentListSerializer.Meta.extra_kwargs
+
+
+class CommentList(ListAPIView):
+ """List comments"""
+
+ permission_classes = (PatchworkPermission,)
+ serializer_class = CommentListSerializer
+ filter_class = CommentFilter
+ search_fields = ('subject',)
+ ordering_fields = ('id', 'subject', 'date', 'submitter')
+ ordering = 'id'
+
+ def get_queryset(self):
+ return Comment.objects.all().select_related(
+ 'submission'
+ ).prefetch_related('related_tags').defer('content')
+
+
+class CommentDetail(RetrieveUpdateAPIView):
+ """Show a comment"""
+
+ permission_classes = (PatchworkPermission,)
+ serializer_class = CommentDetailSerializer
+
+ def get_queryset(self):
+ return Comment.objects.all().select_related(
+ 'submission'
+ ).prefetch_related('related_tags')
diff --git a/patchwork/api/filters.py b/patchwork/api/filters.py
index d207b2b..8256d8c 100644
--- a/patchwork/api/filters.py
+++ b/patchwork/api/filters.py
@@ -26,6 +26,7 @@ from django.forms import ModelChoiceField
from patchwork.models import Bundle
from patchwork.models import Check
+from patchwork.models import Comment
from patchwork.models import CoverLetter
from patchwork.models import Event
from patchwork.models import Patch
@@ -33,6 +34,7 @@ from patchwork.models import Person
from patchwork.models import Project
from patchwork.models import Series
from patchwork.models import State
+from patchwork.models import Submission
class TimestampMixin(FilterSet):
@@ -186,3 +188,17 @@ class BundleFilter(ProjectMixin, FilterSet):
class Meta:
model = Bundle
fields = ('project', 'owner', 'public')
+
+
+class CommentFilter(ProjectMixin, TimestampMixin, FilterSet):
+
+ submitter = PersonFilter(queryset=Person.objects.all())
+ parent = ModelChoiceFilter(name='submission',
+ queryset=Submission.objects.all())
+ project = ProjectFilter(to_field_name='linkname',
+ name='submission__project',
+ queryset=Project.objects.all())
+
+ class Meta:
+ model = Comment
+ fields = ('project', 'parent', 'submitter')
diff --git a/patchwork/api/index.py b/patchwork/api/index.py
index 53494db..ebc8dbf 100644
--- a/patchwork/api/index.py
+++ b/patchwork/api/index.py
@@ -34,4 +34,5 @@ class IndexView(APIView):
'series': reverse('api-series-list', request=request),
'events': reverse('api-event-list', request=request),
'bundles': reverse('api-bundle-list', request=request),
+ 'comments': reverse('api-comment-list', request=request),
})
diff --git a/patchwork/models.py b/patchwork/models.py
index f91b994..67c2d3a 100644
--- a/patchwork/models.py
+++ b/patchwork/models.py
@@ -613,6 +613,9 @@ class Comment(EmailMixin, models.Model):
if hasattr(self.submission, 'patch'):
self.submission.patch.refresh_tag_counts()
+ def is_editable(self, user):
+ return False
+
class Meta:
ordering = ['date']
unique_together = [('msgid', 'submission')]
diff --git a/patchwork/urls.py b/patchwork/urls.py
index 7193472..7ae4425 100644
--- a/patchwork/urls.py
+++ b/patchwork/urls.py
@@ -213,6 +213,7 @@ if settings.ENABLE_REST_API:
from patchwork.api import bundle as api_bundle_views # noqa
from patchwork.api import check as api_check_views # noqa
+ from patchwork.api import comment as api_comment_views # noqa
from patchwork.api import cover as api_cover_views # noqa
from patchwork.api import event as api_event_views # noqa
from patchwork.api import index as api_index_views # noqa
@@ -238,6 +239,12 @@ if settings.ENABLE_REST_API:
url(r'^people/(?P<pk>[^/]+)/$',
api_person_views.PersonDetail.as_view(),
name='api-person-detail'),
+ url(r'^comments/$',
+ api_comment_views.CommentList.as_view(),
+ name='api-comment-list'),
+ url(r'^comments/(?P<pk>[^/]+)/$',
+ api_comment_views.CommentDetail.as_view(),
+ name='api-comment-detail'),
url(r'^covers/$',
api_cover_views.CoverLetterList.as_view(),
name='api-cover-list'),
@@ -277,6 +284,9 @@ if settings.ENABLE_REST_API:
url(r'^events/$',
api_event_views.EventList.as_view(),
name='api-event-list'),
+ url(r'^comments/$',
+ api_comment_views.CommentList.as_view(),
+ name='api-comment-list'),
]
urlpatterns += [
diff --git a/releasenotes/notes/comments-api-b7dff6ee4ce04c9b.yaml b/releasenotes/notes/comments-api-b7dff6ee4ce04c9b.yaml
new file mode 100644
index 0000000..72b3339
--- /dev/null
+++ b/releasenotes/notes/comments-api-b7dff6ee4ce04c9b.yaml
@@ -0,0 +1,10 @@
+---
+api:
+ - |
+ Added /comments endpoint. For comment list, fields
+ 'id', 'url', 'msgid', 'date', 'subject', 'submitter', 'parent', 'tags'
+ are available. For comment detail (/comments/29), comment's
+ 'content', 'headers', 'project'
+ are added as well. Filtering is possible based on
+ 'project', 'parent', 'submitter'
+ fields.
--
2.13.6
More information about the Patchwork
mailing list