get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 140055,
    "url": "https://patches.dpdk.org/api/patches/140055/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20240514113446.1948050-3-luca.vizzarro@arm.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<20240514113446.1948050-3-luca.vizzarro@arm.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20240514113446.1948050-3-luca.vizzarro@arm.com",
    "date": "2024-05-14T11:34:46",
    "name": "[v2,2/2] dts: clean up config types",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "3fa62ec005702b7602f88351dbcd0fff3aff7b4f",
    "submitter": {
        "id": 3197,
        "url": "https://patches.dpdk.org/api/people/3197/?format=api",
        "name": "Luca Vizzarro",
        "email": "luca.vizzarro@arm.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20240514113446.1948050-3-luca.vizzarro@arm.com/mbox/",
    "series": [
        {
            "id": 31920,
            "url": "https://patches.dpdk.org/api/series/31920/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=31920",
            "date": "2024-05-14T11:34:44",
            "name": "dts: update mypy and clean up",
            "version": 2,
            "mbox": "https://patches.dpdk.org/series/31920/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/140055/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/140055/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 4F1944402B;\n\tTue, 14 May 2024 13:35:13 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 421F540698;\n\tTue, 14 May 2024 13:34:59 +0200 (CEST)",
            "from foss.arm.com (foss.arm.com [217.140.110.172])\n by mails.dpdk.org (Postfix) with ESMTP id AE83B40649\n for <dev@dpdk.org>; Tue, 14 May 2024 13:34:56 +0200 (CEST)",
            "from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14])\n by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id E54C51042;\n Tue, 14 May 2024 04:35:20 -0700 (PDT)",
            "from localhost.localdomain (unknown [10.57.4.224])\n by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 1AE4F3F641;\n Tue, 14 May 2024 04:34:54 -0700 (PDT)"
        ],
        "From": "Luca Vizzarro <luca.vizzarro@arm.com>",
        "To": "dev@dpdk.org",
        "Cc": "Luca Vizzarro <luca.vizzarro@arm.com>,\n =?utf-8?q?Juraj_Linke=C5=A1?= <juraj.linkes@pantheon.tech>,\n Jeremy Spewock <jspewock@iol.unh.edu>,\n Paul Szczepanek <paul.szczepanek@arm.com>",
        "Subject": "[PATCH v2 2/2] dts: clean up config types",
        "Date": "Tue, 14 May 2024 12:34:46 +0100",
        "Message-Id": "<20240514113446.1948050-3-luca.vizzarro@arm.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20240514113446.1948050-1-luca.vizzarro@arm.com>",
        "References": "<20240509105704.1162449-1-luca.vizzarro@arm.com>\n <20240514113446.1948050-1-luca.vizzarro@arm.com>",
        "MIME-Version": "1.0",
        "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": "Clean up types used with the configuration classes, and use Self from\nthe newly added typing_extensions module.\n\nMethods that instantiate their own class should be @classmethod instead\nof @staticmethod.\n\nBugzilla ID: 1433\n\nSigned-off-by: Luca Vizzarro <luca.vizzarro@arm.com>\nReviewed-by: Paul Szczepanek <paul.szczepanek@arm.com>\n---\n dts/framework/config/__init__.py              | 47 ++++++++++---------\n .../traffic_generator/__init__.py             | 10 ++--\n dts/poetry.lock                               |  2 +-\n dts/pyproject.toml                            |  1 +\n 4 files changed, 32 insertions(+), 28 deletions(-)",
    "diff": "diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py\nindex 6b2ad2b16d..41b2fbc94d 100644\n--- a/dts/framework/config/__init__.py\n+++ b/dts/framework/config/__init__.py\n@@ -42,6 +42,7 @@\n \n import warlock  # type: ignore[import-untyped]\n import yaml\n+from typing_extensions import Self\n \n from framework.config.types import (\n     BuildTargetConfigDict,\n@@ -156,8 +157,8 @@ class PortConfig:\n     peer_node: str\n     peer_pci: str\n \n-    @staticmethod\n-    def from_dict(node: str, d: PortConfigDict) -> \"PortConfig\":\n+    @classmethod\n+    def from_dict(cls, node: str, d: PortConfigDict) -> Self:\n         \"\"\"A convenience method that creates the object from fewer inputs.\n \n         Args:\n@@ -167,7 +168,7 @@ def from_dict(node: str, d: PortConfigDict) -> \"PortConfig\":\n         Returns:\n             The port configuration instance.\n         \"\"\"\n-        return PortConfig(node=node, **d)\n+        return cls(node=node, **d)\n \n \n @dataclass(slots=True, frozen=True)\n@@ -183,7 +184,7 @@ class TrafficGeneratorConfig:\n     traffic_generator_type: TrafficGeneratorType\n \n     @staticmethod\n-    def from_dict(d: TrafficGeneratorConfigDict) -> \"ScapyTrafficGeneratorConfig\":\n+    def from_dict(d: TrafficGeneratorConfigDict) -> \"TrafficGeneratorConfig\":\n         \"\"\"A convenience method that produces traffic generator config of the proper type.\n \n         Args:\n@@ -312,7 +313,7 @@ class TGNodeConfiguration(NodeConfiguration):\n         traffic_generator: The configuration of the traffic generator present on the TG node.\n     \"\"\"\n \n-    traffic_generator: ScapyTrafficGeneratorConfig\n+    traffic_generator: TrafficGeneratorConfig\n \n \n @dataclass(slots=True, frozen=True)\n@@ -356,8 +357,8 @@ class BuildTargetConfiguration:\n     compiler_wrapper: str\n     name: str\n \n-    @staticmethod\n-    def from_dict(d: BuildTargetConfigDict) -> \"BuildTargetConfiguration\":\n+    @classmethod\n+    def from_dict(cls, d: BuildTargetConfigDict) -> Self:\n         r\"\"\"A convenience method that processes the inputs before creating an instance.\n \n         `arch`, `os`, `cpu` and `compiler` are converted to :class:`Enum`\\s and\n@@ -369,7 +370,7 @@ def from_dict(d: BuildTargetConfigDict) -> \"BuildTargetConfiguration\":\n         Returns:\n             The build target configuration instance.\n         \"\"\"\n-        return BuildTargetConfiguration(\n+        return cls(\n             arch=Architecture(d[\"arch\"]),\n             os=OS(d[\"os\"]),\n             cpu=CPUType(d[\"cpu\"]),\n@@ -407,10 +408,11 @@ class TestSuiteConfig:\n     test_suite: str\n     test_cases: list[str]\n \n-    @staticmethod\n+    @classmethod\n     def from_dict(\n+        cls,\n         entry: str | TestSuiteConfigDict,\n-    ) -> \"TestSuiteConfig\":\n+    ) -> Self:\n         \"\"\"Create an instance from two different types.\n \n         Args:\n@@ -420,9 +422,9 @@ def from_dict(\n             The test suite configuration instance.\n         \"\"\"\n         if isinstance(entry, str):\n-            return TestSuiteConfig(test_suite=entry, test_cases=[])\n+            return cls(test_suite=entry, test_cases=[])\n         elif isinstance(entry, dict):\n-            return TestSuiteConfig(test_suite=entry[\"suite\"], test_cases=entry[\"cases\"])\n+            return cls(test_suite=entry[\"suite\"], test_cases=entry[\"cases\"])\n         else:\n             raise TypeError(f\"{type(entry)} is not valid for a test suite config.\")\n \n@@ -454,11 +456,12 @@ class ExecutionConfiguration:\n     traffic_generator_node: TGNodeConfiguration\n     vdevs: list[str]\n \n-    @staticmethod\n+    @classmethod\n     def from_dict(\n+        cls,\n         d: ExecutionConfigDict,\n-        node_map: dict[str, Union[SutNodeConfiguration | TGNodeConfiguration]],\n-    ) -> \"ExecutionConfiguration\":\n+        node_map: dict[str, SutNodeConfiguration | TGNodeConfiguration],\n+    ) -> Self:\n         \"\"\"A convenience method that processes the inputs before creating an instance.\n \n         The build target and the test suite config are transformed into their respective objects.\n@@ -494,7 +497,7 @@ def from_dict(\n         vdevs = (\n             d[\"system_under_test_node\"][\"vdevs\"] if \"vdevs\" in d[\"system_under_test_node\"] else []\n         )\n-        return ExecutionConfiguration(\n+        return cls(\n             build_targets=build_targets,\n             perf=d[\"perf\"],\n             func=d[\"func\"],\n@@ -505,7 +508,7 @@ def from_dict(\n             vdevs=vdevs,\n         )\n \n-    def copy_and_modify(self, **kwargs) -> \"ExecutionConfiguration\":\n+    def copy_and_modify(self, **kwargs) -> Self:\n         \"\"\"Create a shallow copy with any of the fields modified.\n \n         The only new data are those passed to this method.\n@@ -525,7 +528,7 @@ def copy_and_modify(self, **kwargs) -> \"ExecutionConfiguration\":\n             else:\n                 new_config[field.name] = getattr(self, field.name)\n \n-        return ExecutionConfiguration(**new_config)\n+        return type(self)(**new_config)\n \n \n @dataclass(slots=True, frozen=True)\n@@ -541,8 +544,8 @@ class Configuration:\n \n     executions: list[ExecutionConfiguration]\n \n-    @staticmethod\n-    def from_dict(d: ConfigurationDict) -> \"Configuration\":\n+    @classmethod\n+    def from_dict(cls, d: ConfigurationDict) -> Self:\n         \"\"\"A convenience method that processes the inputs before creating an instance.\n \n         Build target and test suite config are transformed into their respective objects.\n@@ -555,7 +558,7 @@ def from_dict(d: ConfigurationDict) -> \"Configuration\":\n         Returns:\n             The whole configuration instance.\n         \"\"\"\n-        nodes: list[Union[SutNodeConfiguration | TGNodeConfiguration]] = list(\n+        nodes: list[SutNodeConfiguration | TGNodeConfiguration] = list(\n             map(NodeConfiguration.from_dict, d[\"nodes\"])\n         )\n         assert len(nodes) > 0, \"There must be a node to test\"\n@@ -567,7 +570,7 @@ def from_dict(d: ConfigurationDict) -> \"Configuration\":\n             map(ExecutionConfiguration.from_dict, d[\"executions\"], [node_map for _ in d])\n         )\n \n-        return Configuration(executions=executions)\n+        return cls(executions=executions)\n \n \n def load_config(config_file_path: Path) -> Configuration:\ndiff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/framework/testbed_model/traffic_generator/__init__.py\nindex 0eaf0355cd..03e57a77fc 100644\n--- a/dts/framework/testbed_model/traffic_generator/__init__.py\n+++ b/dts/framework/testbed_model/traffic_generator/__init__.py\n@@ -16,7 +16,7 @@\n \n # pylama:ignore=W0611\n \n-from framework.config import ScapyTrafficGeneratorConfig, TrafficGeneratorType\n+from framework.config import ScapyTrafficGeneratorConfig, TrafficGeneratorConfig\n from framework.exception import ConfigurationError\n from framework.testbed_model.node import Node\n \n@@ -28,7 +28,7 @@\n \n \n def create_traffic_generator(\n-    tg_node: Node, traffic_generator_config: ScapyTrafficGeneratorConfig\n+    tg_node: Node, traffic_generator_config: TrafficGeneratorConfig\n ) -> CapturingTrafficGenerator:\n     \"\"\"The factory function for creating traffic generator objects from the test run configuration.\n \n@@ -39,10 +39,10 @@ def create_traffic_generator(\n     Returns:\n         A traffic generator capable of capturing received packets.\n     \"\"\"\n-    match traffic_generator_config.traffic_generator_type:\n-        case TrafficGeneratorType.SCAPY:\n+    match traffic_generator_config:\n+        case ScapyTrafficGeneratorConfig():\n             return ScapyTrafficGenerator(tg_node, traffic_generator_config)\n         case _:\n             raise ConfigurationError(\n-                \"Unknown traffic generator: {traffic_generator_config.traffic_generator_type}\"\n+                f\"Unknown traffic generator: {traffic_generator_config.traffic_generator_type}\"\n             )\ndiff --git a/dts/poetry.lock b/dts/poetry.lock\nindex df9cecb7e0..5f8fa03933 100644\n--- a/dts/poetry.lock\n+++ b/dts/poetry.lock\n@@ -853,4 +853,4 @@ jsonschema = \">=4,<5\"\n [metadata]\n lock-version = \"2.0\"\n python-versions = \"^3.10\"\n-content-hash = \"1572cb14f0bf88cddc6b6b225312ad468d01916b32067d17a7776af76c6d466c\"\n+content-hash = \"4af4dd49c59e5bd6ed99e8c19c6756aaf00125339d26cfad2ef98551dc765f8b\"\ndiff --git a/dts/pyproject.toml b/dts/pyproject.toml\nindex 05c91ef9be..a160d2fa02 100644\n--- a/dts/pyproject.toml\n+++ b/dts/pyproject.toml\n@@ -26,6 +26,7 @@ types-PyYAML = \"^6.0.8\"\n fabric = \"^2.7.1\"\n scapy = \"^2.5.0\"\n pydocstyle = \"6.1.1\"\n+typing-extensions = \"^4.11.0\"\n \n [tool.poetry.group.dev.dependencies]\n mypy = \"^1.10.0\"\n",
    "prefixes": [
        "v2",
        "2/2"
    ]
}