summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Axtens <dja@axtens.net>2020-04-14 15:34:40 +1000
committerDaniel Axtens <dja@axtens.net>2020-04-14 23:27:17 +1000
commitd08b6c72964898c9997a62e4ab6a721f166a56ca (patch)
treec505ea706979e56bdf9fa19f6414787ecdbd2e36
parent08c5856444bc2e100c4acbbea0a244cd46083c4b (diff)
downloadpatchwork-d08b6c72964898c9997a62e4ab6a721f166a56ca.tar
patchwork-d08b6c72964898c9997a62e4ab6a721f166a56ca.tar.gz
api: allow filtering patches and covers by msgid
In the process of fixing the previous bug, I realised that: a) /api/patches/msgid is a perfectly reasonable thing to attempt b) We have no way of finding a patch by message id in the API We can't actualy make /api/patches/msgid work because it may not be unique, but we can add a filter. I'm shoehorning this into stable/2.2, even though it's technically an API change: it's minor, not incompatible and in hindsight a glaring hole. Cc: Michael Ellerman <mpe@ellerman.id.au> Tested-by: Jeremy Kerr <jk@ozlabs.org> Reviewed-by: Andrew Donnellan <ajd@linux.ibm.com> Reviewed-by: Stephen Finucane <stephen@that.guru> Signed-off-by: Daniel Axtens <dja@axtens.net>
-rw-r--r--docs/api/schemas/latest/patchwork.yaml16
-rw-r--r--docs/api/schemas/patchwork.j218
-rw-r--r--docs/api/schemas/v1.2/patchwork.yaml16
-rw-r--r--patchwork/api/filters.py14
-rw-r--r--patchwork/tests/api/test_cover.py12
-rw-r--r--patchwork/tests/api/test_patch.py12
-rw-r--r--releasenotes/notes/rest-filter-msgid-41f693cd4e53cf93.yaml6
7 files changed, 90 insertions, 4 deletions
diff --git a/docs/api/schemas/latest/patchwork.yaml b/docs/api/schemas/latest/patchwork.yaml
index 13cdc9c..cc0d97e 100644
--- a/docs/api/schemas/latest/patchwork.yaml
+++ b/docs/api/schemas/latest/patchwork.yaml
@@ -246,6 +246,14 @@ paths:
schema:
title: ''
type: string
+ - in: query
+ name: msgid
+ description: >
+ The cover message-id as a case-sensitive string, without leading or
+ trailing angle brackets, to filter by.
+ schema:
+ title: ''
+ type: string
responses:
'200':
description: ''
@@ -474,6 +482,14 @@ paths:
schema:
title: ''
type: string
+ - in: query
+ name: msgid
+ description: >
+ The patch message-id as a case-sensitive string, without leading or
+ trailing angle brackets, to filter by.
+ schema:
+ title: ''
+ type: string
responses:
'200':
description: ''
diff --git a/docs/api/schemas/patchwork.j2 b/docs/api/schemas/patchwork.j2
index bd714d5..f5618d4 100644
--- a/docs/api/schemas/patchwork.j2
+++ b/docs/api/schemas/patchwork.j2
@@ -251,6 +251,16 @@ paths:
schema:
title: ''
type: string
+{% if version >= (1, 2) %}
+ - in: query
+ name: msgid
+ description: >
+ The cover message-id as a case-sensitive string, without leading or
+ trailing angle brackets, to filter by.
+ schema:
+ title: ''
+ type: string
+{% endif %}
responses:
'200':
description: ''
@@ -488,6 +498,14 @@ paths:
schema:
title: ''
type: string
+ - in: query
+ name: msgid
+ description: >
+ The patch message-id as a case-sensitive string, without leading or
+ trailing angle brackets, to filter by.
+ schema:
+ title: ''
+ type: string
{% endif %}
responses:
'200':
diff --git a/docs/api/schemas/v1.2/patchwork.yaml b/docs/api/schemas/v1.2/patchwork.yaml
index db2ed12..7bdbe66 100644
--- a/docs/api/schemas/v1.2/patchwork.yaml
+++ b/docs/api/schemas/v1.2/patchwork.yaml
@@ -246,6 +246,14 @@ paths:
schema:
title: ''
type: string
+ - in: query
+ name: msgid
+ description: >
+ The cover message-id as a case-sensitive string, without leading or
+ trailing angle brackets, to filter by.
+ schema:
+ title: ''
+ type: string
responses:
'200':
description: ''
@@ -474,6 +482,14 @@ paths:
schema:
title: ''
type: string
+ - in: query
+ name: msgid
+ description: >
+ The patch message-id as a case-sensitive string, without leading or
+ trailing angle brackets, to filter by.
+ schema:
+ title: ''
+ type: string
responses:
'200':
description: ''
diff --git a/patchwork/api/filters.py b/patchwork/api/filters.py
index deb5ace..93e6281 100644
--- a/patchwork/api/filters.py
+++ b/patchwork/api/filters.py
@@ -184,6 +184,10 @@ class SeriesFilterSet(TimestampMixin, BaseFilterSet):
fields = ('submitter', 'project')
+def msgid_filter(queryset, name, value):
+ return queryset.filter(**{name: '<' + value + '>'})
+
+
class CoverLetterFilterSet(TimestampMixin, BaseFilterSet):
project = ProjectFilter(queryset=Project.objects.all(), distinct=False)
@@ -192,6 +196,7 @@ class CoverLetterFilterSet(TimestampMixin, BaseFilterSet):
series = BaseFilter(queryset=Project.objects.all(),
widget=MultipleHiddenInput, distinct=False)
submitter = PersonFilter(queryset=Person.objects.all(), distinct=False)
+ msgid = CharFilter(method=msgid_filter)
class Meta:
model = CoverLetter
@@ -210,17 +215,18 @@ class PatchFilterSet(TimestampMixin, BaseFilterSet):
delegate = UserFilter(queryset=User.objects.all(), distinct=False)
state = StateFilter(queryset=State.objects.all(), distinct=False)
hash = CharFilter(lookup_expr='iexact')
+ msgid = CharFilter(method=msgid_filter)
class Meta:
model = Patch
- # NOTE(dja): ideally we want to version the hash field, but I cannot
- # find a way to do that which is reliable and not extremely ugly.
+ # NOTE(dja): ideally we want to version the hash/msgid field, but I
+ # can't find a way to do that which is reliable and not extremely ugly.
# The best I can come up with is manually working with request.GET
# which seems to rather defeat the point of using django-filters.
fields = ('project', 'series', 'submitter', 'delegate',
- 'state', 'archived', 'hash')
+ 'state', 'archived', 'hash', 'msgid')
versioned_fields = {
- '1.2': ('hash', ),
+ '1.2': ('hash', 'msgid'),
}
diff --git a/patchwork/tests/api/test_cover.py b/patchwork/tests/api/test_cover.py
index 5eeb190..1b19ded 100644
--- a/patchwork/tests/api/test_cover.py
+++ b/patchwork/tests/api/test_cover.py
@@ -111,6 +111,18 @@ class TestCoverLetterAPI(utils.APITestCase):
'submitter': 'test@example.org'})
self.assertEqual(0, len(resp.data))
+ def test_list_filter_msgid(self):
+ """Filter covers by msgid."""
+ cover = create_cover()
+
+ resp = self.client.get(self.api_url(), {'msgid': cover.url_msgid})
+ self.assertEqual([cover.id], [x['id'] for x in resp.data])
+
+ # empty response if nothing matches
+ resp = self.client.get(self.api_url(), {
+ 'msgid': 'fishfish@fish.fish'})
+ self.assertEqual(0, len(resp.data))
+
@utils.store_samples('cover-list-1-0')
def test_list_version_1_0(self):
create_cover()
diff --git a/patchwork/tests/api/test_patch.py b/patchwork/tests/api/test_patch.py
index b24c5ab..da2dd6e 100644
--- a/patchwork/tests/api/test_patch.py
+++ b/patchwork/tests/api/test_patch.py
@@ -199,6 +199,18 @@ class TestPatchAPI(utils.APITestCase):
{'hash': 'garbagevalue'})
self.assertEqual(1, len(resp.data))
+ def test_list_filter_msgid(self):
+ """Filter patches by msgid."""
+ patch = self._create_patch()
+
+ resp = self.client.get(self.api_url(), {'msgid': patch.url_msgid})
+ self.assertEqual([patch.id], [x['id'] for x in resp.data])
+
+ # empty response if nothing matches
+ resp = self.client.get(self.api_url(), {
+ 'msgid': 'fishfish@fish.fish'})
+ self.assertEqual(0, len(resp.data))
+
@utils.store_samples('patch-list-1-0')
def test_list_version_1_0(self):
"""List patches using API v1.0."""
diff --git a/releasenotes/notes/rest-filter-msgid-41f693cd4e53cf93.yaml b/releasenotes/notes/rest-filter-msgid-41f693cd4e53cf93.yaml
new file mode 100644
index 0000000..0fcbbeb
--- /dev/null
+++ b/releasenotes/notes/rest-filter-msgid-41f693cd4e53cf93.yaml
@@ -0,0 +1,6 @@
+---
+api:
+ - |
+ The REST API now supports filtering patches and cover letters by message
+ ID, using the ``msgid`` query parameter. Don't include leading or trailing
+ angle brackets.