DPDK patches and discussions
 help / color / mirror / Atom feed
From: Luca Vizzarro <luca.vizzarro@arm.com>
To: dev@dpdk.org
Cc: "Juraj Linkeš" <juraj.linkes@pantheon.tech>,
	"Jeremy Spewock" <jspewock@iol.unh.edu>,
	"Luca Vizzarro" <luca.vizzarro@arm.com>,
	"Paul Szczepanek" <paul.szczepanek@arm.com>
Subject: [PATCH v4 2/3] dts: clean up config types
Date: Tue, 14 May 2024 13:05:01 +0100	[thread overview]
Message-ID: <20240514120502.1955468-3-luca.vizzarro@arm.com> (raw)
In-Reply-To: <20240514120502.1955468-1-luca.vizzarro@arm.com>

Clean up types used with the configuration classes, and use Self from
the newly added typing_extensions module.

Methods that instantiate their own class should be @classmethod instead
of @staticmethod.

Bugzilla ID: 1433

Signed-off-by: Luca Vizzarro <luca.vizzarro@arm.com>
Reviewed-by: Paul Szczepanek <paul.szczepanek@arm.com>
---
 dts/framework/config/__init__.py              | 47 ++++++++++---------
 .../traffic_generator/__init__.py             | 10 ++--
 dts/poetry.lock                               |  2 +-
 dts/pyproject.toml                            |  1 +
 4 files changed, 32 insertions(+), 28 deletions(-)

diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index 6b2ad2b16d..41b2fbc94d 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -42,6 +42,7 @@
 
 import warlock  # type: ignore[import-untyped]
 import yaml
+from typing_extensions import Self
 
 from framework.config.types import (
     BuildTargetConfigDict,
@@ -156,8 +157,8 @@ class PortConfig:
     peer_node: str
     peer_pci: str
 
-    @staticmethod
-    def from_dict(node: str, d: PortConfigDict) -> "PortConfig":
+    @classmethod
+    def from_dict(cls, node: str, d: PortConfigDict) -> Self:
         """A convenience method that creates the object from fewer inputs.
 
         Args:
@@ -167,7 +168,7 @@ def from_dict(node: str, d: PortConfigDict) -> "PortConfig":
         Returns:
             The port configuration instance.
         """
-        return PortConfig(node=node, **d)
+        return cls(node=node, **d)
 
 
 @dataclass(slots=True, frozen=True)
@@ -183,7 +184,7 @@ class TrafficGeneratorConfig:
     traffic_generator_type: TrafficGeneratorType
 
     @staticmethod
-    def from_dict(d: TrafficGeneratorConfigDict) -> "ScapyTrafficGeneratorConfig":
+    def from_dict(d: TrafficGeneratorConfigDict) -> "TrafficGeneratorConfig":
         """A convenience method that produces traffic generator config of the proper type.
 
         Args:
@@ -312,7 +313,7 @@ class TGNodeConfiguration(NodeConfiguration):
         traffic_generator: The configuration of the traffic generator present on the TG node.
     """
 
-    traffic_generator: ScapyTrafficGeneratorConfig
+    traffic_generator: TrafficGeneratorConfig
 
 
 @dataclass(slots=True, frozen=True)
@@ -356,8 +357,8 @@ class BuildTargetConfiguration:
     compiler_wrapper: str
     name: str
 
-    @staticmethod
-    def from_dict(d: BuildTargetConfigDict) -> "BuildTargetConfiguration":
+    @classmethod
+    def from_dict(cls, d: BuildTargetConfigDict) -> Self:
         r"""A convenience method that processes the inputs before creating an instance.
 
         `arch`, `os`, `cpu` and `compiler` are converted to :class:`Enum`\s and
@@ -369,7 +370,7 @@ def from_dict(d: BuildTargetConfigDict) -> "BuildTargetConfiguration":
         Returns:
             The build target configuration instance.
         """
-        return BuildTargetConfiguration(
+        return cls(
             arch=Architecture(d["arch"]),
             os=OS(d["os"]),
             cpu=CPUType(d["cpu"]),
@@ -407,10 +408,11 @@ class TestSuiteConfig:
     test_suite: str
     test_cases: list[str]
 
-    @staticmethod
+    @classmethod
     def from_dict(
+        cls,
         entry: str | TestSuiteConfigDict,
-    ) -> "TestSuiteConfig":
+    ) -> Self:
         """Create an instance from two different types.
 
         Args:
@@ -420,9 +422,9 @@ def from_dict(
             The test suite configuration instance.
         """
         if isinstance(entry, str):
-            return TestSuiteConfig(test_suite=entry, test_cases=[])
+            return cls(test_suite=entry, test_cases=[])
         elif isinstance(entry, dict):
-            return TestSuiteConfig(test_suite=entry["suite"], test_cases=entry["cases"])
+            return cls(test_suite=entry["suite"], test_cases=entry["cases"])
         else:
             raise TypeError(f"{type(entry)} is not valid for a test suite config.")
 
@@ -454,11 +456,12 @@ class ExecutionConfiguration:
     traffic_generator_node: TGNodeConfiguration
     vdevs: list[str]
 
-    @staticmethod
+    @classmethod
     def from_dict(
+        cls,
         d: ExecutionConfigDict,
-        node_map: dict[str, Union[SutNodeConfiguration | TGNodeConfiguration]],
-    ) -> "ExecutionConfiguration":
+        node_map: dict[str, SutNodeConfiguration | TGNodeConfiguration],
+    ) -> Self:
         """A convenience method that processes the inputs before creating an instance.
 
         The build target and the test suite config are transformed into their respective objects.
@@ -494,7 +497,7 @@ def from_dict(
         vdevs = (
             d["system_under_test_node"]["vdevs"] if "vdevs" in d["system_under_test_node"] else []
         )
-        return ExecutionConfiguration(
+        return cls(
             build_targets=build_targets,
             perf=d["perf"],
             func=d["func"],
@@ -505,7 +508,7 @@ def from_dict(
             vdevs=vdevs,
         )
 
-    def copy_and_modify(self, **kwargs) -> "ExecutionConfiguration":
+    def copy_and_modify(self, **kwargs) -> Self:
         """Create a shallow copy with any of the fields modified.
 
         The only new data are those passed to this method.
@@ -525,7 +528,7 @@ def copy_and_modify(self, **kwargs) -> "ExecutionConfiguration":
             else:
                 new_config[field.name] = getattr(self, field.name)
 
-        return ExecutionConfiguration(**new_config)
+        return type(self)(**new_config)
 
 
 @dataclass(slots=True, frozen=True)
@@ -541,8 +544,8 @@ class Configuration:
 
     executions: list[ExecutionConfiguration]
 
-    @staticmethod
-    def from_dict(d: ConfigurationDict) -> "Configuration":
+    @classmethod
+    def from_dict(cls, d: ConfigurationDict) -> Self:
         """A convenience method that processes the inputs before creating an instance.
 
         Build target and test suite config are transformed into their respective objects.
@@ -555,7 +558,7 @@ def from_dict(d: ConfigurationDict) -> "Configuration":
         Returns:
             The whole configuration instance.
         """
-        nodes: list[Union[SutNodeConfiguration | TGNodeConfiguration]] = list(
+        nodes: list[SutNodeConfiguration | TGNodeConfiguration] = list(
             map(NodeConfiguration.from_dict, d["nodes"])
         )
         assert len(nodes) > 0, "There must be a node to test"
@@ -567,7 +570,7 @@ def from_dict(d: ConfigurationDict) -> "Configuration":
             map(ExecutionConfiguration.from_dict, d["executions"], [node_map for _ in d])
         )
 
-        return Configuration(executions=executions)
+        return cls(executions=executions)
 
 
 def load_config(config_file_path: Path) -> Configuration:
diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/framework/testbed_model/traffic_generator/__init__.py
index 0eaf0355cd..03e57a77fc 100644
--- a/dts/framework/testbed_model/traffic_generator/__init__.py
+++ b/dts/framework/testbed_model/traffic_generator/__init__.py
@@ -16,7 +16,7 @@
 
 # pylama:ignore=W0611
 
-from framework.config import ScapyTrafficGeneratorConfig, TrafficGeneratorType
+from framework.config import ScapyTrafficGeneratorConfig, TrafficGeneratorConfig
 from framework.exception import ConfigurationError
 from framework.testbed_model.node import Node
 
@@ -28,7 +28,7 @@
 
 
 def create_traffic_generator(
-    tg_node: Node, traffic_generator_config: ScapyTrafficGeneratorConfig
+    tg_node: Node, traffic_generator_config: TrafficGeneratorConfig
 ) -> CapturingTrafficGenerator:
     """The factory function for creating traffic generator objects from the test run configuration.
 
@@ -39,10 +39,10 @@ def create_traffic_generator(
     Returns:
         A traffic generator capable of capturing received packets.
     """
-    match traffic_generator_config.traffic_generator_type:
-        case TrafficGeneratorType.SCAPY:
+    match traffic_generator_config:
+        case ScapyTrafficGeneratorConfig():
             return ScapyTrafficGenerator(tg_node, traffic_generator_config)
         case _:
             raise ConfigurationError(
-                "Unknown traffic generator: {traffic_generator_config.traffic_generator_type}"
+                f"Unknown traffic generator: {traffic_generator_config.traffic_generator_type}"
             )
diff --git a/dts/poetry.lock b/dts/poetry.lock
index df9cecb7e0..5f8fa03933 100644
--- a/dts/poetry.lock
+++ b/dts/poetry.lock
@@ -853,4 +853,4 @@ jsonschema = ">=4,<5"
 [metadata]
 lock-version = "2.0"
 python-versions = "^3.10"
-content-hash = "1572cb14f0bf88cddc6b6b225312ad468d01916b32067d17a7776af76c6d466c"
+content-hash = "4af4dd49c59e5bd6ed99e8c19c6756aaf00125339d26cfad2ef98551dc765f8b"
diff --git a/dts/pyproject.toml b/dts/pyproject.toml
index 05c91ef9be..a160d2fa02 100644
--- a/dts/pyproject.toml
+++ b/dts/pyproject.toml
@@ -26,6 +26,7 @@ types-PyYAML = "^6.0.8"
 fabric = "^2.7.1"
 scapy = "^2.5.0"
 pydocstyle = "6.1.1"
+typing-extensions = "^4.11.0"
 
 [tool.poetry.group.dev.dependencies]
 mypy = "^1.10.0"
-- 
2.34.1


  parent reply	other threads:[~2024-05-14 12:05 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-22 18:26 [PATCH 0/4] dts: error and usage improvements Luca Vizzarro
2024-01-22 18:26 ` [PATCH 1/4] dts: constrain DPDK source flag Luca Vizzarro
2024-01-29 11:47   ` Juraj Linkeš
2024-02-23 19:09     ` Luca Vizzarro
2024-03-01 10:22       ` Juraj Linkeš
2024-01-22 18:26 ` [PATCH 2/4] dts: customise argparse error message Luca Vizzarro
2024-01-29 13:04   ` Juraj Linkeš
2024-02-23 19:12     ` Luca Vizzarro
2024-02-26  9:09       ` Juraj Linkeš
2024-01-22 18:26 ` [PATCH 3/4] dts: show help when DTS is ran without args Luca Vizzarro
2024-01-22 18:26 ` [PATCH 4/4] dts: log stderr with failed remote commands Luca Vizzarro
2024-01-29 13:10   ` Juraj Linkeš
2024-02-23 19:19     ` Luca Vizzarro
2024-02-26  9:05       ` Juraj Linkeš
2024-03-18 17:17 ` [PATCH v2 0/3] dts: error and usage improvements Luca Vizzarro
2024-03-18 17:17   ` [PATCH v2 1/3] dts: rework arguments framework Luca Vizzarro
2024-04-04  9:25     ` Juraj Linkeš
2024-04-09 15:14       ` Luca Vizzarro
2024-04-10  9:46         ` Juraj Linkeš
2024-03-18 17:17   ` [PATCH v2 2/3] dts: constrain DPDK source argument Luca Vizzarro
2024-03-18 17:17   ` [PATCH v2 3/3] dts: store stderr in RemoteCommandExecutionError Luca Vizzarro
2024-05-14 11:44   ` [PATCH v3 0/3] error and usage improvements Luca Vizzarro
2024-05-14 11:44     ` [PATCH v3 1/3] dts: rework arguments framework Luca Vizzarro
2024-05-14 11:55       ` [PATCH v3] " Luca Vizzarro
2024-05-14 11:44     ` [PATCH v3 2/3] dts: constrain DPDK source argument Luca Vizzarro
2024-05-14 11:44     ` [PATCH v3 3/3] dts: store stderr in RemoteCommandExecutionError Luca Vizzarro
2024-05-14 12:04 ` [PATCH v4 0/3] error and usage improvements Luca Vizzarro
2024-05-14 12:05   ` [PATCH v4 1/3] dts: update mypy static checker Luca Vizzarro
2024-05-14 12:05   ` Luca Vizzarro [this message]
2024-05-14 12:05   ` [PATCH v4 3/3] dts: rework arguments framework Luca Vizzarro
2024-05-14 12:10 ` [PATCH v5 0/3] error and usage improvements Luca Vizzarro
2024-05-14 12:10   ` [PATCH v5 1/3] dts: rework arguments framework Luca Vizzarro
2024-05-30 15:30     ` Juraj Linkeš
2024-05-30 18:43       ` Luca Vizzarro
2024-05-31  9:04         ` Juraj Linkeš
2024-05-14 12:10   ` [PATCH v5 2/3] dts: constrain DPDK source argument Luca Vizzarro
2024-05-30 15:41     ` Juraj Linkeš
2024-05-30 18:46       ` Luca Vizzarro
2024-05-14 12:10   ` [PATCH v5 3/3] dts: store stderr in RemoteCommandExecutionError Luca Vizzarro
2024-05-30 15:47     ` Juraj Linkeš
2024-05-30 18:48       ` Luca Vizzarro
2024-05-14 15:26   ` [PATCH v5 0/3] error and usage improvements Luca Vizzarro
2024-05-31 11:20 ` [PATCH v6 " Luca Vizzarro
2024-05-31 11:20   ` [PATCH v6 1/3] dts: rework arguments framework Luca Vizzarro
2024-05-31 12:49     ` Juraj Linkeš
2024-06-14 13:55     ` Jeremy Spewock
2024-05-31 11:20   ` [PATCH v6 2/3] dts: constrain DPDK source argument Luca Vizzarro
2024-05-31 12:50     ` Juraj Linkeš
2024-06-14 13:56       ` Jeremy Spewock
2024-05-31 11:20   ` [PATCH v6 3/3] dts: store stderr in RemoteCommandExecutionError Luca Vizzarro
2024-05-31 12:51     ` Juraj Linkeš
2024-06-14 13:56       ` Jeremy Spewock
2024-06-20  0:24   ` [PATCH v6 0/3] error and usage improvements Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240514120502.1955468-3-luca.vizzarro@arm.com \
    --to=luca.vizzarro@arm.com \
    --cc=dev@dpdk.org \
    --cc=jspewock@iol.unh.edu \
    --cc=juraj.linkes@pantheon.tech \
    --cc=paul.szczepanek@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).