From patchwork Tue May 14 12:05:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luca Vizzarro X-Patchwork-Id: 140061 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id 39EEC4402B; Tue, 14 May 2024 14:05:25 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 504DA4067D; Tue, 14 May 2024 14:05:14 +0200 (CEST) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mails.dpdk.org (Postfix) with ESMTP id 4A3D2402F2 for ; Tue, 14 May 2024 14:05:12 +0200 (CEST) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id BE0661042; Tue, 14 May 2024 05:05:36 -0700 (PDT) Received: from localhost.localdomain (unknown [10.57.4.224]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id EC6AB3F641; Tue, 14 May 2024 05:05:10 -0700 (PDT) From: Luca Vizzarro To: dev@dpdk.org Cc: =?utf-8?q?Juraj_Linke=C5=A1?= , Jeremy Spewock , Luca Vizzarro , Paul Szczepanek Subject: [PATCH v4 2/3] dts: clean up config types Date: Tue, 14 May 2024 13:05:01 +0100 Message-Id: <20240514120502.1955468-3-luca.vizzarro@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240514120502.1955468-1-luca.vizzarro@arm.com> References: <20240122182611.1904974-1-luca.vizzarro@arm.com> <20240514120502.1955468-1-luca.vizzarro@arm.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org 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 Reviewed-by: Paul Szczepanek --- 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"