get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/1558019/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 1558019,
    "url": "http://patchwork.ozlabs.org/api/patches/1558019/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/openvswitch/patch/20211122112256.2011194-4-amorenoz@redhat.com/",
    "project": {
        "id": 47,
        "url": "http://patchwork.ozlabs.org/api/projects/47/?format=api",
        "name": "Open vSwitch",
        "link_name": "openvswitch",
        "list_id": "ovs-dev.openvswitch.org",
        "list_email": "ovs-dev@openvswitch.org",
        "web_url": "http://openvswitch.org/",
        "scm_url": "git@github.com:openvswitch/ovs.git",
        "webscm_url": "https://github.com/openvswitch/ovs",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20211122112256.2011194-4-amorenoz@redhat.com>",
    "list_archive_url": null,
    "date": "2021-11-22T11:22:41",
    "name": "[ovs-dev,v1,03/18] python: add list parser",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": false,
    "hash": "86de44db0190a4f468f6653f8f7381ab11ff83f1",
    "submitter": {
        "id": 77477,
        "url": "http://patchwork.ozlabs.org/api/people/77477/?format=api",
        "name": "Adrian Moreno",
        "email": "amorenoz@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/openvswitch/patch/20211122112256.2011194-4-amorenoz@redhat.com/mbox/",
    "series": [
        {
            "id": 273222,
            "url": "http://patchwork.ozlabs.org/api/series/273222/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/openvswitch/list/?series=273222",
            "date": "2021-11-22T11:22:39",
            "name": "python: add flow parsing library",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/273222/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/1558019/comments/",
    "check": "fail",
    "checks": "http://patchwork.ozlabs.org/api/patches/1558019/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<ovs-dev-bounces@openvswitch.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "dev@openvswitch.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@bilbo.ozlabs.org",
            "ovs-dev@lists.linuxfoundation.org"
        ],
        "Authentication-Results": [
            "bilbo.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=ArNsYlJe;\n\tdkim-atps=neutral",
            "ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN>)",
            "smtp4.osuosl.org (amavisd-new);\n dkim=pass (1024-bit key) header.d=redhat.com",
            "relay.mimecast.com;\n auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=amorenoz@redhat.com"
        ],
        "Received": [
            "from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138])\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) server-digest\n SHA256)\n\t(No client certificate requested)\n\tby bilbo.ozlabs.org (Postfix) with ESMTPS id 4HyPyz3rqZz9sXN\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 22 Nov 2021 22:23:23 +1100 (AEDT)",
            "from localhost (localhost [127.0.0.1])\n\tby smtp1.osuosl.org (Postfix) with ESMTP id 4BC9380F48;\n\tMon, 22 Nov 2021 11:23:20 +0000 (UTC)",
            "from smtp1.osuosl.org ([127.0.0.1])\n\tby localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id OtwZaBSYw_Vs; Mon, 22 Nov 2021 11:23:18 +0000 (UTC)",
            "from lists.linuxfoundation.org (lf-lists.osuosl.org\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby smtp1.osuosl.org (Postfix) with ESMTPS id 80F9D80F1E;\n\tMon, 22 Nov 2021 11:23:16 +0000 (UTC)",
            "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 282FDC002F;\n\tMon, 22 Nov 2021 11:23:16 +0000 (UTC)",
            "from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137])\n by lists.linuxfoundation.org (Postfix) with ESMTP id A2A2FC0012\n for <dev@openvswitch.org>; Mon, 22 Nov 2021 11:23:12 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n by smtp4.osuosl.org (Postfix) with ESMTP id 761DF401D2\n for <dev@openvswitch.org>; Mon, 22 Nov 2021 11:23:11 +0000 (UTC)",
            "from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n with ESMTP id WgN1Wr9l7Cnd for <dev@openvswitch.org>;\n Mon, 22 Nov 2021 11:23:10 +0000 (UTC)",
            "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by smtp4.osuosl.org (Postfix) with ESMTPS id AAE2D401F2\n for <dev@openvswitch.org>; Mon, 22 Nov 2021 11:23:10 +0000 (UTC)",
            "from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com\n [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n us-mta-213-mqJgP6Y0M4ukabKWUw1hkA-1; Mon, 22 Nov 2021 06:23:08 -0500",
            "from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com\n [10.5.11.13])\n (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n (No client certificate requested)\n by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2EDB81006AA5\n for <dev@openvswitch.org>; Mon, 22 Nov 2021 11:23:07 +0000 (UTC)",
            "from amorenoz.users.ipa.redhat.com (unknown [10.2.16.196])\n by smtp.corp.redhat.com (Postfix) with ESMTP id 360815BAE0;\n Mon, 22 Nov 2021 11:23:06 +0000 (UTC)"
        ],
        "X-Virus-Scanned": [
            "amavisd-new at osuosl.org",
            "amavisd-new at osuosl.org"
        ],
        "X-Greylist": "domain auto-whitelisted by SQLgrey-1.8.0",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1637580189;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=thNfj2AYZMazGpkvXz5ZjUj1m0gOjSwwXt+ZRnnzqmY=;\n b=ArNsYlJeCmFzNbSUfE5/o/qkx6o4qZyi2MLGDukLmxReU3t4zMeKUqml0M9wf34Sy5QiHM\n o4MF2SS3HFkDt2khWMTG1uSnO4jav/G1IgPi+RxIe3PcvdrCt0X3S5+SCV6+0EecyxVrOY\n vePtMSAu9jmbgp1OU2cCS55qdeKwSC8=",
        "X-MC-Unique": "mqJgP6Y0M4ukabKWUw1hkA-1",
        "From": "Adrian Moreno <amorenoz@redhat.com>",
        "To": "dev@openvswitch.org",
        "Date": "Mon, 22 Nov 2021 12:22:41 +0100",
        "Message-Id": "<20211122112256.2011194-4-amorenoz@redhat.com>",
        "In-Reply-To": "<20211122112256.2011194-1-amorenoz@redhat.com>",
        "References": "<20211122112256.2011194-1-amorenoz@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 2.79 on 10.5.11.13",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-Originator": "redhat.com",
        "Subject": "[ovs-dev] [PATCH v1 03/18] python: add list parser",
        "X-BeenThere": "ovs-dev@openvswitch.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "<ovs-dev.openvswitch.org>",
        "List-Unsubscribe": "<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>",
        "List-Archive": "<http://mail.openvswitch.org/pipermail/ovs-dev/>",
        "List-Post": "<mailto:ovs-dev@openvswitch.org>",
        "List-Help": "<mailto:ovs-dev-request@openvswitch.org?subject=help>",
        "List-Subscribe": "<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "ovs-dev-bounces@openvswitch.org",
        "Sender": "\"dev\" <ovs-dev-bounces@openvswitch.org>"
    },
    "content": "Some openflow or dpif flows encode their arguments in lists, eg:\n\"some_action(arg1,arg2,arg3)\". In order to decode this in a way that can\nbe then stored and queried, add ListParser and ListDecoders classes\nthat parse lists into KeyValue instances.\n\nThe ListParser / ListDecoders mechanism is quite similar to KVParser and\nKVDecoders. Since the \"key\" of the different KeyValue objects is now\nommited, it has to be provided by ListDecoders.\n\nFor example, take the openflow action \"resubmit\" that can be written as:\n\nresubmit([port],[table][,ct])\n\nCan be decoded by creating a ListDecoders instance such as:\n\nListDecoders([\n                (\"port\", decode_default),\n                (\"table\", decode_int),\n                (\"ct\", decode_flag),\n            ])\n\nNaturally, the order of the decoders must be kept.\n\nSigned-off-by: Adrian Moreno <amorenoz@redhat.com>\n---\n python/automake.mk       |   3 +-\n python/ovs/flows/list.py | 123 +++++++++++++++++++++++++++++++++++++++\n 2 files changed, 125 insertions(+), 1 deletion(-)\n create mode 100644 python/ovs/flows/list.py",
    "diff": "diff --git a/python/automake.mk b/python/automake.mk\nindex 13aa2b4c3..a3265292d 100644\n--- a/python/automake.mk\n+++ b/python/automake.mk\n@@ -44,7 +44,8 @@ ovs_pyfiles = \\\n \tpython/ovs/winutils.py \\\n \tpython/ovs/flows/__init__.py \\\n \tpython/ovs/flows/decoders.py \\\n-\tpython/ovs/flows/kv.py\n+\tpython/ovs/flows/kv.py \\\n+\tpython/ovs/flows/list.py\n \n # These python files are used at build time but not runtime,\n # so they are not installed.\ndiff --git a/python/ovs/flows/list.py b/python/ovs/flows/list.py\nnew file mode 100644\nindex 000000000..d7ad315a6\n--- /dev/null\n+++ b/python/ovs/flows/list.py\n@@ -0,0 +1,123 @@\n+import re\n+import functools\n+\n+from ovs.flows.kv import KeyValue, KeyMetadata, ParseError\n+from ovs.flows.decoders import decode_default\n+\n+\n+class ListDecoders:\n+    \"\"\"ListDecoders is used by ListParser to decode the elements in the list\n+\n+    A decoder is a function that accepts a value and returns its decoded\n+    object\n+    The list_decoder to be used is determined by index in the list provided to\n+    ListDecoders is important.\n+\n+    Args:\n+        decoders (list of tuples): Optional,  A list of tuples.\n+            The first element in the tuple is the keyword associated with the\n+            value. The second element in the tuple is the decoder function.\n+    \"\"\"\n+\n+    def __init__(self, decoders=None):\n+        self._decoders = decoders or list()\n+\n+    def decode(self, index, value_str):\n+        \"\"\"Decode the index'th element of the list\n+\n+        Args:\n+            index (int): the position in the list of the element ot decode\n+            value_str (str): the value string to decode\n+        \"\"\"\n+        if index < 0 or index >= len(self._decoders):\n+            return self._default_decoder(index, value_str)\n+\n+        try:\n+            key = self._decoders[index][0]\n+            value = self._decoders[index][1](value_str)\n+            return key, value\n+        except Exception as e:\n+            raise ParseError(\n+                \"Failed to decode value_str %s: %s\" % (value_str, str(e))\n+            )\n+\n+    @staticmethod\n+    def _default_decoder(index, value):\n+        key = \"elem_{}\".format(index)\n+        return key, decode_default(value)\n+\n+\n+class ListParser:\n+    \"\"\"ListParser parses a list of values and stores them as key-value pairs\n+\n+    It uses a ListDecoders instance to decode each element in the list.\n+\n+    Args:\n+        decoders (ListDecoders): Optional, the decoders to use\n+        delims (list): Optional, list of delimiters of the list. Defaults to\n+            [',']\n+    \"\"\"\n+\n+    def __init__(self, decoders=None, delims=None):\n+        self._decoders = decoders or ListDecoders()\n+        self._keyval = list()\n+        delims = delims or [\",\"]\n+        delims.append(\"$\")\n+        self._regexp = r\"({})\".format(\"|\".join(delims))\n+\n+    def kv(self):\n+        return self._keyval\n+\n+    def __iter__(self):\n+        return iter(self._keyval)\n+\n+    def parse(self, string):\n+        \"\"\"Parse the list in string\n+\n+        Args:\n+            string (str): the string to parse\n+\n+        Raises:\n+            ParseError if any parsing error occurs.\n+        \"\"\"\n+        kpos = 0\n+        index = 0\n+        while kpos < len(string) and string[kpos] != \"\\n\":\n+            split_parts = re.split(self._regexp, string[kpos:], 1)\n+            if len(split_parts) < 3:\n+                break\n+\n+            value_str = split_parts[0]\n+\n+            key, value = self._decoders.decode(index, value_str)\n+\n+            meta = KeyMetadata(\n+                kpos=kpos,\n+                vpos=kpos,\n+                kstring=value_str,\n+                vstring=value_str,\n+            )\n+            self._keyval.append(KeyValue(key, value, meta))\n+\n+            kpos += len(value_str) + 1\n+            index += 1\n+\n+\n+def decode_nested_list(decoders, delims, value):\n+    \"\"\"Extracts nested list from te string and returns it in a dictionary\n+    them in a dictionary\n+\n+    Args:\n+        decoders (ListDecoders): the ListDecoders to use.\n+        value (str): the value string to decode.\n+    \"\"\"\n+    parser = ListParser(decoders, delims)\n+    parser.parse(value)\n+    return {kv.key: kv.value for kv in parser.kv()}\n+\n+\n+def nested_list_decoder(decoders=None, delims=None):\n+    \"\"\"Helper function that creates a nested list decoder with given\n+    ListDecoders\n+    \"\"\"\n+    return functools.partial(decode_nested_list, decoders, delims)\n",
    "prefixes": [
        "ovs-dev",
        "v1",
        "03/18"
    ]
}