get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 82027,
    "url": "https://patches.dpdk.org/api/patches/82027/?format=api",
    "web_url": "https://patches.dpdk.org/project/dts/patch/20201023232903.37387-3-ohilyard@iol.unh.edu/",
    "project": {
        "id": 3,
        "url": "https://patches.dpdk.org/api/projects/3/?format=api",
        "name": "DTS",
        "link_name": "dts",
        "list_id": "dts.dpdk.org",
        "list_email": "dts@dpdk.org",
        "web_url": "",
        "scm_url": "git://dpdk.org/tools/dts",
        "webscm_url": "http://git.dpdk.org/tools/dts/",
        "list_archive_url": "https://inbox.dpdk.org/dts",
        "list_archive_url_format": "https://inbox.dpdk.org/dts/{}",
        "commit_url_format": ""
    },
    "msgid": "<20201023232903.37387-3-ohilyard@iol.unh.edu>",
    "list_archive_url": "https://inbox.dpdk.org/dts/20201023232903.37387-3-ohilyard@iol.unh.edu",
    "date": "2020-10-23T23:28:58",
    "name": "[v2,3/7] rte flow: Add base flow type",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "343d01c9624f48e6cf56c79874f6d0c123b12c42",
    "submitter": {
        "id": 1829,
        "url": "https://patches.dpdk.org/api/people/1829/?format=api",
        "name": "Owen Hilyard",
        "email": "ohilyard@iol.unh.edu"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dts/patch/20201023232903.37387-3-ohilyard@iol.unh.edu/mbox/",
    "series": [
        {
            "id": 13289,
            "url": "https://patches.dpdk.org/api/series/13289/?format=api",
            "web_url": "https://patches.dpdk.org/project/dts/list/?series=13289",
            "date": "2020-10-23T23:28:57",
            "name": "[v2,1/7] rte flow: add test plan and test suite",
            "version": 2,
            "mbox": "https://patches.dpdk.org/series/13289/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/82027/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/82027/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dts-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 386DDA04DD;\n\tSat, 24 Oct 2020 01:29:23 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id B330A685C;\n\tSat, 24 Oct 2020 01:29:21 +0200 (CEST)",
            "from mail-qk1-f194.google.com (mail-qk1-f194.google.com\n [209.85.222.194]) by dpdk.org (Postfix) with ESMTP id 1C841B62\n for <dts@dpdk.org>; Sat, 24 Oct 2020 01:29:21 +0200 (CEST)",
            "by mail-qk1-f194.google.com with SMTP id s14so3087797qkg.11\n for <dts@dpdk.org>; Fri, 23 Oct 2020 16:29:21 -0700 (PDT)",
            "from ohilyard-Alienware-m17.iol.unh.edu (nt-238-66.w4.unh.edu.\n [132.177.238.66])\n by smtp.googlemail.com with ESMTPSA id j16sm1851673qkg.26.2020.10.23.16.29.18\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Fri, 23 Oct 2020 16:29:19 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=iol.unh.edu;\n s=unh-iol;\n h=from:to:cc:subject:date:message-id:in-reply-to:references\n :mime-version:content-transfer-encoding;\n bh=jGOyub4+liwUc1MR0l+4Y/FREf3/hGgyDpj6auij8qk=;\n b=U9Jyz8Y41C1jk7F0gTXQEA638rR3CE9YYzDEE9Y97c9lNie7vEwPlpo3Ncv5RXWvnG\n 3TRqZLg1XtVoQzhnsuODwEZP1+1FzTZzuu0p4/QF/Ki7GegudpwUnuIEROqVoQBqzDDy\n o1ipTXSAmgLA/s4wLICD41sqgWKdqP2lThUdw=",
        "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=jGOyub4+liwUc1MR0l+4Y/FREf3/hGgyDpj6auij8qk=;\n b=c08AXZGJjAgXNbwtFa7F7j/yOVWZVp4EngPTNSFnchMzfKivwWR9o0DF0pPNCHUZeF\n PFW/ePc0edtRNRRlI/mtY3t1ft7c4p+6Q8x11xtCh00MZBtgu9vifwFW+UVup/5fZjYJ\n q2C+DY1vi3lyW4Y3gLnGbzOUu+d/5SxzbcH51pTdaThgMfkVFXjwChCqbqplBhawZnrS\n doZa2lnLpQqVHL8o3dp3HtPh+c54CEgXphQPOcBA9ZwWd/uLr7YMe6a0JiWqtgCUzgy4\n mVdH26LsXez+ucbohiQxIp1dyG46G1YgbotAzwtrPE9SeLgQXC3gafkaKDqeQpeTer5h\n xRjQ==",
        "X-Gm-Message-State": "AOAM532hZNMIaQ2yzSFC7RFeT5cXUrFyenFuGRJi0JSJRtYOAL95907U\n JBWgQQ92ylSvjRXIdoHbRCigcA==",
        "X-Google-Smtp-Source": "\n ABdhPJxnYao5y9swhG/EE+rU/YvbsdTst+Dptfj9oHcyn8C7mA9EegpJpTaIitlOafDLwXXpSAI+vQ==",
        "X-Received": "by 2002:a37:6285:: with SMTP id\n w127mr4767241qkb.454.1603495759452;\n Fri, 23 Oct 2020 16:29:19 -0700 (PDT)",
        "From": "Owen Hilyard <ohilyard@iol.unh.edu>",
        "To": "ohilyard@iol.unh.edu,\n\tdts@dpdk.org,\n\tlijuan.tu@intel.com",
        "Cc": "shall@iol.unh.edu, lihongx.ma@intel.com, lylavoie@iol.unh.edu,\n zhaoyan.chen@intel.com, yuan.peng@intel.com",
        "Date": "Fri, 23 Oct 2020 19:28:58 -0400",
        "Message-Id": "<20201023232903.37387-3-ohilyard@iol.unh.edu>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20201023232903.37387-2-ohilyard@iol.unh.edu>",
        "References": "\n <CAHx6DYCAyA9iXe18+1xd-JqH0N7DKu0fF=ts=bJ3WU_eV1H1Rw@mail.gmail.com>\n <20201023232903.37387-1-ohilyard@iol.unh.edu>\n <20201023232903.37387-2-ohilyard@iol.unh.edu>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dts] [PATCH v2 3/7] rte flow: Add base flow type",
        "X-BeenThere": "dts@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "test suite reviews and discussions <dts.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dts>,\n <mailto:dts-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dts/>",
        "List-Post": "<mailto:dts@dpdk.org>",
        "List-Help": "<mailto:dts-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dts>,\n <mailto:dts-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dts-bounces@dpdk.org",
        "Sender": "\"dts\" <dts-bounces@dpdk.org>"
    },
    "content": "This type acts as a generic base for all flows.\n\nSigned-off-by: Owen Hilyard <ohilyard@iol.unh.edu>\n---\n framework/flow/flow.py | 186 +++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 186 insertions(+)\n create mode 100644 framework/flow/flow.py",
    "diff": "diff --git a/framework/flow/flow.py b/framework/flow/flow.py\nnew file mode 100644\nindex 0000000..2cce079\n--- /dev/null\n+++ b/framework/flow/flow.py\n@@ -0,0 +1,186 @@\n+# BSD LICENSE\n+#\n+# Copyright(c) 2020 Intel Corporation. All rights reserved.\n+# Copyright © 2018[, 2019] The University of New Hampshire. All rights reserved.\n+# All rights reserved.\n+#\n+# Redistribution and use in source and binary forms, with or without\n+# modification, are permitted provided that the following conditions\n+# are met:\n+#\n+#   * Redistributions of source code must retain the above copyright\n+#     notice, this list of conditions and the following disclaimer.\n+#   * Redistributions in binary form must reproduce the above copyright\n+#     notice, this list of conditions and the following disclaimer in\n+#     the documentation and/or other materials provided with the\n+#     distribution.\n+#   * Neither the name of Intel Corporation nor the names of its\n+#     contributors may be used to endorse or promote products derived\n+#     from this software without specific prior written permission.\n+#\n+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+\n+from __future__ import annotations\n+\n+import copy\n+import itertools\n+import operator\n+from functools import reduce\n+from typing import List, FrozenSet, Union, Iterable, Tuple\n+\n+from scapy.layers.l2 import Ether\n+\n+from flow.enums import FlowItemType, FlowActionType\n+from flow.exceptions import InvalidFlowItemException\n+from flow.flow_action_items import ActionFlowItem\n+from flow.flow_items import FlowItem\n+from flow.flow_pattern_items import PatternFlowItem, TUNNELING_PROTOCOLS\n+\n+# Get reserved mac addresses\n+NEVER_MATCH_PACKET = Ether(src=\"\", dst=\"\") / ('\\x00' * 64)\n+\n+\n+def _iterable_deep_compare(i1, i2):\n+    return reduce(\n+        lambda x, y: x and y,\n+        map(lambda x, y: x == y, i1, i2),\n+        True\n+    )\n+\n+\n+def expand_pattern_list_with_iterable_replacing_item(patterns: List[Iterable[FlowItem]],\n+                                                     it: Iterable[Tuple[FlowItem, FrozenSet[str], FrozenSet[str], str]],\n+                                                     item):\n+    \"\"\"\n+    This function takes a list of patterns and splits each of them into 2\n+    parts, excluding the item at index. It then uses the provided\n+    iterator to fill in that value for all patterns.\n+\n+    Ex:\n+    if patterns is [['a', 'b', 'c'], ['c','b','a']], it is [1,2], and item is 'b',\n+    then this function will produce\n+\n+    [['a', 1], ['a', 2], ['a', 1], ['a', 2], ['a', 1], ['a', 2]]\n+\n+    if everything is converted into a list. It is not converted\n+    because that requires using the memory to store all of this at\n+    the same time, which could be fairly large.\n+    \"\"\"\n+\n+    split_patterns = list(map(lambda pattern: (pattern[:pattern.index(item)], pattern[pattern.index(item) + 1:],),\n+                              filter(lambda pattern: item in pattern, patterns)))\n+    # Tee the iterators so I can consume all of them\n+\n+    iterators = itertools.tee(it, len(patterns))\n+    for pattern_before, pattern_after in split_patterns:\n+        for iterator in iterators:\n+            for dataset in iterator:\n+                backup_dataset = copy.deepcopy(dataset)\n+                yield (\n+                    [*pattern_before, backup_dataset[0], *pattern_after],\n+                    *backup_dataset[1:],\n+                )\n+            # yield from map(\n+            #     lambda flow_item_test_properties: (\n+            #         [*pattern_before, flow_item_test_properties[0], *pattern_after],\n+            #         *flow_item_test_properties[1:],\n+            #     ), iterator\n+            # )\n+\n+    yield from filter(lambda pattern: item not in pattern, patterns)\n+\n+\n+class Flow(object):\n+    action_items: List[ActionFlowItem]\n+    pattern_items: List[PatternFlowItem]\n+    entry_points: FrozenSet[FlowItemType]\n+\n+    def __init__(self, action_items=None, pattern_items=None, ):\n+        if action_items is None:\n+            action_items = []\n+\n+        if pattern_items is None:\n+            pattern_items = []\n+\n+        self.action_items = action_items\n+        self.pattern_items = pattern_items\n+\n+    def __truediv__(self, item: Union[FlowItem, Flow]):\n+        \"\"\"\n+        Used in a similar way to scapy's packet composition. Returns a new flow with the mutated state.\n+        @param item: The other flow item.\n+        @return: A Flow containing both items\n+        \"\"\"\n+        if isinstance(item, Flow):\n+            return Flow(pattern_items=[*self.pattern_items, *item.pattern_items],\n+                        action_items=[*self.action_items, *item.action_items])\n+        elif isinstance(item, PatternFlowItem):\n+            if len(self.pattern_items) == 0:\n+                return Flow(pattern_items=[*self.pattern_items, item], action_items=[*self.action_items])\n+            elif item.type in self.pattern_items[-1].valid_next_items:\n+                return Flow(pattern_items=[*self.pattern_items, item], action_items=[*self.action_items])\n+            else:\n+                raise InvalidFlowItemException(self.pattern_items[-1], item, flow=self)\n+        elif isinstance(item, ActionFlowItem):\n+            if len(self.action_items) == 0:\n+                return Flow(pattern_items=[*self.pattern_items], action_items=[*self.action_items, item])\n+\n+            for action in self.action_items:\n+                if item.type not in action.allowed_with:\n+                    raise InvalidFlowItemException(action, item, flow=self)\n+            return Flow(pattern_items=[*self.pattern_items], action_items=[*self.action_items, item])\n+\n+    def __str__(self):\n+        return f\"ingress pattern %s actions queue index 1 / end\" % (\n+                    \" / \".join(str(item) for item in self.pattern_items) + \" / end\")\n+\n+    def __repr__(self):\n+        return str(self)\n+\n+    def __eq__(self, other):\n+        return isinstance(other, Flow) and \\\n+               len(self.action_items) == len(other.action_items) and \\\n+               len(self.pattern_items) == len(other.pattern_items) and \\\n+               _iterable_deep_compare(self.pattern_items, other.pattern_items) and \\\n+               _iterable_deep_compare(self.action_items, other.action_items)\n+\n+    def to_scapy_packet(self):\n+        return reduce(operator.truediv, map(lambda x: x.to_scapy_packet(), self.pattern_items))\n+\n+    def get_test_property_flows(self, pattern_item_types_to_update=None, action_item_types_to_update=None) -> \\\n+            Iterable[Flow]:\n+        if pattern_item_types_to_update is None and action_item_types_to_update is None:\n+            pattern_item_types_to_update = [self.pattern_items[-1]]\n+        elif pattern_item_types_to_update is None:\n+            pattern_item_types_to_update = []\n+        elif action_item_types_to_update is None:\n+            action_item_types_to_update = []\n+\n+        # So that if this object is mutated before the generator is finished, it won't change anything\n+        base_pattern_items = copy.deepcopy(self.pattern_items)\n+        base_action_items = copy.deepcopy(self.action_items)\n+\n+        test_flows: Iterable[Iterable[FlowItem]] = [base_pattern_items]\n+\n+        tunnelling_protocols = list(filter(lambda i: type(i) in TUNNELING_PROTOCOLS, base_pattern_items))\n+        if len(tunnelling_protocols) > 0:\n+            test_flows = expand_pattern_list_with_iterable_replacing_item([*test_flows],\n+                                                                          tunnelling_protocols[0].get_property_stream(),\n+                                                                          tunnelling_protocols[0])\n+        else:\n+            test_flows = expand_pattern_list_with_iterable_replacing_item([*test_flows],\n+                                                                          self.pattern_items[\n+                                                                              -1].get_property_stream(),\n+                                                                          self.pattern_items[-1])\n+        for pattern in test_flows:\n+            yield Flow(pattern_items=pattern[0], action_items=base_action_items), *pattern[1:]\n",
    "prefixes": [
        "v2",
        "3/7"
    ]
}