<div dir="ltr">v5 pushed to next-dts, thanks.</div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Fri, Sep 5, 2025 at 8:41 AM Andrew Bailey <<a href="mailto:abailey@iol.unh.edu">abailey@iol.unh.edu</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Mypy does not check functions and methods that are not entirely type<br>
hinted. This prevents full checks, so they have been added where missing.<br>
Full checks revealed some typing errors, pattern matching was applied<br>
where appropriate to ensure these types were handled properly.<br>
Additionally, the linter raised an error "unable to assign to a method"<br>
that occurred within a decorator trying to manipulate the str method of<br>
a given class. This was changed to use the set_attr function to pass the<br>
linter.<br>
<br>
Signed-off-by: Andrew Bailey <<a href="mailto:abailey@iol.unh.edu" target="_blank">abailey@iol.unh.edu</a>><br>
---<br>
.mailmap | 1 +<br>
dts/framework/context.py | 10 +++---<br>
dts/framework/exception.py | 8 ++---<br>
dts/framework/logger.py | 6 ++--<br>
dts/framework/params/__init__.py | 8 ++---<br>
dts/framework/remote_session/dpdk.py | 16 ++++-----<br>
dts/framework/remote_session/dpdk_shell.py | 2 +-<br>
.../remote_session/interactive_shell.py | 6 ++--<br>
dts/framework/remote_session/python_shell.py | 2 +-<br>
.../remote_session/remote_session.py | 2 +-<br>
dts/framework/remote_session/shell_pool.py | 10 +++---<br>
dts/framework/remote_session/testpmd_shell.py | 14 ++++----<br>
dts/framework/runner.py | 2 +-<br>
dts/framework/settings.py | 11 +++---<br>
dts/framework/test_result.py | 10 +++---<br>
dts/framework/test_run.py | 36 +++++++++----------<br>
dts/framework/test_suite.py | 4 +--<br>
dts/framework/testbed_model/capability.py | 10 +++---<br>
dts/framework/testbed_model/cpu.py | 4 +--<br>
dts/framework/testbed_model/node.py | 2 +-<br>
dts/framework/testbed_model/os_session.py | 2 +-<br>
dts/framework/testbed_model/port.py | 4 +--<br>
dts/framework/testbed_model/posix_session.py | 2 +-<br>
.../testbed_model/traffic_generator/scapy.py | 14 ++++----<br>
.../traffic_generator/traffic_generator.py | 7 ++--<br>
dts/framework/testbed_model/virtual_device.py | 2 +-<br>
dts/framework/utils.py | 6 ++--<br>
dts/tests/TestSuite_blocklist.py | 8 ++---<br>
dts/tests/TestSuite_dynamic_queue_conf.py | 8 ++---<br>
...stSuite_port_restart_config_persistency.py | 2 +-<br>
30 files changed, 113 insertions(+), 106 deletions(-)<br>
<br>
diff --git a/.mailmap b/.mailmap<br>
index d4c04f3b81..7be3d8b76a 100644<br>
--- a/.mailmap<br>
+++ b/.mailmap<br>
@@ -104,6 +104,7 @@ Andre Muezerie <<a href="mailto:andremue@linux.microsoft.com" target="_blank">andremue@linux.microsoft.com</a>> <<a href="mailto:andremue@microsoft.com" target="_blank">andremue@microsoft.com</a>><br>
Andrea Arcangeli <<a href="mailto:aarcange@redhat.com" target="_blank">aarcange@redhat.com</a>><br>
Andrea Grandi <<a href="mailto:andrea.grandi@intel.com" target="_blank">andrea.grandi@intel.com</a>><br>
Andre Richter <<a href="mailto:andre.o.richter@gmail.com" target="_blank">andre.o.richter@gmail.com</a>><br>
+Andrew Bailey <<a href="mailto:abailey@iol.unh.edu" target="_blank">abailey@iol.unh.edu</a>><br>
Andrew Boyer <<a href="mailto:andrew.boyer@amd.com" target="_blank">andrew.boyer@amd.com</a>> <<a href="mailto:aboyer@pensando.io" target="_blank">aboyer@pensando.io</a>><br>
Andrew Harvey <<a href="mailto:agh@cisco.com" target="_blank">agh@cisco.com</a>><br>
Andrew Jackson <<a href="mailto:ajackson@solarflare.com" target="_blank">ajackson@solarflare.com</a>><br>
diff --git a/dts/framework/context.py b/dts/framework/context.py<br>
index 4360bc8699..f98d31d3c1 100644<br>
--- a/dts/framework/context.py<br>
+++ b/dts/framework/context.py<br>
@@ -4,8 +4,9 @@<br>
"""Runtime contexts."""<br>
<br>
import functools<br>
+from collections.abc import Callable<br>
from dataclasses import MISSING, dataclass, field, fields<br>
-from typing import TYPE_CHECKING, ParamSpec<br>
+from typing import TYPE_CHECKING, Any, ParamSpec<br>
<br>
from framework.exception import InternalError<br>
from framework.remote_session.shell_pool import ShellPool<br>
@@ -16,6 +17,7 @@<br>
<br>
if TYPE_CHECKING:<br>
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment<br>
+ from framework.testbed_model.capability import TestProtocol<br>
from framework.testbed_model.traffic_generator.traffic_generator import TrafficGenerator<br>
<br>
P = ParamSpec("P")<br>
@@ -97,12 +99,12 @@ def init_ctx(ctx: Context) -> None:<br>
<br>
def filter_cores(<br>
specifier: LogicalCoreCount | LogicalCoreList, ascending_cores: bool | None = None<br>
-):<br>
+) -> Callable[[type["TestProtocol"]], Callable]:<br>
"""Decorates functions that require a temporary update to the lcore specifier."""<br>
<br>
- def decorator(func):<br>
+ def decorator(func: type["TestProtocol"]) -> Callable:<br>
@functools.wraps(func)<br>
- def wrapper(*args: P.args, **kwargs: P.kwargs):<br>
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> Any:<br>
local_ctx = get_ctx().local<br>
<br>
old_specifier = local_ctx.lcore_filter_specifier<br>
diff --git a/dts/framework/exception.py b/dts/framework/exception.py<br>
index 47e3fac05c..84d42c7779 100644<br>
--- a/dts/framework/exception.py<br>
+++ b/dts/framework/exception.py<br>
@@ -59,7 +59,7 @@ class SSHConnectionError(DTSError):<br>
_host: str<br>
_errors: list[str]<br>
<br>
- def __init__(self, host: str, errors: list[str] | None = None):<br>
+ def __init__(self, host: str, errors: list[str] | None = None) -> None:<br>
"""Define the meaning of the first two arguments.<br>
<br>
Args:<br>
@@ -88,7 +88,7 @@ class _SSHTimeoutError(DTSError):<br>
severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR<br>
_command: str<br>
<br>
- def __init__(self, command: str):<br>
+ def __init__(self, command: str) -> None:<br>
"""Define the meaning of the first argument.<br>
<br>
Args:<br>
@@ -119,7 +119,7 @@ class _SSHSessionDeadError(DTSError):<br>
severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR<br>
_host: str<br>
<br>
- def __init__(self, host: str):<br>
+ def __init__(self, host: str) -> None:<br>
"""Define the meaning of the first argument.<br>
<br>
Args:<br>
@@ -157,7 +157,7 @@ class RemoteCommandExecutionError(DTSError):<br>
_command_stderr: str<br>
_command_return_code: int<br>
<br>
- def __init__(self, command: str, command_stderr: str, command_return_code: int):<br>
+ def __init__(self, command: str, command_stderr: str, command_return_code: int) -> None:<br>
"""Define the meaning of the first two arguments.<br>
<br>
Args:<br>
diff --git a/dts/framework/logger.py b/dts/framework/logger.py<br>
index f43b442bc9..a0c81c3c47 100644<br>
--- a/dts/framework/logger.py<br>
+++ b/dts/framework/logger.py<br>
@@ -15,7 +15,7 @@<br>
import logging<br>
from logging import FileHandler, StreamHandler<br>
from pathlib import Path<br>
-from typing import ClassVar<br>
+from typing import Any, ClassVar<br>
<br>
date_fmt = "%Y/%m/%d %H:%M:%S"<br>
stream_fmt = "%(asctime)s - %(stage)s - %(name)s - %(levelname)s - %(message)s"<br>
@@ -36,12 +36,12 @@ class DTSLogger(logging.Logger):<br>
_stage: ClassVar[str] = "pre_run"<br>
_extra_file_handlers: list[FileHandler] = []<br>
<br>
- def __init__(self, *args, **kwargs):<br>
+ def __init__(self, *args: Any, **kwargs: Any) -> None:<br>
"""Extend the constructor with extra file handlers."""<br>
self._extra_file_handlers = []<br>
super().__init__(*args, **kwargs)<br>
<br>
- def makeRecord(self, *args, **kwargs) -> logging.LogRecord:<br>
+ def makeRecord(self, *args: Any, **kwargs: Any) -> logging.LogRecord:<br>
"""Generates a record with additional stage information.<br>
<br>
This is the default method for the :class:`~logging.Logger` class. We extend it<br>
diff --git a/dts/framework/params/__init__.py b/dts/framework/params/__init__.py<br>
index 1ae227d7b4..e6a2d3c903 100644<br>
--- a/dts/framework/params/__init__.py<br>
+++ b/dts/framework/params/__init__.py<br>
@@ -25,7 +25,7 @@<br>
T = TypeVar("T")<br>
<br>
#: Type for a function taking one argument.<br>
-FnPtr = Callable[[Any], Any]<br>
+FnPtr = Callable[[T], T]<br>
#: Type for a switch parameter.<br>
Switch = Literal[True, None]<br>
#: Type for a yes/no switch parameter.<br>
@@ -44,7 +44,7 @@ def _reduce_functions(funcs: Iterable[FnPtr]) -> FnPtr:<br>
FnPtr: A function that calls the given functions from left to right.<br>
"""<br>
<br>
- def reduced_fn(value):<br>
+ def reduced_fn(value: T) -> T:<br>
for fn in funcs:<br>
value = fn(value)<br>
return value<br>
@@ -75,8 +75,8 @@ class BitMask(enum.Flag):<br>
will allow ``BitMask`` to render as a hexadecimal value.<br>
"""<br>
<br>
- def _class_decorator(original_class):<br>
- original_class.__str__ = _reduce_functions(funcs)<br>
+ def _class_decorator(original_class: T) -> T:<br>
+ setattr(original_class, "__str__", _reduce_functions(funcs))<br>
return original_class<br>
<br>
return _class_decorator<br>
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py<br>
index 606d6e22fe..7b9c0e89cb 100644<br>
--- a/dts/framework/remote_session/dpdk.py<br>
+++ b/dts/framework/remote_session/dpdk.py<br>
@@ -62,7 +62,7 @@ class DPDKBuildEnvironment:<br>
<br>
compiler_version: str | None<br>
<br>
- def __init__(self, config: DPDKBuildConfiguration, node: Node):<br>
+ def __init__(self, config: DPDKBuildConfiguration, node: Node) -> None:<br>
"""DPDK build environment class constructor."""<br>
self.config = config<br>
self._node = node<br>
@@ -74,7 +74,7 @@ def __init__(self, config: DPDKBuildConfiguration, node: Node):<br>
<br>
self.compiler_version = None<br>
<br>
- def setup(self):<br>
+ def setup(self) -> None:<br>
"""Set up the DPDK build on the target node.<br>
<br>
DPDK setup includes setting all internals needed for the build, the copying of DPDK<br>
@@ -118,7 +118,7 @@ def teardown(self) -> None:<br>
)<br>
self._node.main_session.remove_remote_file(tarball_path)<br>
<br>
- def _set_remote_dpdk_tree_path(self, dpdk_tree: PurePath):<br>
+ def _set_remote_dpdk_tree_path(self, dpdk_tree: PurePath) -> None:<br>
"""Set the path to the remote DPDK source tree based on the provided DPDK location.<br>
<br>
Verify DPDK source tree existence on the SUT node, if exists sets the<br>
@@ -205,7 +205,7 @@ def _prepare_and_extract_dpdk_tarball(self, remote_tarball_path: PurePath) -> No<br>
strip_root_dir=True,<br>
)<br>
<br>
- def _set_remote_dpdk_build_dir(self, build_dir: str):<br>
+ def _set_remote_dpdk_build_dir(self, build_dir: str) -> None:<br>
"""Set the `remote_dpdk_build_dir` on the SUT.<br>
<br>
Check existence on the SUT node and sets the<br>
@@ -277,7 +277,7 @@ def remote_dpdk_tree_path(self) -> PurePath:<br>
return self._node.tmp_dir.joinpath(self._remote_tmp_dpdk_tree_dir)<br>
<br>
@property<br>
- def remote_dpdk_build_dir(self) -> str | PurePath:<br>
+ def remote_dpdk_build_dir(self) -> PurePath:<br>
"""The remote DPDK build dir path."""<br>
if self._remote_dpdk_build_dir:<br>
return self._remote_dpdk_build_dir<br>
@@ -286,7 +286,7 @@ def remote_dpdk_build_dir(self) -> str | PurePath:<br>
"Failed to get remote dpdk build dir because we don't know the "<br>
"location on the SUT node."<br>
)<br>
- return ""<br>
+ return PurePath("")<br>
<br>
@cached_property<br>
def dpdk_version(self) -> str | None:<br>
@@ -323,7 +323,7 @@ def __init__(<br>
config: DPDKRuntimeConfiguration,<br>
node: Node,<br>
build_env: DPDKBuildEnvironment | None = None,<br>
- ):<br>
+ ) -> None:<br>
"""DPDK environment constructor.<br>
<br>
Args:<br>
@@ -354,7 +354,7 @@ def __init__(<br>
self._ports_bound_to_dpdk = False<br>
self._kill_session = None<br>
<br>
- def setup(self):<br>
+ def setup(self) -> None:<br>
"""Set up the DPDK runtime on the target node."""<br>
if self.build:<br>
self.build.setup()<br>
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py<br>
index d4aa02f39b..51b97d4ff6 100644<br>
--- a/dts/framework/remote_session/dpdk_shell.py<br>
+++ b/dts/framework/remote_session/dpdk_shell.py<br>
@@ -78,7 +78,7 @@ def __init__(<br>
def path(self) -> PurePath:<br>
"""Relative path to the shell executable from the build folder."""<br>
<br>
- def _make_real_path(self):<br>
+ def _make_real_path(self) -> PurePath:<br>
"""Overrides :meth:`~.interactive_shell.InteractiveShell._make_real_path`.<br>
<br>
Adds the remote DPDK build directory to the path.<br>
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py<br>
index ba8489eafa..ce93247051 100644<br>
--- a/dts/framework/remote_session/interactive_shell.py<br>
+++ b/dts/framework/remote_session/interactive_shell.py<br>
@@ -24,7 +24,7 @@<br>
from abc import ABC, abstractmethod<br>
from collections.abc import Callable<br>
from pathlib import PurePath<br>
-from typing import ClassVar, Concatenate, ParamSpec, TypeAlias, TypeVar<br>
+from typing import Any, ClassVar, Concatenate, ParamSpec, TypeAlias, TypeVar<br>
<br>
from paramiko import Channel, channel<br>
from typing_extensions import Self<br>
@@ -126,7 +126,7 @@ def __init__(<br>
self._privileged = privileged<br>
self._timeout = SETTINGS.timeout<br>
<br>
- def _setup_ssh_channel(self):<br>
+ def _setup_ssh_channel(self) -> None:<br>
self._ssh_channel = self._node.main_session.interactive_session.session.invoke_shell()<br>
self._stdin = self._ssh_channel.makefile_stdin("w")<br>
self._stdout = self._ssh_channel.makefile("r")<br>
@@ -277,7 +277,7 @@ def __enter__(self) -> Self:<br>
self.start_application()<br>
return self<br>
<br>
- def __exit__(self, *_) -> None:<br>
+ def __exit__(self, *_: Any) -> None:<br>
"""Exit the context block.<br>
<br>
Upon exiting a context block with this class, we want to ensure that the instance of the<br>
diff --git a/dts/framework/remote_session/python_shell.py b/dts/framework/remote_session/python_shell.py<br>
index 5b380a5c7a..5f39a244d6 100644<br>
--- a/dts/framework/remote_session/python_shell.py<br>
+++ b/dts/framework/remote_session/python_shell.py<br>
@@ -33,6 +33,6 @@ def path(self) -> PurePath:<br>
return PurePath("python3")<br>
<br>
@only_active<br>
- def close(self):<br>
+ def close(self) -> None:<br>
"""Close Python shell."""<br>
return super().close()<br>
diff --git a/dts/framework/remote_session/remote_session.py b/dts/framework/remote_session/remote_session.py<br>
index 89d4618c41..f616b92f1c 100644<br>
--- a/dts/framework/remote_session/remote_session.py<br>
+++ b/dts/framework/remote_session/remote_session.py<br>
@@ -99,7 +99,7 @@ def __init__(<br>
node_config: NodeConfiguration,<br>
session_name: str,<br>
logger: DTSLogger,<br>
- ):<br>
+ ) -> None:<br>
"""Connect to the node during initialization.<br>
<br>
Args:<br>
diff --git a/dts/framework/remote_session/shell_pool.py b/dts/framework/remote_session/shell_pool.py<br>
index da956950d5..241737eab3 100644<br>
--- a/dts/framework/remote_session/shell_pool.py<br>
+++ b/dts/framework/remote_session/shell_pool.py<br>
@@ -32,7 +32,7 @@ class ShellPool:<br>
_logger: DTSLogger<br>
_pools: list[set["InteractiveShell"]]<br>
<br>
- def __init__(self):<br>
+ def __init__(self) -> None:<br>
"""Shell pool constructor."""<br>
self._logger = get_dts_logger("shell_pool")<br>
self._pools = [set()]<br>
@@ -50,12 +50,12 @@ def _current_pool(self) -> set["InteractiveShell"]:<br>
"""The pool in use for the current scope."""<br>
return self._pools[-1]<br>
<br>
- def register_shell(self, shell: "InteractiveShell"):<br>
+ def register_shell(self, shell: "InteractiveShell") -> None:<br>
"""Register a new shell to the current pool."""<br>
self._logger.debug(f"Registering shell {shell} to pool level {self.pool_level}.")<br>
self._current_pool.add(shell)<br>
<br>
- def unregister_shell(self, shell: "InteractiveShell"):<br>
+ def unregister_shell(self, shell: "InteractiveShell") -> None:<br>
"""Unregister a shell from any pool."""<br>
for level, pool in enumerate(self._pools):<br>
try:<br>
@@ -72,12 +72,12 @@ def unregister_shell(self, shell: "InteractiveShell"):<br>
except KeyError:<br>
pass<br>
<br>
- def start_new_pool(self):<br>
+ def start_new_pool(self) -> None:<br>
"""Start a new shell pool."""<br>
self._logger.debug(f"Starting new shell pool and advancing to level {self.pool_level+1}.")<br>
self._pools.append(set())<br>
<br>
- def terminate_current_pool(self):<br>
+ def terminate_current_pool(self) -> None:<br>
"""Terminate all the shells in the current pool, and restore the previous pool if any.<br>
<br>
If any failure occurs while closing any shell, this is tolerated allowing the termination<br>
diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py<br>
index ad8cb273dc..1df3d5f792 100644<br>
--- a/dts/framework/remote_session/testpmd_shell.py<br>
+++ b/dts/framework/remote_session/testpmd_shell.py<br>
@@ -64,7 +64,7 @@ class TestPmdDevice:<br>
<br>
pci_address: str<br>
<br>
- def __init__(self, pci_address_line: str):<br>
+ def __init__(self, pci_address_line: str) -> None:<br>
"""Initialize the device from the testpmd output line string.<br>
<br>
Args:<br>
@@ -90,7 +90,7 @@ class VLANOffloadFlag(Flag):<br>
QINQ_STRIP = auto()<br>
<br>
@classmethod<br>
- def from_str_dict(cls, d):<br>
+ def from_str_dict(cls, d: dict[str, str]) -> Self:<br>
"""Makes an instance from a dict containing the flag member names with an "on" value.<br>
<br>
Args:<br>
@@ -405,7 +405,7 @@ def make_device_private_info_parser() -> ParserFn:<br>
function that parses the device private info from the TestPmd port info output.<br>
"""<br>
<br>
- def _validate(info: str):<br>
+ def _validate(info: str) -> str | None:<br>
info = info.strip()<br>
if info == "none" or info.startswith("Invalid file") or info.startswith("Failed to dump"):<br>
return None<br>
@@ -1449,7 +1449,7 @@ def requires_stopped_ports(func: TestPmdShellMethod) -> TestPmdShellMethod:<br>
"""<br>
<br>
@functools.wraps(func)<br>
- def _wrapper(self: "TestPmdShell", *args: P.args, **kwargs: P.kwargs):<br>
+ def _wrapper(self: "TestPmdShell", *args: P.args, **kwargs: P.kwargs) -> Any:<br>
if self.ports_started:<br>
self._logger.debug("Ports need to be stopped to continue.")<br>
self.stop_all_ports()<br>
@@ -1470,7 +1470,7 @@ def requires_started_ports(func: TestPmdShellMethod) -> TestPmdShellMethod:<br>
"""<br>
<br>
@functools.wraps(func)<br>
- def _wrapper(self: "TestPmdShell", *args: P.args, **kwargs: P.kwargs):<br>
+ def _wrapper(self: "TestPmdShell", *args: P.args, **kwargs: P.kwargs) -> Any:<br>
if not self.ports_started:<br>
self._logger.debug("Ports need to be started to continue.")<br>
self.start_all_ports()<br>
@@ -1492,7 +1492,7 @@ def add_remove_mtu(mtu: int = 1500) -> Callable[[TestPmdShellMethod], TestPmdShe<br>
<br>
def decorator(func: TestPmdShellMethod) -> TestPmdShellMethod:<br>
@functools.wraps(func)<br>
- def wrapper(self: "TestPmdShell", *args: P.args, **kwargs: P.kwargs):<br>
+ def wrapper(self: "TestPmdShell", *args: P.args, **kwargs: P.kwargs) -> Any:<br>
original_mtu = self.ports[0].mtu<br>
self.set_port_mtu_all(mtu=mtu, verify=False)<br>
retval = func(self, *args, **kwargs)<br>
@@ -1644,7 +1644,7 @@ def wait_link_status_up(self, port_id: int, timeout=SETTINGS.timeout) -> bool:<br>
self._logger.error(f"The link for port {port_id} did not come up in the given timeout.")<br>
return "Link status: up" in port_info<br>
<br>
- def set_forward_mode(self, mode: SimpleForwardingModes, verify: bool = True):<br>
+ def set_forward_mode(self, mode: SimpleForwardingModes, verify: bool = True) -> None:<br>
"""Set packet forwarding mode.<br>
<br>
Args:<br>
diff --git a/dts/framework/runner.py b/dts/framework/runner.py<br>
index 0a3d92b0c8..4f2c05bd2f 100644<br>
--- a/dts/framework/runner.py<br>
+++ b/dts/framework/runner.py<br>
@@ -31,7 +31,7 @@ class DTSRunner:<br>
_logger: DTSLogger<br>
_result: TestRunResult<br>
<br>
- def __init__(self):<br>
+ def __init__(self) -> None:<br>
"""Initialize the instance with configuration, logger, result and string constants."""<br>
try:<br>
self._configuration = load_config(ValidationContext(settings=SETTINGS))<br>
diff --git a/dts/framework/settings.py b/dts/framework/settings.py<br>
index 3f21615223..84b627a06a 100644<br>
--- a/dts/framework/settings.py<br>
+++ b/dts/framework/settings.py<br>
@@ -108,7 +108,7 @@<br>
from argparse import Action, ArgumentDefaultsHelpFormatter, _get_action_name<br>
from dataclasses import dataclass, field<br>
from pathlib import Path<br>
-from typing import Callable<br>
+from typing import Callable, NoReturn<br>
<br>
from pydantic import ValidationError<br>
<br>
@@ -174,7 +174,7 @@ def _make_env_var_name(action: Action, env_var_name: str | None) -> str:<br>
return env_var_name<br>
<br>
<br>
-def _get_env_var_name(action: Action) -> str | None:<br>
+def _get_env_var_name(action: Action | None) -> str | None:<br>
"""Get the environment variable name of the given action."""<br>
return getattr(action, _ENV_VAR_NAME_ATTR, None)<br>
<br>
@@ -237,12 +237,15 @@ def find_action(<br>
<br>
return action<br>
<br>
- def error(self, message):<br>
+ def error(self, message) -> NoReturn:<br>
"""Augments :meth:`~argparse.ArgumentParser.error` with environment variable awareness."""<br>
for action in self._actions:<br>
if _is_from_env(action):<br>
action_name = _get_action_name(action)<br>
env_var_name = _get_env_var_name(action)<br>
+ assert (<br>
+ env_var_name is not None<br>
+ ), "Action was set from environment, but no environment variable name was found."<br>
env_var_value = os.environ.get(env_var_name)<br>
<br>
message = message.replace(<br>
@@ -257,7 +260,7 @@ def error(self, message):<br>
class _EnvVarHelpFormatter(ArgumentDefaultsHelpFormatter):<br>
"""Custom formatter to add environment variables to the help page."""<br>
<br>
- def _get_help_string(self, action):<br>
+ def _get_help_string(self, action: Action) -> str | None:<br>
"""Overrides :meth:`ArgumentDefaultsHelpFormatter._get_help_string`."""<br>
help = super()._get_help_string(action)<br>
<br>
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py<br>
index 8ce6cc8fbf..c6bddc55a9 100644<br>
--- a/dts/framework/test_result.py<br>
+++ b/dts/framework/test_result.py<br>
@@ -77,13 +77,13 @@ class ResultLeaf(BaseModel):<br>
result: Result<br>
reason: DTSError | None = None<br>
<br>
- def __lt__(self, other):<br>
+ def __lt__(self, other: object) -> bool:<br>
"""Compare another instance of the same class by :attr:`~ResultLeaf.result`."""<br>
if isinstance(other, ResultLeaf):<br>
return self.result < other.result<br>
return True<br>
<br>
- def __eq__(self, other):<br>
+ def __eq__(self, other: object) -> bool:<br>
"""Compare equality with compatible classes by :attr:`~ResultLeaf.result`."""<br>
match other:<br>
case ResultLeaf(result=result):<br>
@@ -128,7 +128,7 @@ def add_child(self, label: str) -> "ResultNode":<br>
self.children.append(child)<br>
return child<br>
<br>
- def mark_result_as(self, result: Result, ex: Exception | None = None) -> None:<br>
+ def mark_result_as(self, result: Result, ex: BaseException | None = None) -> None:<br>
"""Mark result for the current step.<br>
<br>
Args:<br>
@@ -149,7 +149,7 @@ def mark_result_as(self, result: Result, ex: Exception | None = None) -> None:<br>
self.children.append(ResultLeaf(result=result, reason=reason))<br>
<br>
def mark_step_as(<br>
- self, step: ExecutionStep, result: Result, ex: Exception | None = None<br>
+ self, step: ExecutionStep, result: Result, ex: BaseException | None = None<br>
) -> None:<br>
"""Mark an execution step with the given result.<br>
<br>
@@ -264,7 +264,7 @@ def serialize_errors(self, execution_errors: list[DTSError]) -> list[str]:<br>
"""Serialize errors as plain text."""<br>
return [str(err) for err in execution_errors]<br>
<br>
- def add_error(self, ex: Exception) -> None:<br>
+ def add_error(self, ex: BaseException) -> None:<br>
"""Add an execution error to the test run result."""<br>
if isinstance(ex, DTSError):<br>
self.execution_errors.append(ex)<br>
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py<br>
index 4355aeeb4b..ca9066299e 100644<br>
--- a/dts/framework/test_run.py<br>
+++ b/dts/framework/test_run.py<br>
@@ -162,7 +162,7 @@ class TestRun:<br>
config: TestRunConfiguration<br>
logger: DTSLogger<br>
<br>
- state: "State"<br>
+ state: Union["State", None]<br>
ctx: Context<br>
result: TestRunResult<br>
selected_tests: list[TestScenario]<br>
@@ -178,7 +178,7 @@ def __init__(<br>
tests_config: dict[str, BaseConfig],<br>
nodes: Iterable[Node],<br>
result: TestRunResult,<br>
- ):<br>
+ ) -> None:<br>
"""Test run constructor.<br>
<br>
Args:<br>
@@ -226,7 +226,7 @@ def required_capabilities(self) -> set[Capability]:<br>
<br>
return caps<br>
<br>
- def spin(self):<br>
+ def spin(self) -> None:<br>
"""Spin the internal state machine that executes the test run."""<br>
<a href="http://self.logger.info" rel="noreferrer" target="_blank">self.logger.info</a>(f"Running test run with SUT '{<a href="http://self.ctx.sut_node.name" rel="noreferrer" target="_blank">self.ctx.sut_node.name</a>}'.")<br>
<br>
@@ -258,11 +258,11 @@ class State(Protocol):<br>
test_run: TestRun<br>
result: TestRunResult | ResultNode<br>
<br>
- def before(self):<br>
+ def before(self) -> None:<br>
"""Hook before the state is processed."""<br>
self.logger.set_stage(self.logger_name, self.log_file_path)<br>
<br>
- def after(self):<br>
+ def after(self) -> None:<br>
"""Hook after the state is processed."""<br>
return<br>
<br>
@@ -289,12 +289,12 @@ def log_file_path(self) -> Path | None:<br>
def next(self) -> Union["State", None]:<br>
"""Next state."""<br>
<br>
- def on_error(self, ex: Exception) -> Union["State", None]:<br>
+ def on_error(self, ex: BaseException) -> Union["State", None]:<br>
"""Next state on error."""<br>
<br>
- def handle_exception(self, ex: Exception) -> Union["State", None]:<br>
+ def handle_exception(self, ex: BaseException) -> Union["State", None]:<br>
"""Handles an exception raised by `next`."""<br>
- next_state = self.on_error(ex)<br>
+ next_state = self.on_error(Exception(ex))<br>
<br>
match ex:<br>
case InternalError():<br>
@@ -362,7 +362,7 @@ def next(self) -> State | None:<br>
)<br>
return TestRunExecution(test_run, self.result)<br>
<br>
- def on_error(self, ex: Exception) -> State | None:<br>
+ def on_error(self, ex: BaseException) -> State | None:<br>
"""Next state on error."""<br>
self.test_run.result.add_error(ex)<br>
return TestRunTeardown(self.test_run, self.result)<br>
@@ -411,7 +411,7 @@ def next(self) -> State | None:<br>
# No more test suites. We are done here.<br>
return TestRunTeardown(test_run, self.result)<br>
<br>
- def on_error(self, ex: Exception) -> State | None:<br>
+ def on_error(self, ex: BaseException) -> State | None:<br>
"""Next state on error."""<br>
self.test_run.result.add_error(ex)<br>
return TestRunTeardown(self.test_run, self.result)<br>
@@ -443,7 +443,7 @@ def next(self) -> State | None:<br>
self.test_run.ctx.sut_node.teardown()<br>
return None<br>
<br>
- def on_error(self, ex: Exception) -> State | None:<br>
+ def on_error(self, ex: BaseException) -> State | None:<br>
"""Next state on error."""<br>
self.test_run.result.add_error(ex)<br>
self.logger.warning(<br>
@@ -491,7 +491,7 @@ def next(self) -> State | None:<br>
result=self.result,<br>
)<br>
<br>
- def on_error(self, ex: Exception) -> State | None:<br>
+ def on_error(self, ex: BaseException) -> State | None:<br>
"""Next state on error."""<br>
self.result.mark_step_as("setup", Result.ERROR, ex)<br>
return TestSuiteTeardown(self.test_run, self.test_suite, self.result)<br>
@@ -543,7 +543,7 @@ def next(self) -> State | None:<br>
# No more test cases. We are done here.<br>
return TestSuiteTeardown(self.test_run, self.test_suite, self.result)<br>
<br>
- def on_error(self, ex: Exception) -> State | None:<br>
+ def on_error(self, ex: BaseException) -> State | None:<br>
"""Next state on error."""<br>
self.test_run.result.add_error(ex)<br>
return TestSuiteTeardown(self.test_run, self.test_suite, self.result)<br>
@@ -568,7 +568,7 @@ def next(self) -> State | None:<br>
self.result.mark_step_as("teardown", Result.PASS)<br>
return TestRunExecution(self.test_run, self.test_run.result)<br>
<br>
- def on_error(self, ex: Exception) -> State | None:<br>
+ def on_error(self, ex: BaseException) -> State | None:<br>
"""Next state on error."""<br>
self.logger.warning(<br>
"The environment may have not been cleaned up correctly. "<br>
@@ -577,7 +577,7 @@ def on_error(self, ex: Exception) -> State | None:<br>
self.result.mark_step_as("teardown", Result.ERROR, ex)<br>
return TestRunExecution(self.test_run, self.test_run.result)<br>
<br>
- def after(self):<br>
+ def after(self) -> None:<br>
"""Hook after state is processed."""<br>
if (<br>
self.result.get_overall_result() in [Result.FAIL, Result.ERROR]<br>
@@ -633,7 +633,7 @@ def next(self) -> State | None:<br>
SETTINGS.re_run,<br>
)<br>
<br>
- def on_error(self, ex: Exception) -> State | None:<br>
+ def on_error(self, ex: BaseException) -> State | None:<br>
"""Next state on error."""<br>
self.result.mark_step_as("setup", Result.ERROR, ex)<br>
self.result.mark_result_as(Result.BLOCK)<br>
@@ -686,7 +686,7 @@ def next(self) -> State | None:<br>
self.result,<br>
)<br>
<br>
- def on_error(self, ex: Exception) -> State | None:<br>
+ def on_error(self, ex: BaseException) -> State | None:<br>
"""Next state on error."""<br>
self.result.mark_result_as(Result.ERROR, ex)<br>
return TestCaseTeardown(<br>
@@ -720,7 +720,7 @@ def next(self) -> State | None:<br>
result=self.result.parent,<br>
)<br>
<br>
- def on_error(self, ex: Exception) -> State | None:<br>
+ def on_error(self, ex: BaseException) -> State | None:<br>
"""Next state on error."""<br>
self.logger.warning(<br>
"The environment may have not been cleaned up correctly. "<br>
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py<br>
index d4e06a567a..5ee5a039d7 100644<br>
--- a/dts/framework/test_suite.py<br>
+++ b/dts/framework/test_suite.py<br>
@@ -92,7 +92,7 @@ class TestSuite(TestProtocol):<br>
_tg_ip_address_ingress: Union[IPv4Interface, IPv6Interface]<br>
_tg_ip_address_egress: Union[IPv4Interface, IPv6Interface]<br>
<br>
- def __init__(self, config: BaseConfig):<br>
+ def __init__(self, config: BaseConfig) -> None:<br>
"""Initialize the test suite testbed information and basic configuration.<br>
<br>
Args:<br>
@@ -681,7 +681,7 @@ def class_obj(self) -> type[TestSuite]:<br>
InternalError: If the test suite class is missing from the module.<br>
"""<br>
<br>
- def is_test_suite(obj) -> bool:<br>
+ def is_test_suite(obj: type) -> bool:<br>
"""Check whether `obj` is a :class:`TestSuite`.<br>
<br>
The `obj` is a subclass of :class:`TestSuite`, but not :class:`TestSuite` itself.<br>
diff --git a/dts/framework/testbed_model/capability.py b/dts/framework/testbed_model/capability.py<br>
index f895b22bb3..87be7e6b93 100644<br>
--- a/dts/framework/testbed_model/capability.py<br>
+++ b/dts/framework/testbed_model/capability.py<br>
@@ -50,7 +50,7 @@ def test_scatter_mbuf_2048(self):<br>
from abc import ABC, abstractmethod<br>
from collections.abc import MutableSet<br>
from dataclasses import dataclass<br>
-from typing import TYPE_CHECKING, Callable, ClassVar, Protocol<br>
+from typing import TYPE_CHECKING, Any, Callable, ClassVar, Protocol<br>
<br>
from typing_extensions import Self<br>
<br>
@@ -374,7 +374,7 @@ def set_required(self, test_case_or_suite: type["TestProtocol"]) -> None:<br>
else:<br>
self.add_to_required(test_case_or_suite)<br>
<br>
- def __eq__(self, other) -> bool:<br>
+ def __eq__(self, other: Any) -> bool:<br>
"""Compare the :attr:`~TopologyCapability.topology_type`s.<br>
<br>
Args:<br>
@@ -385,7 +385,7 @@ def __eq__(self, other) -> bool:<br>
"""<br>
return self.topology_type == other.topology_type<br>
<br>
- def __lt__(self, other) -> bool:<br>
+ def __lt__(self, other: Any) -> bool:<br>
"""Compare the :attr:`~TopologyCapability.topology_type`s.<br>
<br>
Args:<br>
@@ -396,7 +396,7 @@ def __lt__(self, other) -> bool:<br>
"""<br>
return self.topology_type < other.topology_type<br>
<br>
- def __gt__(self, other) -> bool:<br>
+ def __gt__(self, other: Any) -> bool:<br>
"""Compare the :attr:`~TopologyCapability.topology_type`s.<br>
<br>
Args:<br>
@@ -407,7 +407,7 @@ def __gt__(self, other) -> bool:<br>
"""<br>
return other < self<br>
<br>
- def __le__(self, other) -> bool:<br>
+ def __le__(self, other: Any) -> bool:<br>
"""Compare the :attr:`~TopologyCapability.topology_type`s.<br>
<br>
Args:<br>
diff --git a/dts/framework/testbed_model/cpu.py b/dts/framework/testbed_model/cpu.py<br>
index b8bc601c22..6e2ecca080 100644<br>
--- a/dts/framework/testbed_model/cpu.py<br>
+++ b/dts/framework/testbed_model/cpu.py<br>
@@ -80,7 +80,7 @@ class LogicalCoreList:<br>
_lcore_list: list[int]<br>
_lcore_str: str<br>
<br>
- def __init__(self, lcore_list: list[int] | list[str] | list[LogicalCore] | str):<br>
+ def __init__(self, lcore_list: list[int] | list[str] | list[LogicalCore] | str) -> None:<br>
"""Process `lcore_list`, then sort.<br>
<br>
There are four supported logical core list formats::<br>
@@ -169,7 +169,7 @@ def __init__(<br>
lcore_list: list[LogicalCore],<br>
filter_specifier: LogicalCoreCount | LogicalCoreList,<br>
ascending: bool = True,<br>
- ):<br>
+ ) -> None:<br>
"""Filter according to the input filter specifier.<br>
<br>
The input `lcore_list` is copied and sorted by physical core before filtering.<br>
diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py<br>
index 35cf6f1452..4f6150f18c 100644<br>
--- a/dts/framework/testbed_model/node.py<br>
+++ b/dts/framework/testbed_model/node.py<br>
@@ -59,7 +59,7 @@ class Node:<br>
_compiler_version: str | None<br>
_setup: bool<br>
<br>
- def __init__(self, node_config: NodeConfiguration):<br>
+ def __init__(self, node_config: NodeConfiguration) -> None:<br>
"""Connect to the node and gather info during initialization.<br>
<br>
Extra gathered information:<br>
diff --git a/dts/framework/testbed_model/os_session.py b/dts/framework/testbed_model/os_session.py<br>
index b6e03aa83d..b182c3bde4 100644<br>
--- a/dts/framework/testbed_model/os_session.py<br>
+++ b/dts/framework/testbed_model/os_session.py<br>
@@ -115,7 +115,7 @@ def __init__(<br>
node_config: NodeConfiguration,<br>
name: str,<br>
logger: DTSLogger,<br>
- ):<br>
+ ) -> None:<br>
"""Initialize the OS-aware session.<br>
<br>
Connect to the node right away and also create an interactive remote session.<br>
diff --git a/dts/framework/testbed_model/port.py b/dts/framework/testbed_model/port.py<br>
index fc58e2b993..2c0276971f 100644<br>
--- a/dts/framework/testbed_model/port.py<br>
+++ b/dts/framework/testbed_model/port.py<br>
@@ -49,7 +49,7 @@ class Port:<br>
config: Final[PortConfig]<br>
_original_driver: str | None<br>
<br>
- def __init__(self, node: "Node", config: PortConfig):<br>
+ def __init__(self, node: "Node", config: PortConfig) -> None:<br>
"""Initialize the port from `node` and `config`.<br>
<br>
Args:<br>
@@ -128,7 +128,7 @@ def bound_for_dpdk(self) -> bool:<br>
"""Is the port bound to the driver for DPDK?"""<br>
return self.current_driver == self.config.os_driver_for_dpdk<br>
<br>
- def configure_mtu(self, mtu: int):<br>
+ def configure_mtu(self, mtu: int) -> None:<br>
"""Configure the port's MTU value.<br>
<br>
Args:<br>
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/framework/testbed_model/posix_session.py<br>
index c71bc93f0b..dec952685a 100644<br>
--- a/dts/framework/testbed_model/posix_session.py<br>
+++ b/dts/framework/testbed_model/posix_session.py<br>
@@ -183,7 +183,7 @@ def create_remote_tarball(<br>
) -> PurePosixPath:<br>
"""Overrides :meth:`~.os_session.OSSession.create_remote_tarball`."""<br>
<br>
- def generate_tar_exclude_args(exclude_patterns) -> str:<br>
+ def generate_tar_exclude_args(exclude_patterns: str | list[str] | None) -> str:<br>
"""Generate args to exclude patterns when creating a tarball.<br>
<br>
Args:<br>
diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py b/dts/framework/testbed_model/traffic_generator/scapy.py<br>
index e21ba4ed96..a31807e8e4 100644<br>
--- a/dts/framework/testbed_model/traffic_generator/scapy.py<br>
+++ b/dts/framework/testbed_model/traffic_generator/scapy.py<br>
@@ -16,7 +16,7 @@<br>
from collections.abc import Callable<br>
from queue import Empty, SimpleQueue<br>
from threading import Event, Thread<br>
-from typing import ClassVar<br>
+from typing import Any, ClassVar<br>
<br>
from scapy.compat import base64_bytes<br>
from scapy.data import ETHER_TYPES, IP_PROTOS<br>
@@ -57,7 +57,7 @@ class ScapyAsyncSniffer(PythonShell):<br>
<br>
def __init__(<br>
self, node: Node, recv_port: Port, name: str | None = None, privileged: bool = True<br>
- ):<br>
+ ) -> None:<br>
"""Sniffer constructor.<br>
<br>
Args:<br>
@@ -189,7 +189,7 @@ def close(self) -> None:<br>
self._sniffer.join()<br>
super().close()<br>
<br>
- def _sniff(self, recv_port: Port):<br>
+ def _sniff(self, recv_port: Port) -> None:<br>
"""Sniff packets and use events and queue to communicate with the main thread.<br>
<br>
Raises:<br>
@@ -229,7 +229,7 @@ def _sniff(self, recv_port: Port):<br>
self._logger.debug("Stop sniffing.")<br>
self.send_command("\x03") # send Ctrl+C to trigger a KeyboardInterrupt in `sniff`.<br>
<br>
- def _set_packet_filter(self, filter_config: PacketFilteringConfig):<br>
+ def _set_packet_filter(self, filter_config: PacketFilteringConfig) -> None:<br>
"""Make and set a filtering function from `filter_config`.<br>
<br>
Args:<br>
@@ -296,7 +296,7 @@ class also extends :class:`.capturing_traffic_generator.CapturingTrafficGenerato<br>
#: Padding to add to the start of a line for python syntax compliance.<br>
_python_indentation: ClassVar[str] = " " * 4<br>
<br>
- def __init__(self, tg_node: Node, config: ScapyTrafficGeneratorConfig, **kwargs):<br>
+ def __init__(self, tg_node: Node, config: ScapyTrafficGeneratorConfig, **kwargs: Any) -> None:<br>
"""Extend the constructor with Scapy TG specifics.<br>
<br>
Initializes both the traffic generator and the interactive shell used to handle Scapy<br>
@@ -315,7 +315,7 @@ def __init__(self, tg_node: Node, config: ScapyTrafficGeneratorConfig, **kwargs)<br>
<br>
super().__init__(tg_node=tg_node, config=config, **kwargs)<br>
<br>
- def setup(self, topology: Topology):<br>
+ def setup(self, topology: Topology) -> None:<br>
"""Extends :meth:`.traffic_generator.TrafficGenerator.setup`.<br>
<br>
Binds the TG node ports to the kernel drivers and starts up the async sniffer.<br>
@@ -332,7 +332,7 @@ def setup(self, topology: Topology):<br>
self._shell.send_command("from scapy.all import *")<br>
self._shell.send_command("from scapy.contrib.lldp import *")<br>
<br>
- def close(self):<br>
+ def close(self) -> None:<br>
"""Overrides :meth:`.traffic_generator.TrafficGenerator.close`.<br>
<br>
Stops the traffic generator and sniffer shells.<br>
diff --git a/dts/framework/testbed_model/traffic_generator/traffic_generator.py b/dts/framework/testbed_model/traffic_generator/traffic_generator.py<br>
index 8f53b07daf..cac119c183 100644<br>
--- a/dts/framework/testbed_model/traffic_generator/traffic_generator.py<br>
+++ b/dts/framework/testbed_model/traffic_generator/traffic_generator.py<br>
@@ -9,6 +9,7 @@<br>
"""<br>
<br>
from abc import ABC, abstractmethod<br>
+from typing import Any<br>
<br>
from scapy.packet import Packet<br>
<br>
@@ -34,7 +35,7 @@ class TrafficGenerator(ABC):<br>
_tg_node: Node<br>
_logger: DTSLogger<br>
<br>
- def __init__(self, tg_node: Node, config: TrafficGeneratorConfig, **kwargs):<br>
+ def __init__(self, tg_node: Node, config: TrafficGeneratorConfig, **kwargs: Any) -> None:<br>
"""Initialize the traffic generator.<br>
<br>
Additional keyword arguments can be passed through `kwargs` if needed for fulfilling other<br>
@@ -49,10 +50,10 @@ def __init__(self, tg_node: Node, config: TrafficGeneratorConfig, **kwargs):<br>
self._tg_node = tg_node<br>
self._logger = get_dts_logger(f"{self._<a href="http://tg_node.name" rel="noreferrer" target="_blank">tg_node.name</a>} {self._config.type}")<br>
<br>
- def setup(self, topology: Topology):<br>
+ def setup(self, topology: Topology) -> None:<br>
"""Setup the traffic generator."""<br>
<br>
- def teardown(self):<br>
+ def teardown(self) -> None:<br>
"""Teardown the traffic generator."""<br>
self.close()<br>
<br>
diff --git a/dts/framework/testbed_model/virtual_device.py b/dts/framework/testbed_model/virtual_device.py<br>
index 569d67b007..1a4794e695 100644<br>
--- a/dts/framework/testbed_model/virtual_device.py<br>
+++ b/dts/framework/testbed_model/virtual_device.py<br>
@@ -16,7 +16,7 @@ class VirtualDevice:<br>
<br>
name: str<br>
<br>
- def __init__(self, name: str):<br>
+ def __init__(self, name: str) -> None:<br>
"""Initialize the virtual device.<br>
<br>
Args:<br>
diff --git a/dts/framework/utils.py b/dts/framework/utils.py<br>
index 0c81ab1b95..a70c9c7d95 100644<br>
--- a/dts/framework/utils.py<br>
+++ b/dts/framework/utils.py<br>
@@ -147,14 +147,14 @@ class TarCompressionFormat(StrEnum):<br>
zstd = "zst"<br>
<br>
@property<br>
- def extension(self):<br>
+ def extension(self) -> str:<br>
"""Return the extension associated with the compression format.<br>
<br>
If the compression format is 'none', the extension will be in the format 'tar'.<br>
For other compression formats, the extension will be in the format<br>
'tar.{compression format}'.<br>
"""<br>
- return f"{self.value}" if self == self.none else f"{self.none.value}.{self.value}"<br>
+ return f"{self.value}" if self == self.none else f"{type(self).none.value}.{self.value}"<br>
<br>
<br>
def convert_to_list_of_string(value: Any | list[Any]) -> list[str]:<br>
@@ -213,7 +213,7 @@ def filter_func(tarinfo: tarfile.TarInfo) -> tarfile.TarInfo | None:<br>
return target_tarball_path<br>
<br>
<br>
-def extract_tarball(tar_path: str | Path):<br>
+def extract_tarball(tar_path: str | Path) -> None:<br>
"""Extract the contents of a tarball.<br>
<br>
The tarball will be extracted in the same path as `tar_path` parent path.<br>
diff --git a/dts/tests/TestSuite_blocklist.py b/dts/tests/TestSuite_blocklist.py<br>
index ce7da1cc8f..c668bcd86c 100644<br>
--- a/dts/tests/TestSuite_blocklist.py<br>
+++ b/dts/tests/TestSuite_blocklist.py<br>
@@ -16,7 +16,7 @@<br>
class TestBlocklist(TestSuite):<br>
"""DPDK device blocklisting test suite."""<br>
<br>
- def verify_blocklisted_ports(self, ports_to_block: list[Port]):<br>
+ def verify_blocklisted_ports(self, ports_to_block: list[Port]) -> None:<br>
"""Runs testpmd with the given ports blocklisted and verifies the ports."""<br>
with TestPmdShell(allowed_ports=[], blocked_ports=ports_to_block) as testpmd:<br>
allowlisted_ports = {port.device_name for port in testpmd.show_port_info_all()}<br>
@@ -30,7 +30,7 @@ def verify_blocklisted_ports(self, ports_to_block: list[Port]):<br>
self.verify(blocked, "At least one port was not blocklisted")<br>
<br>
@func_test<br>
- def no_blocklisted(self):<br>
+ def no_blocklisted(self) -> None:<br>
"""Run testpmd with no blocklisted device.<br>
<br>
Steps:<br>
@@ -41,7 +41,7 @@ def no_blocklisted(self):<br>
self.verify_blocklisted_ports([])<br>
<br>
@func_test<br>
- def one_port_blocklisted(self):<br>
+ def one_port_blocklisted(self) -> None:<br>
"""Run testpmd with one blocklisted port.<br>
<br>
Steps:<br>
@@ -52,7 +52,7 @@ def one_port_blocklisted(self):<br>
self.verify_blocklisted_ports(self.topology.sut_ports[:1])<br>
<br>
@func_test<br>
- def all_but_one_port_blocklisted(self):<br>
+ def all_but_one_port_blocklisted(self) -> None:<br>
"""Run testpmd with all but one blocklisted port.<br>
<br>
Steps:<br>
diff --git a/dts/tests/TestSuite_dynamic_queue_conf.py b/dts/tests/TestSuite_dynamic_queue_conf.py<br>
index 0e9cda1b9f..3e2f9d816f 100644<br>
--- a/dts/tests/TestSuite_dynamic_queue_conf.py<br>
+++ b/dts/tests/TestSuite_dynamic_queue_conf.py<br>
@@ -277,24 +277,24 @@ def stop_queues(<br>
<br>
@requires(NicCapability.RUNTIME_RX_QUEUE_SETUP)<br>
@func_test<br>
- def rx_queue_stop(self):<br>
+ def rx_queue_stop(self) -> None:<br>
"""Run method for stopping queues with flag for Rx testing set to :data:`True`."""<br>
self.stop_queues(True)<br>
<br>
@requires(NicCapability.RUNTIME_RX_QUEUE_SETUP)<br>
@func_test<br>
- def rx_queue_configuration(self):<br>
+ def rx_queue_configuration(self) -> None:<br>
"""Run method for configuring queues with flag for Rx testing set to :data:`True`."""<br>
self.modify_ring_size(True)<br>
<br>
@requires(NicCapability.RUNTIME_TX_QUEUE_SETUP)<br>
@func_test<br>
- def tx_queue_stop(self):<br>
+ def tx_queue_stop(self) -> None:<br>
"""Run method for stopping queues with flag for Rx testing set to :data:`False`."""<br>
self.stop_queues(False)<br>
<br>
@requires(NicCapability.RUNTIME_TX_QUEUE_SETUP)<br>
@func_test<br>
- def tx_queue_configuration(self):<br>
+ def tx_queue_configuration(self) -> None:<br>
"""Run method for configuring queues with flag for Rx testing set to :data:`False`."""<br>
self.modify_ring_size(False)<br>
diff --git a/dts/tests/TestSuite_port_restart_config_persistency.py b/dts/tests/TestSuite_port_restart_config_persistency.py<br>
index 42ea221586..b773bdfade 100644<br>
--- a/dts/tests/TestSuite_port_restart_config_persistency.py<br>
+++ b/dts/tests/TestSuite_port_restart_config_persistency.py<br>
@@ -21,7 +21,7 @@<br>
class TestPortRestartConfigPersistency(TestSuite):<br>
"""Port config persistency test suite."""<br>
<br>
- def restart_port_and_verify(self, id, testpmd, changed_value) -> None:<br>
+ def restart_port_and_verify(self, id: int, testpmd: TestPmdShell, changed_value: str) -> None:<br>
"""Fetch port config, restart and verify persistency."""<br>
testpmd.start_all_ports()<br>
testpmd.wait_link_status_up(port_id=id, timeout=10)<br>
-- <br>
2.50.1<br>
<br>
</blockquote></div>