get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 109317,
    "url": "http://patches.dpdk.org/api/patches/109317/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20220406151903.2916254-19-juraj.linkes@pantheon.tech/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20220406151903.2916254-19-juraj.linkes@pantheon.tech>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20220406151903.2916254-19-juraj.linkes@pantheon.tech",
    "date": "2022-04-06T15:18:58",
    "name": "[RFC,v1,18/23] dts: merge DTS framework/flow/flow.py to DPDK",
    "commit_ref": null,
    "pull_url": null,
    "state": "rfc",
    "archived": true,
    "hash": "9fb4e7bd9fe0bd387f0f32adc9ce5b283bac0a08",
    "submitter": {
        "id": 1626,
        "url": "http://patches.dpdk.org/api/people/1626/?format=api",
        "name": "Juraj Linkeš",
        "email": "juraj.linkes@pantheon.tech"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20220406151903.2916254-19-juraj.linkes@pantheon.tech/mbox/",
    "series": [
        {
            "id": 22381,
            "url": "http://patches.dpdk.org/api/series/22381/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=22381",
            "date": "2022-04-06T15:18:40",
            "name": "merge DTS test resource files to DPDK",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/22381/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/109317/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/109317/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 04A0CA0509;\n\tWed,  6 Apr 2022 17:21:20 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id DF77B42969;\n\tWed,  6 Apr 2022 17:19:28 +0200 (CEST)",
            "from lb.pantheon.sk (lb.pantheon.sk [46.229.239.20])\n by mails.dpdk.org (Postfix) with ESMTP id F2A5542957\n for <dev@dpdk.org>; Wed,  6 Apr 2022 17:19:25 +0200 (CEST)",
            "from localhost (localhost [127.0.0.1])\n by lb.pantheon.sk (Postfix) with ESMTP id 52542184FEE;\n Wed,  6 Apr 2022 17:19:25 +0200 (CEST)",
            "from lb.pantheon.sk ([127.0.0.1])\n by localhost (lb.pantheon.sk [127.0.0.1]) (amavisd-new, port 10024)\n with ESMTP id iX-ZShZt_vkV; Wed,  6 Apr 2022 17:19:24 +0200 (CEST)",
            "from entguard.lab.pantheon.local (unknown [46.229.239.141])\n by lb.pantheon.sk (Postfix) with ESMTP id EBFC0184FF8;\n Wed,  6 Apr 2022 17:19:14 +0200 (CEST)"
        ],
        "X-Virus-Scanned": "amavisd-new at siecit.sk",
        "From": "=?utf-8?q?Juraj_Linke=C5=A1?= <juraj.linkes@pantheon.tech>",
        "To": "thomas@monjalon.net, david.marchand@redhat.com,\n Honnappa.Nagarahalli@arm.com, ohilyard@iol.unh.edu, lijuan.tu@intel.com",
        "Cc": "dev@dpdk.org, =?utf-8?q?Juraj_Linke=C5=A1?= <juraj.linkes@pantheon.tech>",
        "Subject": "[RFC PATCH v1 18/23] dts: merge DTS framework/flow/flow.py to DPDK",
        "Date": "Wed,  6 Apr 2022 15:18:58 +0000",
        "Message-Id": "<20220406151903.2916254-19-juraj.linkes@pantheon.tech>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20220406151903.2916254-1-juraj.linkes@pantheon.tech>",
        "References": "<20220406151903.2916254-1-juraj.linkes@pantheon.tech>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "---\n dts/framework/flow/flow.py | 223 +++++++++++++++++++++++++++++++++++++\n 1 file changed, 223 insertions(+)\n create mode 100644 dts/framework/flow/flow.py",
    "diff": "diff --git a/dts/framework/flow/flow.py b/dts/framework/flow/flow.py\nnew file mode 100644\nindex 0000000000..e80e69a991\n--- /dev/null\n+++ b/dts/framework/flow/flow.py\n@@ -0,0 +1,223 @@\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 FrozenSet, Iterable, List, Tuple, Union\n+\n+from scapy.layers.l2 import Ether\n+from scapy.packet import Raw\n+\n+from .enums import FlowActionType, FlowItemType\n+from .exceptions import InvalidFlowItemException\n+from .flow_action_items import ActionFlowItem\n+from .flow_items import FlowItem\n+from .flow_pattern_items import TUNNELING_PROTOCOLS, PatternFlowItem\n+\n+# Get reserved mac addresses\n+NEVER_MATCH_PACKET = Ether(src=\"\", dst=\"\") / Raw(\"\\x00\" * 64)\n+\n+\n+def _iterable_deep_compare(i1, i2):\n+    return reduce(lambda x, y: x and y, map(lambda x, y: x == y, i1, i2), True)\n+\n+\n+def expand_pattern_list_with_iterable_replacing_item(\n+    patterns: List[Iterable[FlowItem]],\n+    it: Iterable[Tuple[FlowItem, FrozenSet[str], FrozenSet[str], str]],\n+    item,\n+):\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(\n+        map(\n+            lambda pattern: (\n+                pattern[: pattern.index(item)],\n+                pattern[pattern.index(item) + 1 :],\n+            ),\n+            filter(lambda pattern: item in pattern, patterns),\n+        )\n+    )\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__(\n+        self,\n+        action_items=None,\n+        pattern_items=None,\n+    ):\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(\n+                pattern_items=[*self.pattern_items, *item.pattern_items],\n+                action_items=[*self.action_items, *item.action_items],\n+            )\n+        elif isinstance(item, PatternFlowItem):\n+            if len(self.pattern_items) == 0:\n+                return Flow(\n+                    pattern_items=[*self.pattern_items, item],\n+                    action_items=[*self.action_items],\n+                )\n+            elif item.type in self.pattern_items[-1].valid_next_items:\n+                return Flow(\n+                    pattern_items=[*self.pattern_items, item],\n+                    action_items=[*self.action_items],\n+                )\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(\n+                    pattern_items=[*self.pattern_items],\n+                    action_items=[*self.action_items, item],\n+                )\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(\n+                pattern_items=[*self.pattern_items],\n+                action_items=[*self.action_items, item],\n+            )\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+\n+    def __repr__(self):\n+        return str(self)\n+\n+    def __eq__(self, other):\n+        return (\n+            isinstance(other, Flow)\n+            and len(self.action_items) == len(other.action_items)\n+            and len(self.pattern_items) == len(other.pattern_items)\n+            and _iterable_deep_compare(self.pattern_items, other.pattern_items)\n+            and _iterable_deep_compare(self.action_items, other.action_items)\n+        )\n+\n+    def to_scapy_packet(self):\n+        return reduce(\n+            operator.truediv, map(lambda x: x.to_scapy_packet(), self.pattern_items)\n+        )\n+\n+    def get_test_property_flows(\n+        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(\n+            filter(lambda i: type(i) in TUNNELING_PROTOCOLS, base_pattern_items)\n+        )\n+        if len(tunnelling_protocols) > 0:\n+            test_flows = expand_pattern_list_with_iterable_replacing_item(\n+                [*test_flows],\n+                tunnelling_protocols[0].get_property_stream(),\n+                tunnelling_protocols[0],\n+            )\n+        else:\n+            test_flows = expand_pattern_list_with_iterable_replacing_item(\n+                [*test_flows],\n+                self.pattern_items[-1].get_property_stream(),\n+                self.pattern_items[-1],\n+            )\n+        for pattern in test_flows:\n+            yield Flow(\n+                pattern_items=pattern[0], action_items=base_action_items\n+            ), *pattern[1:]\n",
    "prefixes": [
        "RFC",
        "v1",
        "18/23"
    ]
}