Skip to content

Commit d08b6c7

Browse files
committed
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 <[email protected]> Tested-by: Jeremy Kerr <[email protected]> Reviewed-by: Andrew Donnellan <[email protected]> Reviewed-by: Stephen Finucane <[email protected]> Signed-off-by: Daniel Axtens <[email protected]>
1 parent 08c5856 commit d08b6c7

File tree

7 files changed

+90
-4
lines changed

7 files changed

+90
-4
lines changed

docs/api/schemas/latest/patchwork.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,14 @@ paths:
246246
schema:
247247
title: ''
248248
type: string
249+
- in: query
250+
name: msgid
251+
description: >
252+
The cover message-id as a case-sensitive string, without leading or
253+
trailing angle brackets, to filter by.
254+
schema:
255+
title: ''
256+
type: string
249257
responses:
250258
'200':
251259
description: ''
@@ -474,6 +482,14 @@ paths:
474482
schema:
475483
title: ''
476484
type: string
485+
- in: query
486+
name: msgid
487+
description: >
488+
The patch message-id as a case-sensitive string, without leading or
489+
trailing angle brackets, to filter by.
490+
schema:
491+
title: ''
492+
type: string
477493
responses:
478494
'200':
479495
description: ''

docs/api/schemas/patchwork.j2

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,16 @@ paths:
251251
schema:
252252
title: ''
253253
type: string
254+
{% if version >= (1, 2) %}
255+
- in: query
256+
name: msgid
257+
description: >
258+
The cover message-id as a case-sensitive string, without leading or
259+
trailing angle brackets, to filter by.
260+
schema:
261+
title: ''
262+
type: string
263+
{% endif %}
254264
responses:
255265
'200':
256266
description: ''
@@ -488,6 +498,14 @@ paths:
488498
schema:
489499
title: ''
490500
type: string
501+
- in: query
502+
name: msgid
503+
description: >
504+
The patch message-id as a case-sensitive string, without leading or
505+
trailing angle brackets, to filter by.
506+
schema:
507+
title: ''
508+
type: string
491509
{% endif %}
492510
responses:
493511
'200':

docs/api/schemas/v1.2/patchwork.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,14 @@ paths:
246246
schema:
247247
title: ''
248248
type: string
249+
- in: query
250+
name: msgid
251+
description: >
252+
The cover message-id as a case-sensitive string, without leading or
253+
trailing angle brackets, to filter by.
254+
schema:
255+
title: ''
256+
type: string
249257
responses:
250258
'200':
251259
description: ''
@@ -474,6 +482,14 @@ paths:
474482
schema:
475483
title: ''
476484
type: string
485+
- in: query
486+
name: msgid
487+
description: >
488+
The patch message-id as a case-sensitive string, without leading or
489+
trailing angle brackets, to filter by.
490+
schema:
491+
title: ''
492+
type: string
477493
responses:
478494
'200':
479495
description: ''

patchwork/api/filters.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ class Meta:
184184
fields = ('submitter', 'project')
185185

186186

187+
def msgid_filter(queryset, name, value):
188+
return queryset.filter(**{name: '<' + value + '>'})
189+
190+
187191
class CoverLetterFilterSet(TimestampMixin, BaseFilterSet):
188192

189193
project = ProjectFilter(queryset=Project.objects.all(), distinct=False)
@@ -192,6 +196,7 @@ class CoverLetterFilterSet(TimestampMixin, BaseFilterSet):
192196
series = BaseFilter(queryset=Project.objects.all(),
193197
widget=MultipleHiddenInput, distinct=False)
194198
submitter = PersonFilter(queryset=Person.objects.all(), distinct=False)
199+
msgid = CharFilter(method=msgid_filter)
195200

196201
class Meta:
197202
model = CoverLetter
@@ -210,17 +215,18 @@ class PatchFilterSet(TimestampMixin, BaseFilterSet):
210215
delegate = UserFilter(queryset=User.objects.all(), distinct=False)
211216
state = StateFilter(queryset=State.objects.all(), distinct=False)
212217
hash = CharFilter(lookup_expr='iexact')
218+
msgid = CharFilter(method=msgid_filter)
213219

214220
class Meta:
215221
model = Patch
216-
# NOTE(dja): ideally we want to version the hash field, but I cannot
217-
# find a way to do that which is reliable and not extremely ugly.
222+
# NOTE(dja): ideally we want to version the hash/msgid field, but I
223+
# can't find a way to do that which is reliable and not extremely ugly.
218224
# The best I can come up with is manually working with request.GET
219225
# which seems to rather defeat the point of using django-filters.
220226
fields = ('project', 'series', 'submitter', 'delegate',
221-
'state', 'archived', 'hash')
227+
'state', 'archived', 'hash', 'msgid')
222228
versioned_fields = {
223-
'1.2': ('hash', ),
229+
'1.2': ('hash', 'msgid'),
224230
}
225231

226232

patchwork/tests/api/test_cover.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,18 @@ def test_list_filter_submitter(self):
111111
'submitter': '[email protected]'})
112112
self.assertEqual(0, len(resp.data))
113113

114+
def test_list_filter_msgid(self):
115+
"""Filter covers by msgid."""
116+
cover = create_cover()
117+
118+
resp = self.client.get(self.api_url(), {'msgid': cover.url_msgid})
119+
self.assertEqual([cover.id], [x['id'] for x in resp.data])
120+
121+
# empty response if nothing matches
122+
resp = self.client.get(self.api_url(), {
123+
'msgid': '[email protected]'})
124+
self.assertEqual(0, len(resp.data))
125+
114126
@utils.store_samples('cover-list-1-0')
115127
def test_list_version_1_0(self):
116128
create_cover()

patchwork/tests/api/test_patch.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,18 @@ def test_list_filter_hash_version_1_1(self):
199199
{'hash': 'garbagevalue'})
200200
self.assertEqual(1, len(resp.data))
201201

202+
def test_list_filter_msgid(self):
203+
"""Filter patches by msgid."""
204+
patch = self._create_patch()
205+
206+
resp = self.client.get(self.api_url(), {'msgid': patch.url_msgid})
207+
self.assertEqual([patch.id], [x['id'] for x in resp.data])
208+
209+
# empty response if nothing matches
210+
resp = self.client.get(self.api_url(), {
211+
'msgid': '[email protected]'})
212+
self.assertEqual(0, len(resp.data))
213+
202214
@utils.store_samples('patch-list-1-0')
203215
def test_list_version_1_0(self):
204216
"""List patches using API v1.0."""
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
api:
3+
- |
4+
The REST API now supports filtering patches and cover letters by message
5+
ID, using the ``msgid`` query parameter. Don't include leading or trailing
6+
angle brackets.

0 commit comments

Comments
 (0)