diff options
-rw-r--r-- | docs/api/schemas/latest/patchwork.yaml | 7 | ||||
-rw-r--r-- | docs/api/schemas/patchwork.j2 | 9 | ||||
-rw-r--r-- | docs/api/schemas/v1.2/patchwork.yaml | 7 | ||||
-rw-r--r-- | notes/rest-filter-hash-e031bd3db42eb540.yaml | 5 | ||||
-rw-r--r-- | patchwork/api/filters.py | 8 | ||||
-rw-r--r-- | patchwork/tests/api/test_patch.py | 36 |
6 files changed, 71 insertions, 1 deletions
diff --git a/docs/api/schemas/latest/patchwork.yaml b/docs/api/schemas/latest/patchwork.yaml index 4696900..6c7564b 100644 --- a/docs/api/schemas/latest/patchwork.yaml +++ b/docs/api/schemas/latest/patchwork.yaml @@ -463,6 +463,13 @@ paths: enum: - 'true' - 'false' + - in: query + name: hash + description: > + The patch hash as a case-insensitive hexadecimal string, 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 4fc100e..12a6f67 100644 --- a/docs/api/schemas/patchwork.j2 +++ b/docs/api/schemas/patchwork.j2 @@ -468,6 +468,15 @@ paths: enum: - 'true' - 'false' +{% if version >= (1, 2) %} + - in: query + name: hash + description: > + The patch hash as a case-insensitive hexadecimal string, to filter by. + schema: + title: '' + type: string +{% endif %} responses: '200': description: '' diff --git a/docs/api/schemas/v1.2/patchwork.yaml b/docs/api/schemas/v1.2/patchwork.yaml index 2ced470..7dc9579 100644 --- a/docs/api/schemas/v1.2/patchwork.yaml +++ b/docs/api/schemas/v1.2/patchwork.yaml @@ -463,6 +463,13 @@ paths: enum: - 'true' - 'false' + - in: query + name: hash + description: > + The patch hash as a case-insensitive hexadecimal string, to filter by. + schema: + title: '' + type: string responses: '200': description: '' diff --git a/notes/rest-filter-hash-e031bd3db42eb540.yaml b/notes/rest-filter-hash-e031bd3db42eb540.yaml new file mode 100644 index 0000000..b805931 --- /dev/null +++ b/notes/rest-filter-hash-e031bd3db42eb540.yaml @@ -0,0 +1,5 @@ +--- +api: + - | + The REST API now supports filtering patches by their hashes, using the + ``hash`` query parameter. diff --git a/patchwork/api/filters.py b/patchwork/api/filters.py index 37aca82..4184ee8 100644 --- a/patchwork/api/filters.py +++ b/patchwork/api/filters.py @@ -7,6 +7,7 @@ from django.contrib.auth.models import User from django.core.exceptions import ValidationError from django.db.models import Q from django_filters.rest_framework import FilterSet +from django_filters import CharFilter from django_filters import IsoDateTimeFilter from django_filters import ModelMultipleChoiceFilter from django.forms import ModelMultipleChoiceField as BaseMultipleChoiceField @@ -176,11 +177,16 @@ class PatchFilterSet(TimestampMixin, FilterSet): submitter = PersonFilter(queryset=Person.objects.all()) delegate = UserFilter(queryset=User.objects.all()) state = StateFilter(queryset=State.objects.all()) + hash = CharFilter(lookup_expr='iexact') 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. + # 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') + 'state', 'archived', 'hash') class CheckFilterSet(TimestampMixin, FilterSet): diff --git a/patchwork/tests/api/test_patch.py b/patchwork/tests/api/test_patch.py index edae985..4afc15a 100644 --- a/patchwork/tests/api/test_patch.py +++ b/patchwork/tests/api/test_patch.py @@ -22,6 +22,13 @@ from patchwork.tests.utils import create_user if settings.ENABLE_REST_API: from rest_framework import status +# a diff different from the default, required to test hash filtering +SAMPLE_DIFF = """--- /dev/null\t2019-01-01 00:00:00.000000000 +0800 ++++ a\t2019-01-01 00:00:00.000000000 +0800 +@@ -0,0 +1 @@ ++b +""" + @unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API') class TestPatchAPI(utils.APITestCase): @@ -152,6 +159,35 @@ class TestPatchAPI(utils.APITestCase): 'submitter': 'test@example.org'}) self.assertEqual(0, len(resp.data)) + def test_list_filter_hash(self): + """Filter patches by hash.""" + patch = self._create_patch() + patch_new_diff = create_patch(state=patch.state, project=patch.project, + submitter=patch.submitter, + diff=SAMPLE_DIFF) + + # check regular filtering + resp = self.client.get(self.api_url(), {'hash': patch.hash}) + self.assertEqual([patch.id], [x['id'] for x in resp.data]) + + # 2 patches with identical diffs + patch_same_diff = create_patch(state=patch.state, + project=patch.project, + submitter=patch.submitter) + resp = self.client.get(self.api_url(), {'hash': patch.hash}) + self.assertEqual([patch.id, patch_same_diff.id], + [x['id'] for x in resp.data]) + + # case insensitive matching + resp = self.client.get(self.api_url(), + {'hash': patch_new_diff.hash.upper()}) + self.assertEqual([patch_new_diff.id], [x['id'] for x in resp.data]) + + # empty response if nothing matches + resp = self.client.get(self.api_url(), { + 'hash': 'da638d0746a115000bf890fada1f02679aa282e8'}) + 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.""" |