DPDK patches and discussions
 help / color / mirror / Atom feed
From: Yoan Picchi <yoan.picchi@foss.arm.com>
To: "Juraj Linkeš" <juraj.linkes@pantheon.tech>,
	thomas@monjalon.net, Honnappa.Nagarahalli@arm.com,
	bruce.richardson@intel.com, jspewock@iol.unh.edu,
	probb@iol.unh.edu, paul.szczepanek@arm.com
Cc: dev@dpdk.org
Subject: Re: [PATCH v5 01/23] dts: code adjustments for doc generation
Date: Wed, 8 Nov 2023 13:35:15 +0000	[thread overview]
Message-ID: <ce795b73-f1d5-43ee-a996-ddb8b449d2f9@foss.arm.com> (raw)
In-Reply-To: <20231106171601.160749-2-juraj.linkes@pantheon.tech>

On 11/6/23 17:15, Juraj Linkeš wrote:
> The standard Python tool for generating API documentation, Sphinx,
> imports modules one-by-one when generating the documentation. This
> requires code changes:
> * properly guarding argument parsing in the if __name__ == '__main__'
>    block,
> * the logger used by DTS runner underwent the same treatment so that it
>    doesn't create log files outside of a DTS run,
> * however, DTS uses the arguments to construct an object holding global
>    variables. The defaults for the global variables needed to be moved
>    from argument parsing elsewhere,
> * importing the remote_session module from framework resulted in
>    circular imports because of one module trying to import another
>    module. This is fixed by reorganizing the code,
> * some code reorganization was done because the resulting structure
>    makes more sense, improving documentation clarity.
> 
> The are some other changes which are documentation related:
> * added missing type annotation so they appear in the generated docs,
> * reordered arguments in some methods,
> * removed superfluous arguments and attributes,
> * change private functions/methods/attributes to private and vice-versa.
> 
> The above all appear in the generated documentation and the with them,
> the documentation is improved.
> 
> Signed-off-by: Juraj Linkeš <juraj.linkes@pantheon.tech>
> ---
>   dts/framework/config/__init__.py              | 10 ++-
>   dts/framework/dts.py                          | 33 +++++--
>   dts/framework/exception.py                    | 54 +++++-------
>   dts/framework/remote_session/__init__.py      | 41 ++++-----
>   .../interactive_remote_session.py             |  0
>   .../{remote => }/interactive_shell.py         |  0
>   .../{remote => }/python_shell.py              |  0
>   .../remote_session/remote/__init__.py         | 27 ------
>   .../{remote => }/remote_session.py            |  0
>   .../{remote => }/ssh_session.py               | 12 +--
>   .../{remote => }/testpmd_shell.py             |  0
>   dts/framework/settings.py                     | 87 +++++++++++--------
>   dts/framework/test_result.py                  |  4 +-
>   dts/framework/test_suite.py                   |  7 +-
>   dts/framework/testbed_model/__init__.py       | 12 +--
>   dts/framework/testbed_model/{hw => }/cpu.py   | 13 +++
>   dts/framework/testbed_model/hw/__init__.py    | 27 ------
>   .../linux_session.py                          |  6 +-
>   dts/framework/testbed_model/node.py           | 26 ++++--
>   .../os_session.py                             | 22 ++---
>   dts/framework/testbed_model/{hw => }/port.py  |  0
>   .../posix_session.py                          |  4 +-
>   dts/framework/testbed_model/sut_node.py       |  8 +-
>   dts/framework/testbed_model/tg_node.py        | 30 +------
>   .../traffic_generator/__init__.py             | 24 +++++
>   .../capturing_traffic_generator.py            |  6 +-
>   .../{ => traffic_generator}/scapy.py          | 23 ++---
>   .../traffic_generator.py                      | 16 +++-
>   .../testbed_model/{hw => }/virtual_device.py  |  0
>   dts/framework/utils.py                        | 46 +++-------
>   dts/main.py                                   |  9 +-
>   31 files changed, 259 insertions(+), 288 deletions(-)
>   rename dts/framework/remote_session/{remote => }/interactive_remote_session.py (100%)
>   rename dts/framework/remote_session/{remote => }/interactive_shell.py (100%)
>   rename dts/framework/remote_session/{remote => }/python_shell.py (100%)
>   delete mode 100644 dts/framework/remote_session/remote/__init__.py
>   rename dts/framework/remote_session/{remote => }/remote_session.py (100%)
>   rename dts/framework/remote_session/{remote => }/ssh_session.py (91%)
>   rename dts/framework/remote_session/{remote => }/testpmd_shell.py (100%)
>   rename dts/framework/testbed_model/{hw => }/cpu.py (95%)
>   delete mode 100644 dts/framework/testbed_model/hw/__init__.py
>   rename dts/framework/{remote_session => testbed_model}/linux_session.py (97%)
>   rename dts/framework/{remote_session => testbed_model}/os_session.py (95%)
>   rename dts/framework/testbed_model/{hw => }/port.py (100%)
>   rename dts/framework/{remote_session => testbed_model}/posix_session.py (98%)
>   create mode 100644 dts/framework/testbed_model/traffic_generator/__init__.py
>   rename dts/framework/testbed_model/{ => traffic_generator}/capturing_traffic_generator.py (96%)
>   rename dts/framework/testbed_model/{ => traffic_generator}/scapy.py (95%)
>   rename dts/framework/testbed_model/{ => traffic_generator}/traffic_generator.py (80%)
>   rename dts/framework/testbed_model/{hw => }/virtual_device.py (100%)
> 
> diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
> index cb7e00ba34..2044c82611 100644
> --- a/dts/framework/config/__init__.py
> +++ b/dts/framework/config/__init__.py
> @@ -17,6 +17,7 @@
>   import warlock  # type: ignore[import]
>   import yaml
>   
> +from framework.exception import ConfigurationError
>   from framework.settings import SETTINGS
>   from framework.utils import StrEnum
>   
> @@ -89,7 +90,7 @@ class TrafficGeneratorConfig:
>       traffic_generator_type: TrafficGeneratorType
>   
>       @staticmethod
> -    def from_dict(d: dict):
> +    def from_dict(d: dict) -> "ScapyTrafficGeneratorConfig":

This function looks to be designed to support more trafic generator than 
just scapy, so setting its return type to scapy specifically looks 
wrong. Shouldn't it be a more generic traffic generator type? Like you 
did in create_traffic_generator()

>           # This looks useless now, but is designed to allow expansion to traffic
>           # generators that require more configuration later.
>           match TrafficGeneratorType(d["type"]):
> @@ -97,6 +98,10 @@ def from_dict(d: dict):
>                   return ScapyTrafficGeneratorConfig(
>                       traffic_generator_type=TrafficGeneratorType.SCAPY
>                   )
> +            case _:
> +                raise ConfigurationError(
> +                    f'Unknown traffic generator type "{d["type"]}".'
> +                )
>   
>   
>   @dataclass(slots=True, frozen=True)
> @@ -324,6 +329,3 @@ def load_config() -> Configuration:
>       config: dict[str, Any] = warlock.model_factory(schema, name="_Config")(config_data)
>       config_obj: Configuration = Configuration.from_dict(dict(config))
>       return config_obj
> -
> -
> -CONFIGURATION = load_config()
> diff --git a/dts/framework/dts.py b/dts/framework/dts.py
> index f773f0c38d..4c7fb0c40a 100644
> --- a/dts/framework/dts.py
> +++ b/dts/framework/dts.py
> @@ -6,19 +6,19 @@
>   import sys
>   
>   from .config import (
> -    CONFIGURATION,
>       BuildTargetConfiguration,
>       ExecutionConfiguration,
>       TestSuiteConfig,
> +    load_config,
>   )
>   from .exception import BlockingTestSuiteError
>   from .logger import DTSLOG, getLogger
>   from .test_result import BuildTargetResult, DTSResult, ExecutionResult, Result
>   from .test_suite import get_test_suites
>   from .testbed_model import SutNode, TGNode
> -from .utils import check_dts_python_version
>   
> -dts_logger: DTSLOG = getLogger("DTSRunner")
> +# dummy defaults to satisfy linters
> +dts_logger: DTSLOG = None  # type: ignore[assignment]
>   result: DTSResult = DTSResult(dts_logger)
>   
>   
> @@ -30,14 +30,18 @@ def run_all() -> None:
>       global dts_logger
>       global result
>   
> +    # create a regular DTS logger and create a new result with it
> +    dts_logger = getLogger("DTSRunner")
> +    result = DTSResult(dts_logger)
> +
>       # check the python version of the server that run dts
> -    check_dts_python_version()
> +    _check_dts_python_version()
>   
>       sut_nodes: dict[str, SutNode] = {}
>       tg_nodes: dict[str, TGNode] = {}
>       try:
>           # for all Execution sections
> -        for execution in CONFIGURATION.executions:
> +        for execution in load_config().executions:
>               sut_node = sut_nodes.get(execution.system_under_test_node.name)
>               tg_node = tg_nodes.get(execution.traffic_generator_node.name)
>   
> @@ -82,6 +86,25 @@ def run_all() -> None:
>       _exit_dts()
>   
>   
> +def _check_dts_python_version() -> None:
> +    def RED(text: str) -> str:
> +        return f"\u001B[31;1m{str(text)}\u001B[0m"
> +
> +    if sys.version_info.major < 3 or (
> +        sys.version_info.major == 3 and sys.version_info.minor < 10
> +    ):
> +        print(
> +            RED(
> +                (
> +                    "WARNING: DTS execution node's python version is lower than"
> +                    "python 3.10, is deprecated and will not work in future releases."
> +                )
> +            ),
> +            file=sys.stderr,
> +        )
> +        print(RED("Please use Python >= 3.10 instead"), file=sys.stderr)
> +
> +
>   def _run_execution(
>       sut_node: SutNode,
>       tg_node: TGNode,
> diff --git a/dts/framework/exception.py b/dts/framework/exception.py
> index 001a5a5496..7489c03570 100644
> --- a/dts/framework/exception.py
> +++ b/dts/framework/exception.py
> @@ -42,19 +42,14 @@ class SSHTimeoutError(DTSError):
>       Command execution timeout.
>       """
>   
> -    command: str
> -    output: str
>       severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR
> +    _command: str
>   
> -    def __init__(self, command: str, output: str):
> -        self.command = command
> -        self.output = output
> +    def __init__(self, command: str):
> +        self._command = command
>   
>       def __str__(self) -> str:
> -        return f"TIMEOUT on {self.command}"
> -
> -    def get_output(self) -> str:
> -        return self.output
> +        return f"TIMEOUT on {self._command}"
>   
>   
>   class SSHConnectionError(DTSError):
> @@ -62,18 +57,18 @@ class SSHConnectionError(DTSError):
>       SSH connection error.
>       """
>   
> -    host: str
> -    errors: list[str]
>       severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR
> +    _host: str
> +    _errors: list[str]
>   
>       def __init__(self, host: str, errors: list[str] | None = None):
> -        self.host = host
> -        self.errors = [] if errors is None else errors
> +        self._host = host
> +        self._errors = [] if errors is None else errors
>   
>       def __str__(self) -> str:
> -        message = f"Error trying to connect with {self.host}."
> -        if self.errors:
> -            message += f" Errors encountered while retrying: {', '.join(self.errors)}"
> +        message = f"Error trying to connect with {self._host}."
> +        if self._errors:
> +            message += f" Errors encountered while retrying: {', '.join(self._errors)}"
>   
>           return message
>   
> @@ -84,14 +79,14 @@ class SSHSessionDeadError(DTSError):
>       It can no longer be used.
>       """
>   
> -    host: str
>       severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR
> +    _host: str
>   
>       def __init__(self, host: str):
> -        self.host = host
> +        self._host = host
>   
>       def __str__(self) -> str:
> -        return f"SSH session with {self.host} has died"
> +        return f"SSH session with {self._host} has died"
>   
>   
>   class ConfigurationError(DTSError):
> @@ -107,18 +102,18 @@ class RemoteCommandExecutionError(DTSError):
>       Raised when a command executed on a Node returns a non-zero exit status.
>       """
>   
> -    command: str
> -    command_return_code: int
>       severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR
> +    command: str

did you forget the _ ?

> +    _command_return_code: int
>   
>       def __init__(self, command: str, command_return_code: int):
>           self.command = command
> -        self.command_return_code = command_return_code
> +        self._command_return_code = command_return_code
>   
>       def __str__(self) -> str:
>           return (
>               f"Command {self.command} returned a non-zero exit code: "
> -            f"{self.command_return_code}"
> +            f"{self._command_return_code}"
>           )
>   
>   
> @@ -143,22 +138,15 @@ class TestCaseVerifyError(DTSError):
>       Used in test cases to verify the expected behavior.
>       """
>   
> -    value: str
>       severity: ClassVar[ErrorSeverity] = ErrorSeverity.TESTCASE_VERIFY_ERR
>   
> -    def __init__(self, value: str):
> -        self.value = value
> -
> -    def __str__(self) -> str:
> -        return repr(self.value)
> -
>   
>   class BlockingTestSuiteError(DTSError):
> -    suite_name: str
>       severity: ClassVar[ErrorSeverity] = ErrorSeverity.BLOCKING_TESTSUITE_ERR
> +    _suite_name: str
>   
>       def __init__(self, suite_name: str) -> None:
> -        self.suite_name = suite_name
> +        self._suite_name = suite_name
>   
>       def __str__(self) -> str:
> -        return f"Blocking suite {self.suite_name} failed."
> +        return f"Blocking suite {self._suite_name} failed."
> diff --git a/dts/framework/remote_session/__init__.py b/dts/framework/remote_session/__init__.py
> index 00b6d1f03a..5e7ddb2b05 100644
> --- a/dts/framework/remote_session/__init__.py
> +++ b/dts/framework/remote_session/__init__.py
> @@ -12,29 +12,24 @@
>   
>   # pylama:ignore=W0611
>   
> -from framework.config import OS, NodeConfiguration
> -from framework.exception import ConfigurationError
> +from framework.config import NodeConfiguration
>   from framework.logger import DTSLOG
>   
> -from .linux_session import LinuxSession
> -from .os_session import InteractiveShellType, OSSession
> -from .remote import (
> -    CommandResult,
> -    InteractiveRemoteSession,
> -    InteractiveShell,
> -    PythonShell,
> -    RemoteSession,
> -    SSHSession,
> -    TestPmdDevice,
> -    TestPmdShell,
> -)
> -
> -
> -def create_session(
> +from .interactive_remote_session import InteractiveRemoteSession
> +from .interactive_shell import InteractiveShell
> +from .python_shell import PythonShell
> +from .remote_session import CommandResult, RemoteSession
> +from .ssh_session import SSHSession
> +from .testpmd_shell import TestPmdShell
> +
> +
> +def create_remote_session(
>       node_config: NodeConfiguration, name: str, logger: DTSLOG
> -) -> OSSession:
> -    match node_config.os:
> -        case OS.linux:
> -            return LinuxSession(node_config, name, logger)
> -        case _:
> -            raise ConfigurationError(f"Unsupported OS {node_config.os}")
> +) -> RemoteSession:
> +    return SSHSession(node_config, name, logger)
> +
> +
> +def create_interactive_session(
> +    node_config: NodeConfiguration, logger: DTSLOG
> +) -> InteractiveRemoteSession:
> +    return InteractiveRemoteSession(node_config, logger)
> diff --git a/dts/framework/remote_session/remote/interactive_remote_session.py b/dts/framework/remote_session/interactive_remote_session.py
> similarity index 100%
> rename from dts/framework/remote_session/remote/interactive_remote_session.py
> rename to dts/framework/remote_session/interactive_remote_session.py
> diff --git a/dts/framework/remote_session/remote/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
> similarity index 100%
> rename from dts/framework/remote_session/remote/interactive_shell.py
> rename to dts/framework/remote_session/interactive_shell.py
> diff --git a/dts/framework/remote_session/remote/python_shell.py b/dts/framework/remote_session/python_shell.py
> similarity index 100%
> rename from dts/framework/remote_session/remote/python_shell.py
> rename to dts/framework/remote_session/python_shell.py
> diff --git a/dts/framework/remote_session/remote/__init__.py b/dts/framework/remote_session/remote/__init__.py
> deleted file mode 100644
> index 06403691a5..0000000000
> --- a/dts/framework/remote_session/remote/__init__.py
> +++ /dev/null
> @@ -1,27 +0,0 @@
> -# SPDX-License-Identifier: BSD-3-Clause
> -# Copyright(c) 2023 PANTHEON.tech s.r.o.
> -# Copyright(c) 2023 University of New Hampshire
> -
> -# pylama:ignore=W0611
> -
> -from framework.config import NodeConfiguration
> -from framework.logger import DTSLOG
> -
> -from .interactive_remote_session import InteractiveRemoteSession
> -from .interactive_shell import InteractiveShell
> -from .python_shell import PythonShell
> -from .remote_session import CommandResult, RemoteSession
> -from .ssh_session import SSHSession
> -from .testpmd_shell import TestPmdDevice, TestPmdShell
> -
> -
> -def create_remote_session(
> -    node_config: NodeConfiguration, name: str, logger: DTSLOG
> -) -> RemoteSession:
> -    return SSHSession(node_config, name, logger)
> -
> -
> -def create_interactive_session(
> -    node_config: NodeConfiguration, logger: DTSLOG
> -) -> InteractiveRemoteSession:
> -    return InteractiveRemoteSession(node_config, logger)
> diff --git a/dts/framework/remote_session/remote/remote_session.py b/dts/framework/remote_session/remote_session.py
> similarity index 100%
> rename from dts/framework/remote_session/remote/remote_session.py
> rename to dts/framework/remote_session/remote_session.py
> diff --git a/dts/framework/remote_session/remote/ssh_session.py b/dts/framework/remote_session/ssh_session.py
> similarity index 91%
> rename from dts/framework/remote_session/remote/ssh_session.py
> rename to dts/framework/remote_session/ssh_session.py
> index 8d127f1601..cee11d14d6 100644
> --- a/dts/framework/remote_session/remote/ssh_session.py
> +++ b/dts/framework/remote_session/ssh_session.py
> @@ -18,9 +18,7 @@
>       SSHException,
>   )
>   
> -from framework.config import NodeConfiguration
>   from framework.exception import SSHConnectionError, SSHSessionDeadError, SSHTimeoutError
> -from framework.logger import DTSLOG
>   
>   from .remote_session import CommandResult, RemoteSession
>   
> @@ -45,14 +43,6 @@ class SSHSession(RemoteSession):
>   
>       session: Connection
>   
> -    def __init__(
> -        self,
> -        node_config: NodeConfiguration,
> -        session_name: str,
> -        logger: DTSLOG,
> -    ):
> -        super(SSHSession, self).__init__(node_config, session_name, logger)
> -
>       def _connect(self) -> None:
>           errors = []
>           retry_attempts = 10
> @@ -117,7 +107,7 @@ def _send_command(
>   
>           except CommandTimedOut as e:
>               self._logger.exception(e)
> -            raise SSHTimeoutError(command, e.result.stderr) from e
> +            raise SSHTimeoutError(command) from e
>   
>           return CommandResult(
>               self.name, command, output.stdout, output.stderr, output.return_code
> diff --git a/dts/framework/remote_session/remote/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py
> similarity index 100%
> rename from dts/framework/remote_session/remote/testpmd_shell.py
> rename to dts/framework/remote_session/testpmd_shell.py
> diff --git a/dts/framework/settings.py b/dts/framework/settings.py
> index cfa39d011b..7f5841d073 100644
> --- a/dts/framework/settings.py
> +++ b/dts/framework/settings.py
> @@ -6,7 +6,7 @@
>   import argparse
>   import os
>   from collections.abc import Callable, Iterable, Sequence
> -from dataclasses import dataclass
> +from dataclasses import dataclass, field
>   from pathlib import Path
>   from typing import Any, TypeVar
>   
> @@ -22,8 +22,8 @@ def __init__(
>               option_strings: Sequence[str],
>               dest: str,
>               nargs: str | int | None = None,
> -            const: str | None = None,
> -            default: str = None,
> +            const: bool | None = None,
> +            default: Any = None,
>               type: Callable[[str], _T | argparse.FileType | None] = None,
>               choices: Iterable[_T] | None = None,
>               required: bool = False,
> @@ -32,6 +32,12 @@ def __init__(
>           ) -> None:
>               env_var_value = os.environ.get(env_var)
>               default = env_var_value or default
> +            if const is not None:
> +                nargs = 0
> +                default = const if env_var_value else default
> +                type = None
> +                choices = None
> +                metavar = None
>               super(_EnvironmentArgument, self).__init__(
>                   option_strings,
>                   dest,
> @@ -52,22 +58,28 @@ def __call__(
>               values: Any,
>               option_string: str = None,
>           ) -> None:
> -            setattr(namespace, self.dest, values)
> +            if self.const is not None:
> +                setattr(namespace, self.dest, self.const)
> +            else:
> +                setattr(namespace, self.dest, values)
>   
>       return _EnvironmentArgument
>   
>   
> -@dataclass(slots=True, frozen=True)
> -class _Settings:
> -    config_file_path: str
> -    output_dir: str
> -    timeout: float
> -    verbose: bool
> -    skip_setup: bool
> -    dpdk_tarball_path: Path
> -    compile_timeout: float
> -    test_cases: list
> -    re_run: int
> +@dataclass(slots=True)
> +class Settings:
> +    config_file_path: Path = Path(__file__).parent.parent.joinpath("conf.yaml")
> +    output_dir: str = "output"
> +    timeout: float = 15
> +    verbose: bool = False
> +    skip_setup: bool = False
> +    dpdk_tarball_path: Path | str = "dpdk.tar.xz"
> +    compile_timeout: float = 1200
> +    test_cases: list[str] = field(default_factory=list)
> +    re_run: int = 0
> +
> +
> +SETTINGS: Settings = Settings()
>   
>   
>   def _get_parser() -> argparse.ArgumentParser:
> @@ -81,7 +93,8 @@ def _get_parser() -> argparse.ArgumentParser:
>       parser.add_argument(
>           "--config-file",
>           action=_env_arg("DTS_CFG_FILE"),
> -        default="conf.yaml",
> +        default=SETTINGS.config_file_path,
> +        type=Path,
>           help="[DTS_CFG_FILE] configuration file that describes the test cases, SUTs "
>           "and targets.",
>       )
> @@ -90,7 +103,7 @@ def _get_parser() -> argparse.ArgumentParser:
>           "--output-dir",
>           "--output",
>           action=_env_arg("DTS_OUTPUT_DIR"),
> -        default="output",
> +        default=SETTINGS.output_dir,
>           help="[DTS_OUTPUT_DIR] Output directory where dts logs and results are saved.",
>       )
>   
> @@ -98,7 +111,7 @@ def _get_parser() -> argparse.ArgumentParser:
>           "-t",
>           "--timeout",
>           action=_env_arg("DTS_TIMEOUT"),
> -        default=15,
> +        default=SETTINGS.timeout,
>           type=float,
>           help="[DTS_TIMEOUT] The default timeout for all DTS operations except for "
>           "compiling DPDK.",
> @@ -108,8 +121,9 @@ def _get_parser() -> argparse.ArgumentParser:
>           "-v",
>           "--verbose",
>           action=_env_arg("DTS_VERBOSE"),
> -        default="N",
> -        help="[DTS_VERBOSE] Set to 'Y' to enable verbose output, logging all messages "
> +        default=SETTINGS.verbose,
> +        const=True,
> +        help="[DTS_VERBOSE] Specify to enable verbose output, logging all messages "
>           "to the console.",
>       )
>   
> @@ -117,8 +131,8 @@ def _get_parser() -> argparse.ArgumentParser:
>           "-s",
>           "--skip-setup",
>           action=_env_arg("DTS_SKIP_SETUP"),
> -        default="N",
> -        help="[DTS_SKIP_SETUP] Set to 'Y' to skip all setup steps on SUT and TG nodes.",
> +        const=True,
> +        help="[DTS_SKIP_SETUP] Specify to skip all setup steps on SUT and TG nodes.",
>       )
>   
>       parser.add_argument(
> @@ -126,7 +140,7 @@ def _get_parser() -> argparse.ArgumentParser:
>           "--snapshot",
>           "--git-ref",
>           action=_env_arg("DTS_DPDK_TARBALL"),
> -        default="dpdk.tar.xz",
> +        default=SETTINGS.dpdk_tarball_path,
>           type=Path,
>           help="[DTS_DPDK_TARBALL] Path to DPDK source code tarball or a git commit ID, "
>           "tag ID or tree ID to test. To test local changes, first commit them, "
> @@ -136,7 +150,7 @@ def _get_parser() -> argparse.ArgumentParser:
>       parser.add_argument(
>           "--compile-timeout",
>           action=_env_arg("DTS_COMPILE_TIMEOUT"),
> -        default=1200,
> +        default=SETTINGS.compile_timeout,
>           type=float,
>           help="[DTS_COMPILE_TIMEOUT] The timeout for compiling DPDK.",
>       )
> @@ -153,7 +167,7 @@ def _get_parser() -> argparse.ArgumentParser:
>           "--re-run",
>           "--re_run",
>           action=_env_arg("DTS_RERUN"),
> -        default=0,
> +        default=SETTINGS.re_run,
>           type=int,
>           help="[DTS_RERUN] Re-run each test case the specified amount of times "
>           "if a test failure occurs",
> @@ -162,23 +176,22 @@ def _get_parser() -> argparse.ArgumentParser:
>       return parser
>   
>   
> -def _get_settings() -> _Settings:
> +def get_settings() -> Settings:
>       parsed_args = _get_parser().parse_args()
> -    return _Settings(
> +    return Settings(

That means we're parsing and creating a new setting object everytime 
we're trying to read the setting? Shouldn't we just save it and return a 
copy? That seems to be the old behavior, any reason to change it?

Related to this, this do mean that the previously created setting 
variable is only used to set up the parser, so it might need to be 
renamed to default_setting if it doesnt get reused.

>           config_file_path=parsed_args.config_file,
>           output_dir=parsed_args.output_dir,
>           timeout=parsed_args.timeout,
> -        verbose=(parsed_args.verbose == "Y"),
> -        skip_setup=(parsed_args.skip_setup == "Y"),
> +        verbose=parsed_args.verbose,
> +        skip_setup=parsed_args.skip_setup,
>           dpdk_tarball_path=Path(
> -            DPDKGitTarball(parsed_args.tarball, parsed_args.output_dir)
> -        )
> -        if not os.path.exists(parsed_args.tarball)
> -        else Path(parsed_args.tarball),
> +            Path(DPDKGitTarball(parsed_args.tarball, parsed_args.output_dir))
> +            if not os.path.exists(parsed_args.tarball)
> +            else Path(parsed_args.tarball)
> +        ),
>           compile_timeout=parsed_args.compile_timeout,
> -        test_cases=parsed_args.test_cases.split(",") if parsed_args.test_cases else [],
> +        test_cases=(
> +            parsed_args.test_cases.split(",") if parsed_args.test_cases else []
> +        ),
>           re_run=parsed_args.re_run,
>       )
> -
> -
> -SETTINGS: _Settings = _get_settings()
> diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
> index f0fbe80f6f..603e18872c 100644
> --- a/dts/framework/test_result.py
> +++ b/dts/framework/test_result.py
> @@ -254,7 +254,7 @@ def add_build_target(
>           self._inner_results.append(build_target_result)
>           return build_target_result
>   
> -    def add_sut_info(self, sut_info: NodeInfo):
> +    def add_sut_info(self, sut_info: NodeInfo) -> None:
>           self.sut_os_name = sut_info.os_name
>           self.sut_os_version = sut_info.os_version
>           self.sut_kernel_version = sut_info.kernel_version
> @@ -297,7 +297,7 @@ def add_execution(self, sut_node: NodeConfiguration) -> ExecutionResult:
>           self._inner_results.append(execution_result)
>           return execution_result
>   
> -    def add_error(self, error) -> None:
> +    def add_error(self, error: Exception) -> None:
>           self._errors.append(error)
>   
>       def process(self) -> None:
> diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
> index 3b890c0451..d53553bf34 100644
> --- a/dts/framework/test_suite.py
> +++ b/dts/framework/test_suite.py
> @@ -11,7 +11,7 @@
>   import re
>   from ipaddress import IPv4Interface, IPv6Interface, ip_interface
>   from types import MethodType
> -from typing import Union
> +from typing import Any, Union
>   
>   from scapy.layers.inet import IP  # type: ignore[import]
>   from scapy.layers.l2 import Ether  # type: ignore[import]
> @@ -26,8 +26,7 @@
>   from .logger import DTSLOG, getLogger
>   from .settings import SETTINGS
>   from .test_result import BuildTargetResult, Result, TestCaseResult, TestSuiteResult
> -from .testbed_model import SutNode, TGNode
> -from .testbed_model.hw.port import Port, PortLink
> +from .testbed_model import Port, PortLink, SutNode, TGNode
>   from .utils import get_packet_summaries
>   
>   
> @@ -453,7 +452,7 @@ def _execute_test_case(
>   
>   
>   def get_test_suites(testsuite_module_path: str) -> list[type[TestSuite]]:
> -    def is_test_suite(object) -> bool:
> +    def is_test_suite(object: Any) -> bool:
>           try:
>               if issubclass(object, TestSuite) and object is not TestSuite:
>                   return True
> diff --git a/dts/framework/testbed_model/__init__.py b/dts/framework/testbed_model/__init__.py
> index 5cbb859e47..8ced05653b 100644
> --- a/dts/framework/testbed_model/__init__.py
> +++ b/dts/framework/testbed_model/__init__.py
> @@ -9,15 +9,9 @@
>   
>   # pylama:ignore=W0611
>   
> -from .hw import (
> -    LogicalCore,
> -    LogicalCoreCount,
> -    LogicalCoreCountFilter,
> -    LogicalCoreList,
> -    LogicalCoreListFilter,
> -    VirtualDevice,
> -    lcore_filter,
> -)
> +from .cpu import LogicalCoreCount, LogicalCoreCountFilter, LogicalCoreList
>   from .node import Node
> +from .port import Port, PortLink
>   from .sut_node import SutNode
>   from .tg_node import TGNode
> +from .virtual_device import VirtualDevice
> diff --git a/dts/framework/testbed_model/hw/cpu.py b/dts/framework/testbed_model/cpu.py
> similarity index 95%
> rename from dts/framework/testbed_model/hw/cpu.py
> rename to dts/framework/testbed_model/cpu.py
> index d1918a12dc..8fe785dfe4 100644
> --- a/dts/framework/testbed_model/hw/cpu.py
> +++ b/dts/framework/testbed_model/cpu.py
> @@ -272,3 +272,16 @@ def filter(self) -> list[LogicalCore]:
>               )
>   
>           return filtered_lcores
> +
> +
> +def lcore_filter(
> +    core_list: list[LogicalCore],
> +    filter_specifier: LogicalCoreCount | LogicalCoreList,
> +    ascending: bool,
> +) -> LogicalCoreFilter:
> +    if isinstance(filter_specifier, LogicalCoreList):
> +        return LogicalCoreListFilter(core_list, filter_specifier, ascending)
> +    elif isinstance(filter_specifier, LogicalCoreCount):
> +        return LogicalCoreCountFilter(core_list, filter_specifier, ascending)
> +    else:
> +        raise ValueError(f"Unsupported filter r{filter_specifier}")
> diff --git a/dts/framework/testbed_model/hw/__init__.py b/dts/framework/testbed_model/hw/__init__.py
> deleted file mode 100644
> index 88ccac0b0e..0000000000
> --- a/dts/framework/testbed_model/hw/__init__.py
> +++ /dev/null
> @@ -1,27 +0,0 @@
> -# SPDX-License-Identifier: BSD-3-Clause
> -# Copyright(c) 2023 PANTHEON.tech s.r.o.
> -
> -# pylama:ignore=W0611
> -
> -from .cpu import (
> -    LogicalCore,
> -    LogicalCoreCount,
> -    LogicalCoreCountFilter,
> -    LogicalCoreFilter,
> -    LogicalCoreList,
> -    LogicalCoreListFilter,
> -)
> -from .virtual_device import VirtualDevice
> -
> -
> -def lcore_filter(
> -    core_list: list[LogicalCore],
> -    filter_specifier: LogicalCoreCount | LogicalCoreList,
> -    ascending: bool,
> -) -> LogicalCoreFilter:
> -    if isinstance(filter_specifier, LogicalCoreList):
> -        return LogicalCoreListFilter(core_list, filter_specifier, ascending)
> -    elif isinstance(filter_specifier, LogicalCoreCount):
> -        return LogicalCoreCountFilter(core_list, filter_specifier, ascending)
> -    else:
> -        raise ValueError(f"Unsupported filter r{filter_specifier}")
> diff --git a/dts/framework/remote_session/linux_session.py b/dts/framework/testbed_model/linux_session.py
> similarity index 97%
> rename from dts/framework/remote_session/linux_session.py
> rename to dts/framework/testbed_model/linux_session.py
> index a3f1a6bf3b..f472bb8f0f 100644
> --- a/dts/framework/remote_session/linux_session.py
> +++ b/dts/framework/testbed_model/linux_session.py
> @@ -9,10 +9,10 @@
>   from typing_extensions import NotRequired
>   
>   from framework.exception import RemoteCommandExecutionError
> -from framework.testbed_model import LogicalCore
> -from framework.testbed_model.hw.port import Port
>   from framework.utils import expand_range
>   
> +from .cpu import LogicalCore
> +from .port import Port
>   from .posix_session import PosixSession
>   
>   
> @@ -64,7 +64,7 @@ def get_remote_cpus(self, use_first_core: bool) -> list[LogicalCore]:
>               lcores.append(LogicalCore(lcore, core, socket, node))
>           return lcores
>   
> -    def get_dpdk_file_prefix(self, dpdk_prefix) -> str:
> +    def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
>           return dpdk_prefix
>   
>       def setup_hugepages(self, hugepage_amount: int, force_first_numa: bool) -> None:
> diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py
> index fc01e0bf8e..7571e7b98d 100644
> --- a/dts/framework/testbed_model/node.py
> +++ b/dts/framework/testbed_model/node.py
> @@ -12,23 +12,26 @@
>   from typing import Any, Callable, Type, Union
>   
>   from framework.config import (
> +    OS,
>       BuildTargetConfiguration,
>       ExecutionConfiguration,
>       NodeConfiguration,
>   )
> +from framework.exception import ConfigurationError
>   from framework.logger import DTSLOG, getLogger
> -from framework.remote_session import InteractiveShellType, OSSession, create_session
>   from framework.settings import SETTINGS
>   
> -from .hw import (
> +from .cpu import (
>       LogicalCore,
>       LogicalCoreCount,
>       LogicalCoreList,
>       LogicalCoreListFilter,
> -    VirtualDevice,
>       lcore_filter,
>   )
> -from .hw.port import Port
> +from .linux_session import LinuxSession
> +from .os_session import InteractiveShellType, OSSession
> +from .port import Port
> +from .virtual_device import VirtualDevice
>   
>   
>   class Node(ABC):
> @@ -69,6 +72,7 @@ def __init__(self, node_config: NodeConfiguration):
>       def _init_ports(self) -> None:
>           self.ports = [Port(self.name, port_config) for port_config in self.config.ports]
>           self.main_session.update_ports(self.ports)
> +

Is the newline intended?

>           for port in self.ports:
>               self.configure_port_state(port)
>   
> @@ -172,9 +176,9 @@ def create_interactive_shell(
>   
>           return self.main_session.create_interactive_shell(
>               shell_cls,
> -            app_args,
>               timeout,
>               privileged,
> +            app_args,
>           )
>   
>       def filter_lcores(
> @@ -205,7 +209,7 @@ def _get_remote_cpus(self) -> None:
>           self._logger.info("Getting CPU information.")
>           self.lcores = self.main_session.get_remote_cpus(self.config.use_first_core)
>   
> -    def _setup_hugepages(self):
> +    def _setup_hugepages(self) -> None:
>           """
>           Setup hugepages on the Node. Different architectures can supply different
>           amounts of memory for hugepages and numa-based hugepage allocation may need
> @@ -249,3 +253,13 @@ def skip_setup(func: Callable[..., Any]) -> Callable[..., Any]:
>               return lambda *args: None
>           else:
>               return func
> +
> +
> +def create_session(
> +    node_config: NodeConfiguration, name: str, logger: DTSLOG
> +) -> OSSession:
> +    match node_config.os:
> +        case OS.linux:
> +            return LinuxSession(node_config, name, logger)
> +        case _:
> +            raise ConfigurationError(f"Unsupported OS {node_config.os}")
> diff --git a/dts/framework/remote_session/os_session.py b/dts/framework/testbed_model/os_session.py
> similarity index 95%
> rename from dts/framework/remote_session/os_session.py
> rename to dts/framework/testbed_model/os_session.py
> index 8a709eac1c..76e595a518 100644
> --- a/dts/framework/remote_session/os_session.py
> +++ b/dts/framework/testbed_model/os_session.py
> @@ -10,19 +10,19 @@
>   
>   from framework.config import Architecture, NodeConfiguration, NodeInfo
>   from framework.logger import DTSLOG
> -from framework.remote_session.remote import InteractiveShell
> -from framework.settings import SETTINGS
> -from framework.testbed_model import LogicalCore
> -from framework.testbed_model.hw.port import Port
> -from framework.utils import MesonArgs
> -
> -from .remote import (
> +from framework.remote_session import (
>       CommandResult,
>       InteractiveRemoteSession,
> +    InteractiveShell,
>       RemoteSession,
>       create_interactive_session,
>       create_remote_session,
>   )
> +from framework.settings import SETTINGS
> +from framework.utils import MesonArgs
> +
> +from .cpu import LogicalCore
> +from .port import Port
>   
>   InteractiveShellType = TypeVar("InteractiveShellType", bound=InteractiveShell)
>   
> @@ -85,9 +85,9 @@ def send_command(
>       def create_interactive_shell(
>           self,
>           shell_cls: Type[InteractiveShellType],
> -        eal_parameters: str,
>           timeout: float,
>           privileged: bool,
> +        app_args: str,

Is there a reason why the argument position got changed? I'd guess 
because it's more idomatic to have the extra arg at the end, but I just 
want to make sure it's intended.

>       ) -> InteractiveShellType:
>           """
>           See "create_interactive_shell" in SutNode
> @@ -96,7 +96,7 @@ def create_interactive_shell(
>               self.interactive_session.session,
>               self._logger,
>               self._get_privileged_command if privileged else None,
> -            eal_parameters,
> +            app_args,
>               timeout,
>           )
>   
> @@ -113,7 +113,7 @@ def _get_privileged_command(command: str) -> str:
>           """
>   
>       @abstractmethod
> -    def guess_dpdk_remote_dir(self, remote_dir) -> PurePath:
> +    def guess_dpdk_remote_dir(self, remote_dir: str | PurePath) -> PurePath:
>           """
>           Try to find DPDK remote dir in remote_dir.
>           """
> @@ -227,7 +227,7 @@ def kill_cleanup_dpdk_apps(self, dpdk_prefix_list: Iterable[str]) -> None:
>           """
>   
>       @abstractmethod
> -    def get_dpdk_file_prefix(self, dpdk_prefix) -> str:
> +    def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
>           """
>           Get the DPDK file prefix that will be used when running DPDK apps.
>           """
> diff --git a/dts/framework/testbed_model/hw/port.py b/dts/framework/testbed_model/port.py
> similarity index 100%
> rename from dts/framework/testbed_model/hw/port.py
> rename to dts/framework/testbed_model/port.py
> diff --git a/dts/framework/remote_session/posix_session.py b/dts/framework/testbed_model/posix_session.py
> similarity index 98%
> rename from dts/framework/remote_session/posix_session.py
> rename to dts/framework/testbed_model/posix_session.py
> index 5da0516e05..1d1d5b1b26 100644
> --- a/dts/framework/remote_session/posix_session.py
> +++ b/dts/framework/testbed_model/posix_session.py
> @@ -32,7 +32,7 @@ def combine_short_options(**opts: bool) -> str:
>   
>           return ret_opts
>   
> -    def guess_dpdk_remote_dir(self, remote_dir) -> PurePosixPath:
> +    def guess_dpdk_remote_dir(self, remote_dir: str | PurePath) -> PurePosixPath:
>           remote_guess = self.join_remote_path(remote_dir, "dpdk-*")
>           result = self.send_command(f"ls -d {remote_guess} | tail -1")
>           return PurePosixPath(result.stdout)
> @@ -219,7 +219,7 @@ def _remove_dpdk_runtime_dirs(
>           for dpdk_runtime_dir in dpdk_runtime_dirs:
>               self.remove_remote_dir(dpdk_runtime_dir)
>   
> -    def get_dpdk_file_prefix(self, dpdk_prefix) -> str:
> +    def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
>           return ""
>   
>       def get_compiler_version(self, compiler_name: str) -> str:
> diff --git a/dts/framework/testbed_model/sut_node.py b/dts/framework/testbed_model/sut_node.py
> index 202aebfd06..4e33cf02ea 100644
> --- a/dts/framework/testbed_model/sut_node.py
> +++ b/dts/framework/testbed_model/sut_node.py
> @@ -15,12 +15,14 @@
>       NodeInfo,
>       SutNodeConfiguration,
>   )
> -from framework.remote_session import CommandResult, InteractiveShellType, OSSession
> +from framework.remote_session import CommandResult
>   from framework.settings import SETTINGS
>   from framework.utils import MesonArgs
>   
> -from .hw import LogicalCoreCount, LogicalCoreList, VirtualDevice
> +from .cpu import LogicalCoreCount, LogicalCoreList
>   from .node import Node
> +from .os_session import InteractiveShellType, OSSession
> +from .virtual_device import VirtualDevice
>   
>   
>   class EalParameters(object):
> @@ -289,7 +291,7 @@ def create_eal_parameters(
>           prefix: str = "dpdk",
>           append_prefix_timestamp: bool = True,
>           no_pci: bool = False,
> -        vdevs: list[VirtualDevice] = None,
> +        vdevs: list[VirtualDevice] | None = None,
>           other_eal_param: str = "",
>       ) -> "EalParameters":
>           """
> diff --git a/dts/framework/testbed_model/tg_node.py b/dts/framework/testbed_model/tg_node.py
> index 27025cfa31..166eb8430e 100644
> --- a/dts/framework/testbed_model/tg_node.py
> +++ b/dts/framework/testbed_model/tg_node.py
> @@ -16,16 +16,11 @@
>   
>   from scapy.packet import Packet  # type: ignore[import]
>   
> -from framework.config import (
> -    ScapyTrafficGeneratorConfig,
> -    TGNodeConfiguration,
> -    TrafficGeneratorType,
> -)
> -from framework.exception import ConfigurationError
> -
> -from .capturing_traffic_generator import CapturingTrafficGenerator
> -from .hw.port import Port
> +from framework.config import TGNodeConfiguration
> +
>   from .node import Node
> +from .port import Port
> +from .traffic_generator import CapturingTrafficGenerator, create_traffic_generator
>   
>   
>   class TGNode(Node):
> @@ -80,20 +75,3 @@ def close(self) -> None:
>           """Free all resources used by the node"""
>           self.traffic_generator.close()
>           super(TGNode, self).close()
> -
> -
> -def create_traffic_generator(
> -    tg_node: TGNode, traffic_generator_config: ScapyTrafficGeneratorConfig
> -) -> CapturingTrafficGenerator:
> -    """A factory function for creating traffic generator object from user config."""
> -
> -    from .scapy import ScapyTrafficGenerator
> -
> -    match traffic_generator_config.traffic_generator_type:
> -        case TrafficGeneratorType.SCAPY:
> -            return ScapyTrafficGenerator(tg_node, traffic_generator_config)
> -        case _:
> -            raise ConfigurationError(
> -                "Unknown traffic generator: "
> -                f"{traffic_generator_config.traffic_generator_type}"
> -            )
> diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/framework/testbed_model/traffic_generator/__init__.py
> new file mode 100644
> index 0000000000..11bfa1ee0f
> --- /dev/null
> +++ b/dts/framework/testbed_model/traffic_generator/__init__.py
> @@ -0,0 +1,24 @@
> +# SPDX-License-Identifier: BSD-3-Clause
> +# Copyright(c) 2023 PANTHEON.tech s.r.o.
> +
> +from framework.config import ScapyTrafficGeneratorConfig, TrafficGeneratorType
> +from framework.exception import ConfigurationError
> +from framework.testbed_model.node import Node
> +
> +from .capturing_traffic_generator import CapturingTrafficGenerator
> +from .scapy import ScapyTrafficGenerator
> +
> +
> +def create_traffic_generator(
> +    tg_node: Node, traffic_generator_config: ScapyTrafficGeneratorConfig
> +) -> CapturingTrafficGenerator:
> +    """A factory function for creating traffic generator object from user config."""
> +
> +    match traffic_generator_config.traffic_generator_type:
> +        case TrafficGeneratorType.SCAPY:
> +            return ScapyTrafficGenerator(tg_node, traffic_generator_config)
> +        case _:
> +            raise ConfigurationError(
> +                "Unknown traffic generator: "
> +                f"{traffic_generator_config.traffic_generator_type}"
> +            )
> diff --git a/dts/framework/testbed_model/capturing_traffic_generator.py b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
> similarity index 96%
> rename from dts/framework/testbed_model/capturing_traffic_generator.py
> rename to dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
> index ab98987f8e..e521211ef0 100644
> --- a/dts/framework/testbed_model/capturing_traffic_generator.py
> +++ b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
> @@ -16,9 +16,9 @@
>   from scapy.packet import Packet  # type: ignore[import]
>   
>   from framework.settings import SETTINGS
> +from framework.testbed_model.port import Port
>   from framework.utils import get_packet_summaries
>   
> -from .hw.port import Port
>   from .traffic_generator import TrafficGenerator
>   
>   
> @@ -130,7 +130,9 @@ def _send_packets_and_capture(
>           for the specified duration. It must be able to handle no received packets.
>           """
>   
> -    def _write_capture_from_packets(self, capture_name: str, packets: list[Packet]):
> +    def _write_capture_from_packets(
> +        self, capture_name: str, packets: list[Packet]
> +    ) -> None:
>           file_name = f"{SETTINGS.output_dir}/{capture_name}.pcap"
>           self._logger.debug(f"Writing packets to {file_name}.")
>           scapy.utils.wrpcap(file_name, packets)
> diff --git a/dts/framework/testbed_model/scapy.py b/dts/framework/testbed_model/traffic_generator/scapy.py
> similarity index 95%
> rename from dts/framework/testbed_model/scapy.py
> rename to dts/framework/testbed_model/traffic_generator/scapy.py
> index af0d4dbb25..51864b6e6b 100644
> --- a/dts/framework/testbed_model/scapy.py
> +++ b/dts/framework/testbed_model/traffic_generator/scapy.py
> @@ -24,16 +24,15 @@
>   from scapy.packet import Packet  # type: ignore[import]
>   
>   from framework.config import OS, ScapyTrafficGeneratorConfig
> -from framework.logger import DTSLOG, getLogger
>   from framework.remote_session import PythonShell
>   from framework.settings import SETTINGS
> +from framework.testbed_model.node import Node
> +from framework.testbed_model.port import Port
>   
>   from .capturing_traffic_generator import (
>       CapturingTrafficGenerator,
>       _get_default_capture_name,
>   )
> -from .hw.port import Port
> -from .tg_node import TGNode
>   
>   """
>   ========= BEGIN RPC FUNCTIONS =========
> @@ -146,7 +145,7 @@ def quit(self) -> None:
>           self._BaseServer__shutdown_request = True
>           return None
>   
> -    def add_rpc_function(self, name: str, function_bytes: xmlrpc.client.Binary):
> +    def add_rpc_function(self, name: str, function_bytes: xmlrpc.client.Binary) -> None:
>           """Add a function to the server.
>   
>           This is meant to be executed remotely.
> @@ -191,15 +190,9 @@ class ScapyTrafficGenerator(CapturingTrafficGenerator):
>       session: PythonShell
>       rpc_server_proxy: xmlrpc.client.ServerProxy
>       _config: ScapyTrafficGeneratorConfig
> -    _tg_node: TGNode
> -    _logger: DTSLOG
> -
> -    def __init__(self, tg_node: TGNode, config: ScapyTrafficGeneratorConfig):
> -        self._config = config
> -        self._tg_node = tg_node
> -        self._logger = getLogger(
> -            f"{self._tg_node.name} {self._config.traffic_generator_type}"
> -        )
> +
> +    def __init__(self, tg_node: Node, config: ScapyTrafficGeneratorConfig):
> +        super().__init__(tg_node, config)
>   
>           assert (
>               self._tg_node.config.os == OS.linux
> @@ -235,7 +228,7 @@ def __init__(self, tg_node: TGNode, config: ScapyTrafficGeneratorConfig):
>               function_bytes = marshal.dumps(function.__code__)
>               self.rpc_server_proxy.add_rpc_function(function.__name__, function_bytes)
>   
> -    def _start_xmlrpc_server_in_remote_python(self, listen_port: int):
> +    def _start_xmlrpc_server_in_remote_python(self, listen_port: int) -> None:
>           # load the source of the function
>           src = inspect.getsource(QuittableXMLRPCServer)
>           # Lines with only whitespace break the repl if in the middle of a function
> @@ -280,7 +273,7 @@ def _send_packets_and_capture(
>           scapy_packets = [Ether(packet.data) for packet in xmlrpc_packets]
>           return scapy_packets
>   
> -    def close(self):
> +    def close(self) -> None:
>           try:
>               self.rpc_server_proxy.quit()
>           except ConnectionRefusedError:
> diff --git a/dts/framework/testbed_model/traffic_generator.py b/dts/framework/testbed_model/traffic_generator/traffic_generator.py
> similarity index 80%
> rename from dts/framework/testbed_model/traffic_generator.py
> rename to dts/framework/testbed_model/traffic_generator/traffic_generator.py
> index 28c35d3ce4..ea7c3963da 100644
> --- a/dts/framework/testbed_model/traffic_generator.py
> +++ b/dts/framework/testbed_model/traffic_generator/traffic_generator.py
> @@ -12,11 +12,12 @@
>   
>   from scapy.packet import Packet  # type: ignore[import]
>   
> -from framework.logger import DTSLOG
> +from framework.config import TrafficGeneratorConfig
> +from framework.logger import DTSLOG, getLogger
> +from framework.testbed_model.node import Node
> +from framework.testbed_model.port import Port
>   from framework.utils import get_packet_summaries
>   
> -from .hw.port import Port
> -
>   
>   class TrafficGenerator(ABC):
>       """The base traffic generator.
> @@ -24,8 +25,17 @@ class TrafficGenerator(ABC):
>       Defines the few basic methods that each traffic generator must implement.
>       """
>   
> +    _config: TrafficGeneratorConfig
> +    _tg_node: Node
>       _logger: DTSLOG
>   
> +    def __init__(self, tg_node: Node, config: TrafficGeneratorConfig):
> +        self._config = config
> +        self._tg_node = tg_node
> +        self._logger = getLogger(
> +            f"{self._tg_node.name} {self._config.traffic_generator_type}"
> +        )
> +
>       def send_packet(self, packet: Packet, port: Port) -> None:
>           """Send a packet and block until it is fully sent.
>   
> diff --git a/dts/framework/testbed_model/hw/virtual_device.py b/dts/framework/testbed_model/virtual_device.py
> similarity index 100%
> rename from dts/framework/testbed_model/hw/virtual_device.py
> rename to dts/framework/testbed_model/virtual_device.py
> diff --git a/dts/framework/utils.py b/dts/framework/utils.py
> index d27c2c5b5f..f0c916471c 100644
> --- a/dts/framework/utils.py
> +++ b/dts/framework/utils.py
> @@ -7,7 +7,6 @@
>   import json
>   import os
>   import subprocess
> -import sys
>   from enum import Enum
>   from pathlib import Path
>   from subprocess import SubprocessError
> @@ -16,35 +15,7 @@
>   
>   from .exception import ConfigurationError
>   
> -
> -class StrEnum(Enum):
> -    @staticmethod
> -    def _generate_next_value_(
> -        name: str, start: int, count: int, last_values: object
> -    ) -> str:
> -        return name
> -
> -    def __str__(self) -> str:
> -        return self.name
> -
> -
> -REGEX_FOR_PCI_ADDRESS = "/[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}.[0-9]{1}/"
> -
> -
> -def check_dts_python_version() -> None:
> -    if sys.version_info.major < 3 or (
> -        sys.version_info.major == 3 and sys.version_info.minor < 10
> -    ):
> -        print(
> -            RED(
> -                (
> -                    "WARNING: DTS execution node's python version is lower than"
> -                    "python 3.10, is deprecated and will not work in future releases."
> -                )
> -            ),
> -            file=sys.stderr,
> -        )
> -        print(RED("Please use Python >= 3.10 instead"), file=sys.stderr)
> +REGEX_FOR_PCI_ADDRESS: str = "/[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}.[0-9]{1}/"
>   
>   
>   def expand_range(range_str: str) -> list[int]:
> @@ -67,7 +38,7 @@ def expand_range(range_str: str) -> list[int]:
>       return expanded_range
>   
>   
> -def get_packet_summaries(packets: list[Packet]):
> +def get_packet_summaries(packets: list[Packet]) -> str:
>       if len(packets) == 1:
>           packet_summaries = packets[0].summary()
>       else:
> @@ -77,8 +48,15 @@ def get_packet_summaries(packets: list[Packet]):
>       return f"Packet contents: \n{packet_summaries}"
>   
>   
> -def RED(text: str) -> str:
> -    return f"\u001B[31;1m{str(text)}\u001B[0m"
> +class StrEnum(Enum):
> +    @staticmethod
> +    def _generate_next_value_(
> +        name: str, start: int, count: int, last_values: object
> +    ) -> str:
> +        return name

I don't understand this function? I don't see it used anywhere. And the 
parameters are unused?

> +
> +    def __str__(self) -> str:
> +        return self.name
>   
>   
>   class MesonArgs(object):
> @@ -225,5 +203,5 @@ def _delete_tarball(self) -> None:
>           if self._tarball_path and os.path.exists(self._tarball_path):
>               os.remove(self._tarball_path)
>   
> -    def __fspath__(self):
> +    def __fspath__(self) -> str:
>           return str(self._tarball_path)
> diff --git a/dts/main.py b/dts/main.py
> index 43311fa847..5d4714b0c3 100755
> --- a/dts/main.py
> +++ b/dts/main.py
> @@ -10,10 +10,17 @@
>   
>   import logging
>   
> -from framework import dts
> +from framework import settings
>   
>   
>   def main() -> None:
> +    """Set DTS settings, then run DTS.
> +
> +    The DTS settings are taken from the command line arguments and the environment variables.
> +    """
> +    settings.SETTINGS = settings.get_settings()
> +    from framework import dts

Why the import *inside* the main ?

> +
>       dts.run_all()
>   
>   


  reply	other threads:[~2023-11-08 13:35 UTC|newest]

Thread overview: 257+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-23 10:40 [RFC PATCH v1 0/4] dts: add dts api docs Juraj Linkeš
2023-03-23 10:40 ` [RFC PATCH v1 1/4] dts: code adjustments for sphinx Juraj Linkeš
2023-03-23 10:40 ` [RFC PATCH v1 2/4] dts: add doc generation dependencies Juraj Linkeš
2023-03-23 10:40 ` [RFC PATCH v1 3/4] dts: add doc generation Juraj Linkeš
2023-03-23 10:40 ` [RFC PATCH v1 4/4] dts: format docstrigs to google format Juraj Linkeš
2023-04-28 19:33   ` Jeremy Spewock
2023-04-03  9:17 ` [RFC PATCH v1 0/4] dts: add dts api docs Juraj Linkeš
2023-04-03  9:42   ` Bruce Richardson
2023-04-25  8:20     ` Juraj Linkeš
2023-04-25  8:44       ` Bruce Richardson
2023-04-25  8:57         ` Juraj Linkeš
2023-04-25  9:43           ` Bruce Richardson
2023-05-03 11:33             ` Juraj Linkeš
2023-05-04 12:37 ` [RFC PATCH v2 " Juraj Linkeš
2023-05-04 12:37   ` [RFC PATCH v2 1/4] dts: code adjustments for sphinx Juraj Linkeš
2023-05-04 12:37   ` [RFC PATCH v2 2/4] dts: add doc generation dependencies Juraj Linkeš
2023-05-04 12:37   ` [RFC PATCH v2 3/4] dts: add doc generation Juraj Linkeš
2023-05-04 12:45     ` Bruce Richardson
2023-05-05  7:53       ` Juraj Linkeš
2023-05-05 10:24         ` Bruce Richardson
2023-05-05 10:41           ` Juraj Linkeš
2023-05-05 10:56     ` Bruce Richardson
2023-05-05 11:13       ` Juraj Linkeš
2023-05-05 13:28         ` Bruce Richardson
2023-05-09  9:23           ` Juraj Linkeš
2023-05-09  9:40             ` Bruce Richardson
2023-05-10 12:19               ` Juraj Linkeš
2023-05-04 12:37   ` [RFC PATCH v2 4/4] dts: format docstrigs to google format Juraj Linkeš
2023-05-05 14:06   ` [RFC PATCH v2 0/4] dts: add dts api docs Bruce Richardson
2023-05-09 15:28     ` Juraj Linkeš
2023-05-11  8:55     ` Juraj Linkeš
2023-05-11  9:14   ` [RFC PATCH v3 " Juraj Linkeš
2023-05-11  9:14     ` [RFC PATCH v3 1/4] dts: code adjustments for sphinx Juraj Linkeš
2023-05-11  9:14     ` [RFC PATCH v3 2/4] dts: add doc generation dependencies Juraj Linkeš
2023-05-11  9:14     ` [RFC PATCH v3 3/4] dts: add doc generation Juraj Linkeš
2023-05-11  9:14     ` [RFC PATCH v3 4/4] dts: format docstrigs to google format Juraj Linkeš
2023-06-21 18:27       ` Jeremy Spewock
2023-05-17 16:56     ` [RFC PATCH v3 0/4] dts: add dts api docs Bruce Richardson
2023-05-22  9:17       ` Juraj Linkeš
2023-08-31 10:04     ` [RFC PATCH v4 " Juraj Linkeš
2023-08-31 10:04       ` [RFC PATCH v4 1/4] dts: code adjustments for sphinx Juraj Linkeš
2023-10-22 14:30         ` Yoan Picchi
2023-10-23  6:44           ` Juraj Linkeš
2023-10-23 11:52             ` Yoan Picchi
2023-10-24  6:39               ` Juraj Linkeš
2023-10-24 12:21                 ` Yoan Picchi
2023-08-31 10:04       ` [RFC PATCH v4 2/4] dts: add doc generation dependencies Juraj Linkeš
2023-10-27 15:27         ` Yoan Picchi
2023-08-31 10:04       ` [RFC PATCH v4 3/4] dts: add doc generation Juraj Linkeš
2023-09-20  7:08         ` Juraj Linkeš
2023-10-26 16:43         ` Yoan Picchi
2023-10-27  9:52           ` Juraj Linkeš
2023-08-31 10:04       ` [RFC PATCH v4 4/4] dts: format docstrigs to google format Juraj Linkeš
2023-09-01 17:02         ` Jeremy Spewock
2023-10-31 12:10         ` Yoan Picchi
2023-11-02 10:17           ` Juraj Linkeš
2023-11-06 17:15       ` [PATCH v5 00/23] dts: add dts api docs Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 01/23] dts: code adjustments for doc generation Juraj Linkeš
2023-11-08 13:35           ` Yoan Picchi [this message]
2023-11-15  7:46             ` Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 02/23] dts: add docstring checker Juraj Linkeš
2023-11-07 17:38           ` Yoan Picchi
2023-11-06 17:15         ` [PATCH v5 03/23] dts: add basic developer docs Juraj Linkeš
2023-11-07 14:39           ` Yoan Picchi
2023-11-08  9:01             ` Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 04/23] dts: exceptions docstring update Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 05/23] dts: settings " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 06/23] dts: logger and " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 07/23] dts: dts runner and main " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 08/23] dts: test suite " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 09/23] dts: test result " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 10/23] dts: config " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 11/23] dts: remote session " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 12/23] dts: interactive " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 13/23] dts: port and virtual device " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 14/23] dts: cpu " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 15/23] dts: os session " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 16/23] dts: posix and linux sessions " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 17/23] dts: node " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 18/23] dts: sut and tg nodes " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 19/23] dts: base traffic generators " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 20/23] dts: scapy tg " Juraj Linkeš
2023-11-06 17:15         ` [PATCH v5 21/23] dts: test suites " Juraj Linkeš
2023-11-06 17:16         ` [PATCH v5 22/23] dts: add doc generation dependencies Juraj Linkeš
2023-11-06 17:16         ` [PATCH v5 23/23] dts: add doc generation Juraj Linkeš
2023-11-08 12:53         ` [PATCH v6 01/23] dts: code adjustments for " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 02/23] dts: add docstring checker Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 03/23] dts: add basic developer docs Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 04/23] dts: exceptions docstring update Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 05/23] dts: settings " Juraj Linkeš
2023-11-08 16:17             ` Yoan Picchi
2023-11-15 10:09               ` Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 06/23] dts: logger and " Juraj Linkeš
2023-11-08 17:14             ` Yoan Picchi
2023-11-15 10:11               ` Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 07/23] dts: dts runner and main " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 08/23] dts: test suite " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 09/23] dts: test result " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 10/23] dts: config " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 11/23] dts: remote session " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 12/23] dts: interactive " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 13/23] dts: port and virtual device " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 14/23] dts: cpu " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 15/23] dts: os session " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 16/23] dts: posix and linux sessions " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 17/23] dts: node " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 18/23] dts: sut and tg nodes " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 19/23] dts: base traffic generators " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 20/23] dts: scapy tg " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 21/23] dts: test suites " Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 22/23] dts: add doc generation dependencies Juraj Linkeš
2023-11-08 16:00             ` Yoan Picchi
2023-11-15 10:00               ` Juraj Linkeš
2023-11-08 12:53           ` [PATCH v6 23/23] dts: add doc generation Juraj Linkeš
2023-11-15 13:09             ` [PATCH v7 00/21] dts: docstrings update Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 01/21] dts: code adjustments for doc generation Juraj Linkeš
2023-11-16 21:04                 ` Jeremy Spewock
2023-11-20 16:10                   ` Juraj Linkeš
2023-11-20 16:02                 ` Yoan Picchi
2023-11-15 13:09               ` [PATCH v7 02/21] dts: add docstring checker Juraj Linkeš
2023-11-20 16:03                 ` Yoan Picchi
2023-11-15 13:09               ` [PATCH v7 03/21] dts: add basic developer docs Juraj Linkeš
2023-11-20 16:03                 ` Yoan Picchi
2023-11-15 13:09               ` [PATCH v7 04/21] dts: exceptions docstring update Juraj Linkeš
2023-11-20 16:22                 ` Yoan Picchi
2023-11-20 16:35                   ` Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 05/21] dts: settings " Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 06/21] dts: logger and utils " Juraj Linkeš
2023-11-20 16:23                 ` Yoan Picchi
2023-11-20 16:36                   ` Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 07/21] dts: dts runner and main " Juraj Linkeš
2023-11-16 21:51                 ` Jeremy Spewock
2023-11-20 16:13                   ` Juraj Linkeš
2023-11-20 17:43                 ` Yoan Picchi
2023-11-21  9:10                   ` Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 08/21] dts: test suite " Juraj Linkeš
2023-11-16 22:16                 ` Jeremy Spewock
2023-11-20 16:25                   ` Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 09/21] dts: test result " Juraj Linkeš
2023-11-16 22:47                 ` Jeremy Spewock
2023-11-20 16:33                   ` Juraj Linkeš
2023-11-30 21:20                     ` Jeremy Spewock
2023-11-15 13:09               ` [PATCH v7 10/21] dts: config " Juraj Linkeš
2023-11-21 15:08                 ` Yoan Picchi
2023-11-22 10:42                   ` Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 11/21] dts: remote session " Juraj Linkeš
2023-11-21 15:36                 ` Yoan Picchi
2023-11-22 11:13                   ` Juraj Linkeš
2023-11-22 11:25                     ` Yoan Picchi
2023-11-15 13:09               ` [PATCH v7 12/21] dts: interactive " Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 13/21] dts: port and virtual device " Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 14/21] dts: cpu " Juraj Linkeš
2023-11-21 17:45                 ` Yoan Picchi
2023-11-22 11:18                   ` Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 15/21] dts: os session " Juraj Linkeš
2023-11-22 11:50                 ` Yoan Picchi
2023-11-22 13:27                   ` Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 16/21] dts: posix and linux sessions " Juraj Linkeš
2023-11-22 13:24                 ` Yoan Picchi
2023-11-22 13:35                   ` Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 17/21] dts: node " Juraj Linkeš
2023-11-22 12:18                 ` Yoan Picchi
2023-11-22 13:28                   ` Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 18/21] dts: sut and tg nodes " Juraj Linkeš
2023-11-22 13:12                 ` Yoan Picchi
2023-11-22 13:34                   ` Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 19/21] dts: base traffic generators " Juraj Linkeš
2023-11-21 16:20                 ` Yoan Picchi
2023-11-22 11:38                   ` Juraj Linkeš
2023-11-22 11:56                     ` Yoan Picchi
2023-11-22 13:11                       ` Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 20/21] dts: scapy tg " Juraj Linkeš
2023-11-21 16:33                 ` Yoan Picchi
2023-11-22 13:18                   ` Juraj Linkeš
2023-11-15 13:09               ` [PATCH v7 21/21] dts: test suites " Juraj Linkeš
2023-11-16 17:36                 ` Yoan Picchi
2023-11-20 10:17                   ` Juraj Linkeš
2023-11-20 12:50                     ` Yoan Picchi
2023-11-22 13:40                       ` Juraj Linkeš
2023-11-23 15:13               ` [PATCH v8 00/21] dts: docstrings update Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 01/21] dts: code adjustments for doc generation Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 02/21] dts: add docstring checker Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 03/21] dts: add basic developer docs Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 04/21] dts: exceptions docstring update Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 05/21] dts: settings " Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 06/21] dts: logger and utils " Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 07/21] dts: dts runner and main " Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 08/21] dts: test suite " Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 09/21] dts: test result " Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 10/21] dts: config " Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 11/21] dts: remote session " Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 12/21] dts: interactive " Juraj Linkeš
2023-11-30 21:49                   ` Jeremy Spewock
2023-12-04  9:50                     ` Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 13/21] dts: port and virtual device " Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 14/21] dts: cpu " Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 15/21] dts: os session " Juraj Linkeš
2023-12-01 17:33                   ` Jeremy Spewock
2023-12-04  9:53                     ` Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 16/21] dts: posix and linux sessions " Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 17/21] dts: node " Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 18/21] dts: sut and tg nodes " Juraj Linkeš
2023-12-01 18:06                   ` Jeremy Spewock
2023-12-04 10:02                     ` Juraj Linkeš
2023-12-04 11:02                       ` Bruce Richardson
2023-11-23 15:13                 ` [PATCH v8 19/21] dts: base traffic generators " Juraj Linkeš
2023-12-01 18:05                   ` Jeremy Spewock
2023-12-04 10:03                     ` Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 20/21] dts: scapy tg " Juraj Linkeš
2023-12-01 18:17                   ` Jeremy Spewock
2023-12-04 10:07                     ` Juraj Linkeš
2023-11-23 15:13                 ` [PATCH v8 21/21] dts: test suites " Juraj Linkeš
2023-12-01 16:00                 ` [PATCH v8 00/21] dts: docstrings update Yoan Picchi
2023-12-01 18:23                   ` Jeremy Spewock
2023-12-04 10:24                 ` [PATCH v9 " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 01/21] dts: code adjustments for doc generation Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 02/21] dts: add docstring checker Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 03/21] dts: add basic developer docs Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 04/21] dts: exceptions docstring update Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 05/21] dts: settings " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 06/21] dts: logger and utils " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 07/21] dts: dts runner and main " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 08/21] dts: test suite " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 09/21] dts: test result " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 10/21] dts: config " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 11/21] dts: remote session " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 12/21] dts: interactive " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 13/21] dts: port and virtual device " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 14/21] dts: cpu " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 15/21] dts: os session " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 16/21] dts: posix and linux sessions " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 17/21] dts: node " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 18/21] dts: sut and tg nodes " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 19/21] dts: base traffic generators " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 20/21] dts: scapy tg " Juraj Linkeš
2023-12-04 10:24                   ` [PATCH v9 21/21] dts: test suites " Juraj Linkeš
2023-12-05 18:39                     ` Jeremy Spewock
2023-12-21 11:48                   ` [PATCH v9 00/21] dts: docstrings update Thomas Monjalon
2023-11-15 13:36             ` [PATCH v1 0/2] dts: api docs generation Juraj Linkeš
2023-11-15 13:36               ` [PATCH v1 1/2] dts: add doc generation dependencies Juraj Linkeš
2023-11-15 13:36               ` [PATCH v1 2/2] dts: add doc generation Juraj Linkeš
2024-01-22 12:00               ` [PATCH v2 0/3] dts: API docs generation Juraj Linkeš
2024-01-22 12:00                 ` [PATCH v2 1/3] dts: add doc generation dependencies Juraj Linkeš
2024-01-22 12:00                 ` [PATCH v2 2/3] dts: add API doc sources Juraj Linkeš
2024-01-22 12:00                 ` [PATCH v2 3/3] dts: add API doc generation Juraj Linkeš
2024-01-22 16:35               ` [PATCH v3 0/3] dts: API docs generation Juraj Linkeš
2024-01-22 16:35                 ` [PATCH v3 1/3] dts: add doc generation dependencies Juraj Linkeš
2024-01-22 16:35                 ` [PATCH v3 2/3] dts: add API doc sources Juraj Linkeš
2024-01-22 16:35                 ` [PATCH v3 3/3] dts: add API doc generation Juraj Linkeš
2024-01-29 17:09                   ` Jeremy Spewock
     [not found]                   ` <CAJvnSUCNjo0p-yhROF1MNLKhjiAw2QTyTHO2hpOaVVUn0xnJ0A@mail.gmail.com>
2024-02-29 18:12                     ` Nicholas Pratte
2024-04-12 10:14               ` [PATCH v4 0/3] dts: API docs generation Juraj Linkeš
2024-04-12 10:14                 ` [PATCH v4 1/3] dts: add doc generation dependencies Juraj Linkeš
2024-04-12 10:14                 ` [PATCH v4 2/3] dts: add API doc sources Juraj Linkeš
2024-04-12 10:14                 ` [PATCH v4 3/3] dts: add API doc generation Juraj Linkeš
2024-04-29 13:49                 ` [PATCH v4 0/3] dts: API docs generation Jeremy Spewock
2024-04-29 14:12                   ` Patrick Robb

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=ce795b73-f1d5-43ee-a996-ddb8b449d2f9@foss.arm.com \
    --to=yoan.picchi@foss.arm.com \
    --cc=Honnappa.Nagarahalli@arm.com \
    --cc=bruce.richardson@intel.com \
    --cc=dev@dpdk.org \
    --cc=jspewock@iol.unh.edu \
    --cc=juraj.linkes@pantheon.tech \
    --cc=paul.szczepanek@arm.com \
    --cc=probb@iol.unh.edu \
    --cc=thomas@monjalon.net \
    /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).