Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1270129/?format=api
https://patchwork.ozlabs.org/api/patches/1270129/?format=api", "web_url": "https://patchwork.ozlabs.org/project/patchwork/patch/20200414062102.6798-3-dja@axtens.net/", "project": { "id": 16, "url": "https://patchwork.ozlabs.org/api/projects/16/?format=api", "name": "Patchwork", "link_name": "patchwork", "list_id": "patchwork.lists.ozlabs.org", "list_email": "patchwork@lists.ozlabs.org", "web_url": "http://jk.ozlabs.org/projects/patchwork/", "scm_url": "git://github.com/getpatchwork/patchwork", "webscm_url": "https://github.com/getpatchwork/patchwork", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20200414062102.6798-3-dja@axtens.net>", "list_archive_url": null, "date": "2020-04-14T06:21:02", "name": "[2/2] api: allow filtering patches and covers by msgid", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "35621a9b0e149d7ee9cbb626991811d508ea7a25", "submitter": { "id": 65792, "url": "https://patchwork.ozlabs.org/api/people/65792/?format=api", "name": "Daniel Axtens", "email": "dja@axtens.net" }, "delegate": null, "mbox": "https://patchwork.ozlabs.org/project/patchwork/patch/20200414062102.6798-3-dja@axtens.net/mbox/", "series": [ { "id": 170086, "url": "https://patchwork.ozlabs.org/api/series/170086/?format=api", "web_url": "https://patchwork.ozlabs.org/project/patchwork/list/?series=170086", "date": "2020-04-14T06:21:00", "name": "v2.2 fixups for OzLabs", "version": 1, "mbox": "https://patchwork.ozlabs.org/series/170086/mbox/" } ], "comments": "https://patchwork.ozlabs.org/api/patches/1270129/comments/", "check": "pending", "checks": "https://patchwork.ozlabs.org/api/patches/1270129/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "patchwork@lists.ozlabs.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "patchwork@lists.ozlabs.org" ], "Received": [ "from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (4096 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 491b4T4gh0z9s71\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 14 Apr 2020 16:22:17 +1000 (AEST)", "from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 491b4R4Vg8zDqWw\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 14 Apr 2020 16:22:15 +1000 (AEST)", "from mail-pj1-x1041.google.com (mail-pj1-x1041.google.com\n [IPv6:2607:f8b0:4864:20::1041])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by lists.ozlabs.org (Postfix) with ESMTPS id 491b3K3xjzzDqTL\n for <patchwork@lists.ozlabs.org>; Tue, 14 Apr 2020 16:21:17 +1000 (AEST)", "by mail-pj1-x1041.google.com with SMTP id mn19so4798786pjb.0\n for <patchwork@lists.ozlabs.org>; Mon, 13 Apr 2020 23:21:17 -0700 (PDT)", "from localhost\n (2001-44b8-1113-6700-65ed-ce52-e9b0-0e8c.static.ipv6.internode.on.net.\n [2001:44b8:1113:6700:65ed:ce52:e9b0:e8c])\n by smtp.gmail.com with ESMTPSA id q63sm1127445pfb.178.2020.04.13.23.21.12\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Mon, 13 Apr 2020 23:21:13 -0700 (PDT)" ], "Authentication-Results": [ "ozlabs.org;\n dmarc=none (p=none dis=none) header.from=axtens.net", "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=axtens.net header.i=@axtens.net header.a=rsa-sha256\n header.s=google header.b=iPX+Yz5D;\n\tdkim-atps=neutral", "lists.ozlabs.org; spf=pass (sender SPF authorized)\n smtp.mailfrom=axtens.net (client-ip=2607:f8b0:4864:20::1041;\n helo=mail-pj1-x1041.google.com; envelope-from=dja@axtens.net;\n receiver=<UNKNOWN>)", "lists.ozlabs.org;\n dmarc=none (p=none dis=none) header.from=axtens.net", "lists.ozlabs.org; dkim=pass (1024-bit key;\n unprotected) header.d=axtens.net header.i=@axtens.net header.a=rsa-sha256\n header.s=google header.b=iPX+Yz5D; dkim-atps=neutral" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=axtens.net; s=google;\n h=from:to:cc:subject:date:message-id:in-reply-to:references\n :mime-version:content-transfer-encoding;\n bh=mi1ZClZg5nzBCZ/0N8U9CBWAZlsb9xwB81QDZX+eBuI=;\n b=iPX+Yz5DoQFXNjLneM+UykOQc7uejn+FtjwMRHLtgut+e/jxCJbtNemmrkVA/38U2c\n t1X02TT81sNaymW1DemjmjPoPxu0sSLAt2iXzpVmIRzRyPXCWZ9JLZtM6ZNk0S/+5nSY\n 3ba8ICmCig4O8cjqP1Q0GGrlXRwLpMkFQFnyc=", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20161025;\n h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n :references:mime-version:content-transfer-encoding;\n bh=mi1ZClZg5nzBCZ/0N8U9CBWAZlsb9xwB81QDZX+eBuI=;\n b=pMOQ7Z/fBuci5O1AIGPRG8yrxE8aVhppZhlTq0PBcpzTS4OHOQYxj4Kkt6Kt0/YAx2\n 8XyObKi9pd24dnQXT+rjCPJwOSJmdgsebkAlxqLAjJTJ4uIn6GAgHxFCVGBhzfQn5Vyo\n sWnv/0TT/ZgykLij+fxJwEr/HusblwcAz9QHZG+4xpNsiEjZbe2Xzt7t2soKQCoOeTBn\n j8aMFjsKvIrXEonqMP5QnLmKQgv7A0PWb5i/x7zXnJCps5nuP+OyPAhfg1f1zAM36/J6\n bj5LRKvmwj5EpXoWsD96DmepKSX1MS/7ghTbhe/8dTqQ91YB0cIiOyMNYVg0VMDxmfcs\n OnBA==", "X-Gm-Message-State": "AGi0PuZugW2vb33+enhMGegPT26lJe7zS5X5y8YwO52uTM97AgxG5N9T\n T6DB7BZ3tVaeAdPV+jx7coDZlOO7wTY=", "X-Google-Smtp-Source": "\n APiQypJl2Ras5wETAIEw9orW1mrS/xrrpA+5lVhQCCpl5FtdnQf/WL3Ye4PbUbW9btVApAmLXuaqPg==", "X-Received": "by 2002:a17:90a:364c:: with SMTP id\n s70mr25652975pjb.143.1586845274133;\n Mon, 13 Apr 2020 23:21:14 -0700 (PDT)", "From": "Daniel Axtens <dja@axtens.net>", "To": "patchwork@lists.ozlabs.org", "Subject": "[PATCH 2/2] api: allow filtering patches and covers by msgid", "Date": "Tue, 14 Apr 2020 16:21:02 +1000", "Message-Id": "<20200414062102.6798-3-dja@axtens.net>", "X-Mailer": "git-send-email 2.20.1", "In-Reply-To": "<20200414062102.6798-1-dja@axtens.net>", "References": "<20200414062102.6798-1-dja@axtens.net>", "MIME-Version": "1.0", "X-BeenThere": "patchwork@lists.ozlabs.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "Patchwork development <patchwork.lists.ozlabs.org>", "List-Unsubscribe": "<https://lists.ozlabs.org/options/patchwork>,\n <mailto:patchwork-request@lists.ozlabs.org?subject=unsubscribe>", "List-Archive": "<http://lists.ozlabs.org/pipermail/patchwork/>", "List-Post": "<mailto:patchwork@lists.ozlabs.org>", "List-Help": "<mailto:patchwork-request@lists.ozlabs.org?subject=help>", "List-Subscribe": "<https://lists.ozlabs.org/listinfo/patchwork>,\n <mailto:patchwork-request@lists.ozlabs.org?subject=subscribe>", "Cc": "Michael Ellerman <mpe@ellerman.id.au>, jk@ozlabs.org", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org", "Sender": "\"Patchwork\"\n <patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>" }, "content": "In the process of fixing the previous bug, I realised that:\n\n a) /api/patches/msgid is a perfectly reasonable thing to attempt\n b) We have no way of finding a patch by message id in the API\n\nWe can't actualy make /api/patches/msgid work because it may not\nbe unique, but we can add a filter.\n\nI'm shoehorning this into stable/2.2, even though it's technically\nan API change: it's minor, not incompatible and in hindsight a\nglaring hole.\n\nCc: Michael Ellerman <mpe@ellerman.id.au>\nSigned-off-by: Daniel Axtens <dja@axtens.net>\n---\n docs/api/schemas/latest/patchwork.yaml | 16 ++++++++++++++++\n docs/api/schemas/patchwork.j2 | 18 ++++++++++++++++++\n docs/api/schemas/v1.2/patchwork.yaml | 16 ++++++++++++++++\n patchwork/api/filters.py | 14 ++++++++++----\n patchwork/tests/api/test_cover.py | 12 ++++++++++++\n patchwork/tests/api/test_patch.py | 12 ++++++++++++\n .../rest-filter-msgid-41f693cd4e53cf93.yaml | 6 ++++++\n 7 files changed, 90 insertions(+), 4 deletions(-)\n create mode 100644 releasenotes/notes/rest-filter-msgid-41f693cd4e53cf93.yaml", "diff": "diff --git a/docs/api/schemas/latest/patchwork.yaml b/docs/api/schemas/latest/patchwork.yaml\nindex 13cdc9cd78fd..cc0d97e696b6 100644\n--- a/docs/api/schemas/latest/patchwork.yaml\n+++ b/docs/api/schemas/latest/patchwork.yaml\n@@ -246,6 +246,14 @@ paths:\n schema:\n title: ''\n type: string\n+ - in: query\n+ name: msgid\n+ description: >\n+ The cover message-id as a case-sensitive string, without leading or\n+ trailing angle brackets, to filter by.\n+ schema:\n+ title: ''\n+ type: string\n responses:\n '200':\n description: ''\n@@ -474,6 +482,14 @@ paths:\n schema:\n title: ''\n type: string\n+ - in: query\n+ name: msgid\n+ description: >\n+ The patch message-id as a case-sensitive string, without leading or\n+ trailing angle brackets, to filter by.\n+ schema:\n+ title: ''\n+ type: string\n responses:\n '200':\n description: ''\ndiff --git a/docs/api/schemas/patchwork.j2 b/docs/api/schemas/patchwork.j2\nindex bd714d5e7a2a..f5618d41faa0 100644\n--- a/docs/api/schemas/patchwork.j2\n+++ b/docs/api/schemas/patchwork.j2\n@@ -251,6 +251,16 @@ paths:\n schema:\n title: ''\n type: string\n+{% if version >= (1, 2) %}\n+ - in: query\n+ name: msgid\n+ description: >\n+ The cover message-id as a case-sensitive string, without leading or\n+ trailing angle brackets, to filter by.\n+ schema:\n+ title: ''\n+ type: string\n+{% endif %}\n responses:\n '200':\n description: ''\n@@ -488,6 +498,14 @@ paths:\n schema:\n title: ''\n type: string\n+ - in: query\n+ name: msgid\n+ description: >\n+ The patch message-id as a case-sensitive string, without leading or\n+ trailing angle brackets, to filter by.\n+ schema:\n+ title: ''\n+ type: string\n {% endif %}\n responses:\n '200':\ndiff --git a/docs/api/schemas/v1.2/patchwork.yaml b/docs/api/schemas/v1.2/patchwork.yaml\nindex db2ed122eec2..7bdbe66997c0 100644\n--- a/docs/api/schemas/v1.2/patchwork.yaml\n+++ b/docs/api/schemas/v1.2/patchwork.yaml\n@@ -246,6 +246,14 @@ paths:\n schema:\n title: ''\n type: string\n+ - in: query\n+ name: msgid\n+ description: >\n+ The cover message-id as a case-sensitive string, without leading or\n+ trailing angle brackets, to filter by.\n+ schema:\n+ title: ''\n+ type: string\n responses:\n '200':\n description: ''\n@@ -474,6 +482,14 @@ paths:\n schema:\n title: ''\n type: string\n+ - in: query\n+ name: msgid\n+ description: >\n+ The patch message-id as a case-sensitive string, without leading or\n+ trailing angle brackets, to filter by.\n+ schema:\n+ title: ''\n+ type: string\n responses:\n '200':\n description: ''\ndiff --git a/patchwork/api/filters.py b/patchwork/api/filters.py\nindex deb5ace11880..93e6281bf5e6 100644\n--- a/patchwork/api/filters.py\n+++ b/patchwork/api/filters.py\n@@ -184,6 +184,10 @@ class SeriesFilterSet(TimestampMixin, BaseFilterSet):\n fields = ('submitter', 'project')\n \n \n+def msgid_filter(queryset, name, value):\n+ return queryset.filter(**{name: '<' + value + '>'})\n+\n+\n class CoverLetterFilterSet(TimestampMixin, BaseFilterSet):\n \n project = ProjectFilter(queryset=Project.objects.all(), distinct=False)\n@@ -192,6 +196,7 @@ class CoverLetterFilterSet(TimestampMixin, BaseFilterSet):\n series = BaseFilter(queryset=Project.objects.all(),\n widget=MultipleHiddenInput, distinct=False)\n submitter = PersonFilter(queryset=Person.objects.all(), distinct=False)\n+ msgid = CharFilter(method=msgid_filter)\n \n class Meta:\n model = CoverLetter\n@@ -210,17 +215,18 @@ class PatchFilterSet(TimestampMixin, BaseFilterSet):\n delegate = UserFilter(queryset=User.objects.all(), distinct=False)\n state = StateFilter(queryset=State.objects.all(), distinct=False)\n hash = CharFilter(lookup_expr='iexact')\n+ msgid = CharFilter(method=msgid_filter)\n \n class Meta:\n model = Patch\n- # NOTE(dja): ideally we want to version the hash field, but I cannot\n- # find a way to do that which is reliable and not extremely ugly.\n+ # NOTE(dja): ideally we want to version the hash/msgid field, but I\n+ # can't find a way to do that which is reliable and not extremely ugly.\n # The best I can come up with is manually working with request.GET\n # which seems to rather defeat the point of using django-filters.\n fields = ('project', 'series', 'submitter', 'delegate',\n- 'state', 'archived', 'hash')\n+ 'state', 'archived', 'hash', 'msgid')\n versioned_fields = {\n- '1.2': ('hash', ),\n+ '1.2': ('hash', 'msgid'),\n }\n \n \ndiff --git a/patchwork/tests/api/test_cover.py b/patchwork/tests/api/test_cover.py\nindex 5eeb1902e1d1..1b19ded1b4d5 100644\n--- a/patchwork/tests/api/test_cover.py\n+++ b/patchwork/tests/api/test_cover.py\n@@ -111,6 +111,18 @@ class TestCoverLetterAPI(utils.APITestCase):\n 'submitter': 'test@example.org'})\n self.assertEqual(0, len(resp.data))\n \n+ def test_list_filter_msgid(self):\n+ \"\"\"Filter covers by msgid.\"\"\"\n+ cover = create_cover()\n+\n+ resp = self.client.get(self.api_url(), {'msgid': cover.url_msgid})\n+ self.assertEqual([cover.id], [x['id'] for x in resp.data])\n+\n+ # empty response if nothing matches\n+ resp = self.client.get(self.api_url(), {\n+ 'msgid': 'fishfish@fish.fish'})\n+ self.assertEqual(0, len(resp.data))\n+\n @utils.store_samples('cover-list-1-0')\n def test_list_version_1_0(self):\n create_cover()\ndiff --git a/patchwork/tests/api/test_patch.py b/patchwork/tests/api/test_patch.py\nindex b24c5ab28947..da2dd6e9084b 100644\n--- a/patchwork/tests/api/test_patch.py\n+++ b/patchwork/tests/api/test_patch.py\n@@ -199,6 +199,18 @@ class TestPatchAPI(utils.APITestCase):\n {'hash': 'garbagevalue'})\n self.assertEqual(1, len(resp.data))\n \n+ def test_list_filter_msgid(self):\n+ \"\"\"Filter patches by msgid.\"\"\"\n+ patch = self._create_patch()\n+\n+ resp = self.client.get(self.api_url(), {'msgid': patch.url_msgid})\n+ self.assertEqual([patch.id], [x['id'] for x in resp.data])\n+\n+ # empty response if nothing matches\n+ resp = self.client.get(self.api_url(), {\n+ 'msgid': 'fishfish@fish.fish'})\n+ self.assertEqual(0, len(resp.data))\n+\n @utils.store_samples('patch-list-1-0')\n def test_list_version_1_0(self):\n \"\"\"List patches using API v1.0.\"\"\"\ndiff --git a/releasenotes/notes/rest-filter-msgid-41f693cd4e53cf93.yaml b/releasenotes/notes/rest-filter-msgid-41f693cd4e53cf93.yaml\nnew file mode 100644\nindex 000000000000..0fcbbeb8a736\n--- /dev/null\n+++ b/releasenotes/notes/rest-filter-msgid-41f693cd4e53cf93.yaml\n@@ -0,0 +1,6 @@\n+---\n+api:\n+ - |\n+ The REST API now supports filtering patches and cover letters by message\n+ ID, using the ``msgid`` query parameter. Don't include leading or trailing\n+ angle brackets.\n", "prefixes": [ "2/2" ] }{ "id": 1270129, "url": "