From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id D22BF42646;
	Tue, 26 Sep 2023 23:52:20 +0200 (CEST)
Received: from mails.dpdk.org (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id A423A40269;
	Tue, 26 Sep 2023 23:52:20 +0200 (CEST)
Received: from mail-pj1-f49.google.com (mail-pj1-f49.google.com
 [209.85.216.49]) by mails.dpdk.org (Postfix) with ESMTP id AA500400D5
 for <dev@dpdk.org>; Tue, 26 Sep 2023 23:52:18 +0200 (CEST)
Received: by mail-pj1-f49.google.com with SMTP id
 98e67ed59e1d1-278eaffd81dso1358229a91.0
 for <dev@dpdk.org>; Tue, 26 Sep 2023 14:52:18 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=iol.unh.edu; s=unh-iol; t=1695765138; x=1696369938; darn=dpdk.org;
 h=cc:to:subject:message-id:date:from:in-reply-to:references
 :mime-version:from:to:cc:subject:date:message-id:reply-to;
 bh=zdjkNwWUamXVjwaTnDAP+Xm7h8UEPAzh8Fr0/c90pDc=;
 b=Vxo41FjAk71xeG9GQPC3Vg+ilhQWHJ+bukzCp0v40jTJnlM1XBDvbgxlaA4jIaxBpJ
 ur5MuL4LKF47giYJUC0lZ5FZk9NJ2fjD64X3/qcUdXtdAujeQTBFibdwsNIxSlfi7Yev
 kIBptbwo7OzMz+V+W533rvOr1d2sp/iM7kGh4=
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20230601; t=1695765138; x=1696369938;
 h=cc:to:subject:message-id:date:from:in-reply-to:references
 :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id
 :reply-to;
 bh=zdjkNwWUamXVjwaTnDAP+Xm7h8UEPAzh8Fr0/c90pDc=;
 b=bDzmlSOJ5XWxPHHXhMWA69DpFa3int9uvGx7F0lkwFuvsBATlDMnKR5gwBI2gKb/am
 f9omU+HwyW4R8a6P0M/w5iWGhSBwsjyY2f+HFI820e4obFHNh9SL+sTCiVDZQIor0VDN
 2MWPMOeMAUT0My4Pp9w7VMbUSVyQFNQsPHadBFD6FCCb2Jxi4o35xqO6TFIlfE0SlQeu
 hd05FY3bWJAQrWjxe6pBFoVLoOhj1iafcjjBsSsqv3hOP2vY4gzYWLc+1S19EnRWY8ys
 7Vfr0icU8hnxJ+d06gqDf5r5rlEQBK+o7sknGEkxsufhC3EIVcb7IBACXJsMhhf3Pf2H
 rDrQ==
X-Gm-Message-State: AOJu0YwPfHxB4kcRjc1HLja9C72O9I0lc13rh8c+V1fpQ20gwrh6JTkS
 30Qg9Na82zGzt40QHwyOizoq7BojeEhUDIgtwCdm8A==
X-Google-Smtp-Source: AGHT+IEk1CTIakqJocHtov8+jSRVEJrFTfDtWPokieGlYfjjgsyWsqPVlaUc7f6ulXDViIhNmnIdbRbXeC8iciu3y2M=
X-Received: by 2002:a17:90b:4f85:b0:26d:2b86:dbe1 with SMTP id
 qe5-20020a17090b4f8500b0026d2b86dbe1mr8651643pjb.25.1695765137347; Tue, 26
 Sep 2023 14:52:17 -0700 (PDT)
MIME-Version: 1.0
References: <20221103132926.445627-3-juraj.linkes@pantheon.tech>
 <20230926121013.23351-1-juraj.linkes@pantheon.tech>
 <20230926121013.23351-2-juraj.linkes@pantheon.tech>
In-Reply-To: <20230926121013.23351-2-juraj.linkes@pantheon.tech>
From: Jeremy Spewock <jspewock@iol.unh.edu>
Date: Tue, 26 Sep 2023 17:52:06 -0400
Message-ID: <CAAA20UTQfKUprvs0hQtcV+ESj9xve=zJhWw8fvHieZnctRj21A@mail.gmail.com>
Subject: Re: [PATCH v2 2/2] dts: reformat to 100 line length
To: =?UTF-8?Q?Juraj_Linke=C5=A1?= <juraj.linkes@pantheon.tech>
Cc: thomas@monjalon.net, Honnappa.Nagarahalli@arm.com, 
 bruce.richardson@intel.com, probb@iol.unh.edu, stephen@networkplumber.org, 
 dev@dpdk.org
Content-Type: multipart/alternative; boundary="000000000000a26bf306064a1647"
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org

--000000000000a26bf306064a1647
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

I think this is a good idea because of all the weird places we had to break
things up with the 88 character cap. I do however also notice that in some
cases where these multi-line strings were combined back into one line it
would just have two string literals on the same line rather than them being
just oen string. I tried to point out everywhere I found this behavoir
below as it looks a little awkward in the code.

It looks good to me otherwise though.


On Tue, Sep 26, 2023 at 8:10=E2=80=AFAM Juraj Linke=C5=A1 <juraj.linkes@pan=
theon.tech>
wrote:

> Reformat to 100 from the previous 88 to unify with C recommendations.
>
> Signed-off-by: Juraj Linke=C5=A1 <juraj.linkes@pantheon.tech>
> ---
>  dts/framework/config/__init__.py              | 20 ++-----
>  dts/framework/dts.py                          | 12 +---
>  dts/framework/exception.py                    |  3 +-
>  dts/framework/remote_session/__init__.py      |  4 +-
>  dts/framework/remote_session/linux_session.py | 39 ++++---------
>  dts/framework/remote_session/posix_session.py | 30 +++-------
>  .../remote/interactive_remote_session.py      |  7 +--
>  .../remote/interactive_shell.py               |  4 +-
>  .../remote_session/remote/remote_session.py   |  8 +--
>  .../remote_session/remote/ssh_session.py      | 16 ++----
>  .../remote_session/remote/testpmd_shell.py    |  8 +--
>  dts/framework/settings.py                     |  4 +-
>  dts/framework/test_result.py                  | 16 ++----
>  dts/framework/test_suite.py                   | 57 +++++--------------
>  .../capturing_traffic_generator.py            |  4 +-
>  dts/framework/testbed_model/hw/cpu.py         | 20 ++-----
>  dts/framework/testbed_model/node.py           |  8 +--
>  dts/framework/testbed_model/scapy.py          | 16 ++----
>  dts/framework/testbed_model/sut_node.py       | 38 ++++---------
>  dts/framework/testbed_model/tg_node.py        |  7 +--
>  dts/framework/utils.py                        | 20 ++-----
>  dts/pyproject.toml                            |  4 +-
>  dts/tests/TestSuite_hello_world.py            |  4 +-
>  dts/tests/TestSuite_smoke_tests.py            | 11 +---
>  24 files changed, 93 insertions(+), 267 deletions(-)
>
> diff --git a/dts/framework/config/__init__.py
> b/dts/framework/config/__init__.py
> index cb7e00ba34..9b32cf0532 100644
> --- a/dts/framework/config/__init__.py
> +++ b/dts/framework/config/__init__.py
> @@ -140,9 +140,7 @@ def from_dict(d: dict) ->
> Union["SutNodeConfiguration", "TGNodeConfiguration"]:
>
>          if "traffic_generator" in d:
>              return TGNodeConfiguration(
> -                traffic_generator=3DTrafficGeneratorConfig.from_dict(
> -                    d["traffic_generator"]
> -                ),
> +
> traffic_generator=3DTrafficGeneratorConfig.from_dict(d["traffic_generator=
"]),
>                  **common_config,
>              )
>          else:
> @@ -249,9 +247,7 @@ def from_dict(
>          build_targets: list[BuildTargetConfiguration] =3D list(
>              map(BuildTargetConfiguration.from_dict, d["build_targets"])
>          )
> -        test_suites: list[TestSuiteConfig] =3D list(
> -            map(TestSuiteConfig.from_dict, d["test_suites"])
> -        )
> +        test_suites: list[TestSuiteConfig] =3D
> list(map(TestSuiteConfig.from_dict, d["test_suites"]))
>          sut_name =3D d["system_under_test_node"]["node_name"]
>          skip_smoke_tests =3D d.get("skip_smoke_tests", False)
>          assert sut_name in node_map, f"Unknown SUT {sut_name} in
> execution {d}"
> @@ -268,9 +264,7 @@ def from_dict(
>          ), f"Invalid TG configuration {traffic_generator_node}"
>
>          vdevs =3D (
> -            d["system_under_test_node"]["vdevs"]
> -            if "vdevs" in d["system_under_test_node"]
> -            else []
> +            d["system_under_test_node"]["vdevs"] if "vdevs" in
> d["system_under_test_node"] else []
>          )
>          return ExecutionConfiguration(
>              build_targets=3Dbuild_targets,
> @@ -299,9 +293,7 @@ def from_dict(d: dict) -> "Configuration":
>          assert len(nodes) =3D=3D len(node_map), "Duplicate node names ar=
e not
> allowed"
>
>          executions: list[ExecutionConfiguration] =3D list(
> -            map(
> -                ExecutionConfiguration.from_dict, d["executions"],
> [node_map for _ in d]
> -            )
> +            map(ExecutionConfiguration.from_dict, d["executions"],
> [node_map for _ in d])
>          )
>
>          return Configuration(executions=3Dexecutions)
> @@ -315,9 +307,7 @@ def load_config() -> Configuration:
>      with open(SETTINGS.config_file_path, "r") as f:
>          config_data =3D yaml.safe_load(f)
>
> -    schema_path =3D os.path.join(
> -        pathlib.Path(__file__).parent.resolve(), "conf_yaml_schema.json"
> -    )
> +    schema_path =3D os.path.join(pathlib.Path(__file__).parent.resolve()=
,
> "conf_yaml_schema.json")
>
>      with open(schema_path, "r") as f:
>          schema =3D json.load(f)
> diff --git a/dts/framework/dts.py b/dts/framework/dts.py
> index f773f0c38d..e2aada5a23 100644
> --- a/dts/framework/dts.py
> +++ b/dts/framework/dts.py
> @@ -92,9 +92,7 @@ def _run_execution(
>      Run the given execution. This involves running the execution setup a=
s
> well as
>      running all build targets in the given execution.
>      """
> -    dts_logger.info(
> -        f"Running execution with SUT '{
> execution.system_under_test_node.name}'."
> -    )
> +    dts_logger.info(f"Running execution with SUT '{
> execution.system_under_test_node.name}'.")
>      execution_result =3D result.add_execution(sut_node.config)
>      execution_result.add_sut_info(sut_node.node_info)
>
> @@ -107,9 +105,7 @@ def _run_execution(
>
>      else:
>          for build_target in execution.build_targets:
> -            _run_build_target(
> -                sut_node, tg_node, build_target, execution,
> execution_result
> -            )
> +            _run_build_target(sut_node, tg_node, build_target, execution=
,
> execution_result)
>
>      finally:
>          try:
> @@ -170,9 +166,7 @@ def _run_all_suites(
>          execution.test_suites[:0] =3D
> [TestSuiteConfig.from_dict("smoke_tests")]
>      for test_suite_config in execution.test_suites:
>          try:
> -            _run_single_suite(
> -                sut_node, tg_node, execution, build_target_result,
> test_suite_config
> -            )
> +            _run_single_suite(sut_node, tg_node, execution,
> build_target_result, test_suite_config)
>          except BlockingTestSuiteError as e:
>              dts_logger.exception(
>                  f"An error occurred within
> {test_suite_config.test_suite}. "
> diff --git a/dts/framework/exception.py b/dts/framework/exception.py
> index 001a5a5496..59cf9fd12a 100644
> --- a/dts/framework/exception.py
> +++ b/dts/framework/exception.py
> @@ -117,8 +117,7 @@ def __init__(self, command: str, command_return_code:
> int):
>
>      def __str__(self) -> str:
>          return (
> -            f"Command {self.command} returned a non-zero exit code: "
> -            f"{self.command_return_code}"
> +            f"Command {self.command} returned a non-zero exit code: "
> f"{self.command_return_code}"
>

If you modify this to be on the same line you actually don't need the
separate string on this line. The line could instead be the following:

f"Command {self.command} returned a non-zero exit code:
{self.command_return_code}"


>          )
>
>
> diff --git a/dts/framework/remote_session/__init__.py
> b/dts/framework/remote_session/__init__.py
> index 00b6d1f03a..6124417bd7 100644
> --- a/dts/framework/remote_session/__init__.py
> +++ b/dts/framework/remote_session/__init__.py
> @@ -30,9 +30,7 @@
>  )
>
>
> -def create_session(
> -    node_config: NodeConfiguration, name: str, logger: DTSLOG
> -) -> OSSession:
> +def create_session(node_config: NodeConfiguration, name: str, logger:
> DTSLOG) -> OSSession:
>      match node_config.os:
>          case OS.linux:
>              return LinuxSession(node_config, name, logger)
> diff --git a/dts/framework/remote_session/linux_session.py
> b/dts/framework/remote_session/linux_session.py
> index a3f1a6bf3b..aa76e25436 100644
> --- a/dts/framework/remote_session/linux_session.py
> +++ b/dts/framework/remote_session/linux_session.py
> @@ -82,9 +82,7 @@ def setup_hugepages(self, hugepage_amount: int,
> force_first_numa: bool) -> None:
>          self._mount_huge_pages()
>
>      def _get_hugepage_size(self) -> int:
> -        hugepage_size =3D self.send_command(
> -            "awk '/Hugepagesize/ {print $2}' /proc/meminfo"
> -        ).stdout
> +        hugepage_size =3D self.send_command("awk '/Hugepagesize/ {print
> $2}' /proc/meminfo").stdout
>          return int(hugepage_size)
>
>      def _get_hugepages_total(self) -> int:
> @@ -120,13 +118,9 @@ def _supports_numa(self) -> bool:
>          # there's no reason to do any numa specific configuration)
>          return len(self._numa_nodes) > 1
>
> -    def _configure_huge_pages(
> -        self, amount: int, size: int, force_first_numa: bool
> -    ) -> None:
> +    def _configure_huge_pages(self, amount: int, size: int,
> force_first_numa: bool) -> None:
>          self._logger.info("Configuring Hugepages.")
> -        hugepage_config_path =3D (
> -            f"/sys/kernel/mm/hugepages/hugepages-{size}kB/nr_hugepages"
> -        )
> +        hugepage_config_path =3D
> f"/sys/kernel/mm/hugepages/hugepages-{size}kB/nr_hugepages"
>          if force_first_numa and self._supports_numa():
>              # clear non-numa hugepages
>              self.send_command(f"echo 0 | tee {hugepage_config_path}",
> privileged=3DTrue)
> @@ -135,24 +129,18 @@ def _configure_huge_pages(
>                  f"/hugepages-{size}kB/nr_hugepages"
>              )
>
> -        self.send_command(
> -            f"echo {amount} | tee {hugepage_config_path}", privileged=3D=
True
> -        )
> +        self.send_command(f"echo {amount} | tee {hugepage_config_path}",
> privileged=3DTrue)
>
>      def update_ports(self, ports: list[Port]) -> None:
>          self._logger.debug("Gathering port info.")
>          for port in ports:
> -            assert (
> -                port.node =3D=3D self.name
> -            ), "Attempted to gather port info on the wrong node"
> +            assert port.node =3D=3D self.name, "Attempted to gather port
> info on the wrong node"
>
>          port_info_list =3D self._get_lshw_info()
>          for port in ports:
>              for port_info in port_info_list:
>                  if f"pci@{port.pci}" =3D=3D port_info.get("businfo"):
> -                    self._update_port_attr(
> -                        port, port_info.get("logicalname"), "logical_nam=
e"
> -                    )
> +                    self._update_port_attr(port,
> port_info.get("logicalname"), "logical_name")
>                      self._update_port_attr(port, port_info.get("serial")=
,
> "mac_address")
>                      port_info_list.remove(port_info)
>                      break
> @@ -163,25 +151,18 @@ def _get_lshw_info(self) -> list[LshwOutput]:
>          output =3D self.send_command("lshw -quiet -json -C network",
> verify=3DTrue)
>          return json.loads(output.stdout)
>
> -    def _update_port_attr(
> -        self, port: Port, attr_value: str | None, attr_name: str
> -    ) -> None:
> +    def _update_port_attr(self, port: Port, attr_value: str | None,
> attr_name: str) -> None:
>          if attr_value:
>              setattr(port, attr_name, attr_value)
> -            self._logger.debug(
> -                f"Found '{attr_name}' of port {port.pci}: '{attr_value}'=
."
> -            )
> +            self._logger.debug(f"Found '{attr_name}' of port {port.pci}:
> '{attr_value}'.")
>          else:
>              self._logger.warning(
> -                f"Attempted to get '{attr_name}' of port {port.pci}, "
> -                f"but it doesn't exist."
> +                f"Attempted to get '{attr_name}' of port {port.pci}, "
> f"but it doesn't exist."
>

This is another case where the two different strings aren't needed


>              )
>
>      def configure_port_state(self, port: Port, enable: bool) -> None:
>          state =3D "up" if enable else "down"
> -        self.send_command(
> -            f"ip link set dev {port.logical_name} {state}",
> privileged=3DTrue
> -        )
> +        self.send_command(f"ip link set dev {port.logical_name} {state}"=
,
> privileged=3DTrue)
>
>      def configure_port_ip_address(
>          self,
> diff --git a/dts/framework/remote_session/posix_session.py
> b/dts/framework/remote_session/posix_session.py
> index 5da0516e05..eb59252dd1 100644
> --- a/dts/framework/remote_session/posix_session.py
> +++ b/dts/framework/remote_session/posix_session.py
> @@ -94,8 +94,7 @@ def extract_remote_tarball(
>          expected_dir: str | PurePath | None =3D None,
>      ) -> None:
>          self.send_command(
> -            f"tar xfm {remote_tarball_path} "
> -            f"-C {PurePosixPath(remote_tarball_path).parent}",
> +            f"tar xfm {remote_tarball_path} " f"-C
> {PurePosixPath(remote_tarball_path).parent}",
>

Double string here as well.


>              60,
>          )
>          if expected_dir:
> @@ -125,8 +124,7 @@ def build_dpdk(
>                  self._logger.info("Configuring DPDK build from scratch."=
)
>                  self.remove_remote_dir(remote_dpdk_build_dir)
>                  self.send_command(
> -                    f"meson setup "
> -                    f"{meson_args} {remote_dpdk_dir}
> {remote_dpdk_build_dir}",
> +                    f"meson setup " f"{meson_args} {remote_dpdk_dir}
> {remote_dpdk_build_dir}",
>

Double string.


>                      timeout,
>                      verify=3DTrue,
>                      env=3Denv_vars,
> @@ -140,9 +138,7 @@ def build_dpdk(
>              raise DPDKBuildError(f"DPDK build failed when doing
> '{e.command}'.")
>
>      def get_dpdk_version(self, build_dir: str | PurePath) -> str:
> -        out =3D self.send_command(
> -            f"cat {self.join_remote_path(build_dir, 'VERSION')}",
> verify=3DTrue
> -        )
> +        out =3D self.send_command(f"cat {self.join_remote_path(build_dir=
,
> 'VERSION')}", verify=3DTrue)
>          return out.stdout
>
>      def kill_cleanup_dpdk_apps(self, dpdk_prefix_list: Iterable[str]) ->
> None:
> @@ -156,9 +152,7 @@ def kill_cleanup_dpdk_apps(self, dpdk_prefix_list:
> Iterable[str]) -> None:
>              self._check_dpdk_hugepages(dpdk_runtime_dirs)
>              self._remove_dpdk_runtime_dirs(dpdk_runtime_dirs)
>
> -    def _get_dpdk_runtime_dirs(
> -        self, dpdk_prefix_list: Iterable[str]
> -    ) -> list[PurePosixPath]:
> +    def _get_dpdk_runtime_dirs(self, dpdk_prefix_list: Iterable[str]) ->
> list[PurePosixPath]:
>          prefix =3D PurePosixPath("/var", "run", "dpdk")
>          if not dpdk_prefix_list:
>              remote_prefixes =3D self._list_remote_dirs(prefix)
> @@ -174,9 +168,7 @@ def _list_remote_dirs(self, remote_path: str |
> PurePath) -> list[str] | None:
>          Return a list of directories of the remote_dir.
>          If remote_path doesn't exist, return None.
>          """
> -        out =3D self.send_command(
> -            f"ls -l {remote_path} | awk '/^d/ {{print $NF}}'"
> -        ).stdout
> +        out =3D self.send_command(f"ls -l {remote_path} | awk '/^d/ {{pr=
int
> $NF}}'").stdout
>          if "No such file or directory" in out:
>              return None
>          else:
> @@ -200,9 +192,7 @@ def _remote_files_exists(self, remote_path: PurePath)
> -> bool:
>          result =3D self.send_command(f"test -e {remote_path}")
>          return not result.return_code
>
> -    def _check_dpdk_hugepages(
> -        self, dpdk_runtime_dirs: Iterable[str | PurePath]
> -    ) -> None:
> +    def _check_dpdk_hugepages(self, dpdk_runtime_dirs: Iterable[str |
> PurePath]) -> None:
>          for dpdk_runtime_dir in dpdk_runtime_dirs:
>              hugepage_info =3D PurePosixPath(dpdk_runtime_dir,
> "hugepage_info")
>              if self._remote_files_exists(hugepage_info):
> @@ -213,9 +203,7 @@ def _check_dpdk_hugepages(
>                      self._logger.warning(out)
>
>  self._logger.warning("*******************************************")
>
> -    def _remove_dpdk_runtime_dirs(
> -        self, dpdk_runtime_dirs: Iterable[str | PurePath]
> -    ) -> None:
> +    def _remove_dpdk_runtime_dirs(self, dpdk_runtime_dirs: Iterable[str =
|
> PurePath]) -> None:
>          for dpdk_runtime_dir in dpdk_runtime_dirs:
>              self.remove_remote_dir(dpdk_runtime_dir)
>
> @@ -245,6 +233,4 @@ def get_node_info(self) -> NodeInfo:
>              SETTINGS.timeout,
>          ).stdout.split("\n")
>          kernel_version =3D self.send_command("uname -r",
> SETTINGS.timeout).stdout
> -        return NodeInfo(
> -            os_release_info[0].strip(), os_release_info[1].strip(),
> kernel_version
> -        )
> +        return NodeInfo(os_release_info[0].strip(),
> os_release_info[1].strip(), kernel_version)
> diff --git
> a/dts/framework/remote_session/remote/interactive_remote_session.py
> b/dts/framework/remote_session/remote/interactive_remote_session.py
> index 9085a668e8..42c99b2525 100644
> --- a/dts/framework/remote_session/remote/interactive_remote_session.py
> +++ b/dts/framework/remote_session/remote/interactive_remote_session.py
> @@ -73,9 +73,7 @@ def __init__(self, node_config: NodeConfiguration,
> _logger: DTSLOG) -> None:
>              f"Initializing interactive connection for {self.username}@
> {self.hostname}"
>          )
>          self._connect()
> -        self._logger.info(
> -            f"Interactive connection successful for {self.username}@
> {self.hostname}"
> -        )
> +        self._logger.info(f"Interactive connection successful for
> {self.username}@{self.hostname}")
>
>      def _connect(self) -> None:
>          """Establish a connection to the node.
> @@ -108,8 +106,7 @@ def _connect(self) -> None:
>                  self._logger.debug(traceback.format_exc())
>                  self._logger.warning(e)
>                  self._logger.info(
> -                    "Retrying interactive session connection: "
> -                    f"retry number {retry_attempt +1}"
> +                    "Retrying interactive session connection: " f"retry
> number {retry_attempt +1}"
>

Here you can get rid of the double string, but you would have to make sure
to add the f to the start to make the whole thing and f-string.


>                  )
>              else:
>                  break
> diff --git a/dts/framework/remote_session/remote/interactive_shell.py
> b/dts/framework/remote_session/remote/interactive_shell.py
> index c24376b2a8..4db19fb9b3 100644
> --- a/dts/framework/remote_session/remote/interactive_shell.py
> +++ b/dts/framework/remote_session/remote/interactive_shell.py
> @@ -85,9 +85,7 @@ def __init__(
>          self._app_args =3D app_args
>          self._start_application(get_privileged_command)
>
> -    def _start_application(
> -        self, get_privileged_command: Callable[[str], str] | None
> -    ) -> None:
> +    def _start_application(self, get_privileged_command: Callable[[str],
> str] | None) -> None:
>          """Starts a new interactive application based on the path to the
> app.
>
>          This method is often overridden by subclasses as their process f=
or
> diff --git a/dts/framework/remote_session/remote/remote_session.py
> b/dts/framework/remote_session/remote/remote_session.py
> index 0647d93de4..719f7d1ef7 100644
> --- a/dts/framework/remote_session/remote/remote_session.py
> +++ b/dts/framework/remote_session/remote/remote_session.py
> @@ -96,9 +96,7 @@ def send_command(
>          If verify is True, check the return code of the executed command
>          and raise a RemoteCommandExecutionError if the command failed.
>          """
> -        self._logger.info(
> -            f"Sending: '{command}'" + (f" with env vars: '{env}'" if env
> else "")
> -        )
> +        self._logger.info(f"Sending: '{command}'" + (f" with env vars:
> '{env}'" if env else ""))
>          result =3D self._send_command(command, timeout, env)
>          if verify and result.return_code:
>              self._logger.debug(
> @@ -112,9 +110,7 @@ def send_command(
>          return result
>
>      @abstractmethod
> -    def _send_command(
> -        self, command: str, timeout: float, env: dict | None
> -    ) -> CommandResult:
> +    def _send_command(self, command: str, timeout: float, env: dict |
> None) -> CommandResult:
>          """
>          Use the underlying protocol to execute the command using optiona=
l
> env vars
>          and return CommandResult.
> diff --git a/dts/framework/remote_session/remote/ssh_session.py
> b/dts/framework/remote_session/remote/ssh_session.py
> index 8d127f1601..1a7ee649ab 100644
> --- a/dts/framework/remote_session/remote/ssh_session.py
> +++ b/dts/framework/remote_session/remote/ssh_session.py
> @@ -80,9 +80,7 @@ def _connect(self) -> None:
>                  if error not in errors:
>                      errors.append(error)
>
> -                self._logger.info(
> -                    f"Retrying connection: retry number {retry_attempt +
> 1}."
> -                )
> +                self._logger.info(f"Retrying connection: retry number
> {retry_attempt + 1}.")
>
>              else:
>                  break
> @@ -92,9 +90,7 @@ def _connect(self) -> None:
>      def is_alive(self) -> bool:
>          return self.session.is_connected
>
> -    def _send_command(
> -        self, command: str, timeout: float, env: dict | None
> -    ) -> CommandResult:
> +    def _send_command(self, command: str, timeout: float, env: dict |
> None) -> CommandResult:
>          """Send a command and return the result of the execution.
>
>          Args:
> @@ -107,9 +103,7 @@ def _send_command(
>              SSHTimeoutError: The command execution timed out.
>          """
>          try:
> -            output =3D self.session.run(
> -                command, env=3Denv, warn=3DTrue, hide=3DTrue, timeout=3D=
timeout
> -            )
> +            output =3D self.session.run(command, env=3Denv, warn=3DTrue,
> hide=3DTrue, timeout=3Dtimeout)
>
>          except (UnexpectedExit, ThreadException) as e:
>              self._logger.exception(e)
> @@ -119,9 +113,7 @@ def _send_command(
>              self._logger.exception(e)
>              raise SSHTimeoutError(command, e.result.stderr) from e
>
> -        return CommandResult(
> -            self.name, command, output.stdout, output.stderr,
> output.return_code
> -        )
> +        return CommandResult(self.name, command, output.stdout,
> output.stderr, output.return_code)
>
>      def copy_from(
>          self,
> diff --git a/dts/framework/remote_session/remote/testpmd_shell.py
> b/dts/framework/remote_session/remote/testpmd_shell.py
> index 1455b5a199..08ac311016 100644
> --- a/dts/framework/remote_session/remote/testpmd_shell.py
> +++ b/dts/framework/remote_session/remote/testpmd_shell.py
> @@ -21,13 +21,9 @@ class TestPmdShell(InteractiveShell):
>      path: PurePath =3D PurePath("app", "dpdk-testpmd")
>      dpdk_app: bool =3D True
>      _default_prompt: str =3D "testpmd>"
> -    _command_extra_chars: str =3D (
> -        "\n"  # We want to append an extra newline to every command
> -    )
> +    _command_extra_chars: str =3D "\n"  # We want to append an extra
> newline to every command
>
> -    def _start_application(
> -        self, get_privileged_command: Callable[[str], str] | None
> -    ) -> None:
> +    def _start_application(self, get_privileged_command: Callable[[str],
> str] | None) -> None:
>          """See "_start_application" in InteractiveShell."""
>          self._app_args +=3D " -- -i"
>          super()._start_application(get_privileged_command)
> diff --git a/dts/framework/settings.py b/dts/framework/settings.py
> index cfa39d011b..aad444e99c 100644
> --- a/dts/framework/settings.py
> +++ b/dts/framework/settings.py
> @@ -170,9 +170,7 @@ def _get_settings() -> _Settings:
>          timeout=3Dparsed_args.timeout,
>          verbose=3D(parsed_args.verbose =3D=3D "Y"),
>          skip_setup=3D(parsed_args.skip_setup =3D=3D "Y"),
> -        dpdk_tarball_path=3DPath(
> -            DPDKGitTarball(parsed_args.tarball, parsed_args.output_dir)
> -        )
> +        dpdk_tarball_path=3DPath(DPDKGitTarball(parsed_args.tarball,
> parsed_args.output_dir))
>          if not os.path.exists(parsed_args.tarball)
>          else Path(parsed_args.tarball),
>          compile_timeout=3Dparsed_args.compile_timeout,
> diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
> index f0fbe80f6f..4c2e7e2418 100644
> --- a/dts/framework/test_result.py
> +++ b/dts/framework/test_result.py
> @@ -83,9 +83,7 @@ def __iadd__(self, other: Result) -> "Statistics":
>          """
>          self[other.name] +=3D 1
>          self["PASS RATE"] =3D (
> -            float(self[Result.PASS.name])
> -            * 100
> -            / sum(self[result.name] for result in Result)
> +            float(self[Result.PASS.name]) * 100 / sum(self[result.name]
> for result in Result)
>          )
>          return self
>
> @@ -135,9 +133,7 @@ def _get_setup_teardown_errors(self) ->
> list[Exception]:
>
>      def _get_inner_errors(self) -> list[Exception]:
>          return [
> -            error
> -            for inner_result in self._inner_results
> -            for error in inner_result.get_errors()
> +            error for inner_result in self._inner_results for error in
> inner_result.get_errors()
>          ]
>
>      def get_errors(self) -> list[Exception]:
> @@ -174,9 +170,7 @@ def add_stats(self, statistics: Statistics) -> None:
>          statistics +=3D self.result
>
>      def __bool__(self) -> bool:
> -        return (
> -            bool(self.setup_result) and bool(self.teardown_result) and
> bool(self.result)
> -        )
> +        return bool(self.setup_result) and bool(self.teardown_result) an=
d
> bool(self.result)
>
>
>  class TestSuiteResult(BaseResult):
> @@ -247,9 +241,7 @@ def __init__(self, sut_node: NodeConfiguration):
>          super(ExecutionResult, self).__init__()
>          self.sut_node =3D sut_node
>
> -    def add_build_target(
> -        self, build_target: BuildTargetConfiguration
> -    ) -> BuildTargetResult:
> +    def add_build_target(self, build_target: BuildTargetConfiguration) -=
>
> BuildTargetResult:
>          build_target_result =3D BuildTargetResult(build_target)
>          self._inner_results.append(build_target_result)
>          return build_target_result
> diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
> index 3b890c0451..46d3de4944 100644
> --- a/dts/framework/test_suite.py
> +++ b/dts/framework/test_suite.py
> @@ -102,9 +102,7 @@ def _process_links(self) -> None:
>                      tg_port.peer,
>                      tg_port.identifier,
>                  ):
> -                    self._port_links.append(
> -                        PortLink(sut_port=3Dsut_port, tg_port=3Dtg_port)
> -                    )
> +                    self._port_links.append(PortLink(sut_port=3Dsut_port=
,
> tg_port=3Dtg_port))
>
>      def set_up_suite(self) -> None:
>          """
> @@ -151,9 +149,7 @@ def configure_testbed_ipv4(self, restore: bool =3D
> False) -> None:
>      def _configure_ipv4_forwarding(self, enable: bool) -> None:
>          self.sut_node.configure_ipv4_forwarding(enable)
>
> -    def send_packet_and_capture(
> -        self, packet: Packet, duration: float =3D 1
> -    ) -> list[Packet]:
> +    def send_packet_and_capture(self, packet: Packet, duration: float =
=3D
> 1) -> list[Packet]:
>          """
>          Send a packet through the appropriate interface and
>          receive on the appropriate interface.
> @@ -202,21 +198,15 @@ def verify(self, condition: bool,
> failure_description: str) -> None:
>              self._fail_test_case_verify(failure_description)
>
>      def _fail_test_case_verify(self, failure_description: str) -> None:
> -        self._logger.debug(
> -            "A test case failed, showing the last 10 commands executed o=
n
> SUT:"
> -        )
> +        self._logger.debug("A test case failed, showing the last 10
> commands executed on SUT:")
>          for command_res in
> self.sut_node.main_session.remote_session.history[-10:]:
>              self._logger.debug(command_res.command)
> -        self._logger.debug(
> -            "A test case failed, showing the last 10 commands executed o=
n
> TG:"
> -        )
> +        self._logger.debug("A test case failed, showing the last 10
> commands executed on TG:")
>          for command_res in
> self.tg_node.main_session.remote_session.history[-10:]:
>              self._logger.debug(command_res.command)
>          raise TestCaseVerifyError(failure_description)
>
> -    def verify_packets(
> -        self, expected_packet: Packet, received_packets: list[Packet]
> -    ) -> None:
> +    def verify_packets(self, expected_packet: Packet, received_packets:
> list[Packet]) -> None:
>          for received_packet in received_packets:
>              if self._compare_packets(expected_packet, received_packet):
>                  break
> @@ -225,17 +215,11 @@ def verify_packets(
>                  f"The expected packet
> {get_packet_summaries(expected_packet)} "
>                  f"not found among received
> {get_packet_summaries(received_packets)}"
>              )
> -            self._fail_test_case_verify(
> -                "An expected packet not found among received packets."
> -            )
> +            self._fail_test_case_verify("An expected packet not found
> among received packets.")
>
> -    def _compare_packets(
> -        self, expected_packet: Packet, received_packet: Packet
> -    ) -> bool:
> +    def _compare_packets(self, expected_packet: Packet, received_packet:
> Packet) -> bool:
>          self._logger.debug(
> -            "Comparing packets: \n"
> -            f"{expected_packet.summary()}\n"
> -            f"{received_packet.summary()}"
> +            "Comparing packets: \n" f"{expected_packet.summary()}\n"
> f"{received_packet.summary()}"
>

Same situation as above where you would want to make sure to put the f at
the start.


>          )
>
>          l3 =3D IP in expected_packet.layers()
> @@ -262,14 +246,10 @@ def _compare_packets(
>              expected_payload =3D expected_payload.payload
>
>          if expected_payload:
> -            self._logger.debug(
> -                f"The expected packet did not contain {expected_payload}=
."
> -            )
> +            self._logger.debug(f"The expected packet did not contain
> {expected_payload}.")
>              return False
>          if received_payload and received_payload.__class__ !=3D Padding:
> -            self._logger.debug(
> -                "The received payload had extra layers which were not
> padding."
> -            )
> +            self._logger.debug("The received payload had extra layers
> which were not padding.")
>              return False
>          return True
>
> @@ -296,10 +276,7 @@ def _verify_l2_frame(self, received_packet: Ether,
> l3: bool) -> bool:
>
>      def _verify_l3_packet(self, received_packet: IP, expected_packet: IP=
)
> -> bool:
>          self._logger.debug("Looking at the IP layer.")
> -        if (
> -            received_packet.src !=3D expected_packet.src
> -            or received_packet.dst !=3D expected_packet.dst
> -        ):
> +        if received_packet.src !=3D expected_packet.src or
> received_packet.dst !=3D expected_packet.dst:
>              return False
>          return True
>
> @@ -373,9 +350,7 @@ def _get_test_cases(self, test_case_regex: str) ->
> list[MethodType]:
>              if self._should_be_executed(test_case_name, test_case_regex)=
:
>                  filtered_test_cases.append(test_case)
>          cases_str =3D ", ".join((x.__name__ for x in filtered_test_cases=
))
> -        self._logger.debug(
> -            f"Found test cases '{cases_str}' in
> {self.__class__.__name__}."
> -        )
> +        self._logger.debug(f"Found test cases '{cases_str}' in
> {self.__class__.__name__}.")
>          return filtered_test_cases
>
>      def _should_be_executed(self, test_case_name: str, test_case_regex:
> str) -> bool:
> @@ -445,9 +420,7 @@ def _execute_test_case(
>              self._logger.exception(f"Test case execution ERROR:
> {test_case_name}")
>              test_case_result.update(Result.ERROR, e)
>          except KeyboardInterrupt:
> -            self._logger.error(
> -                f"Test case execution INTERRUPTED by user:
> {test_case_name}"
> -            )
> +            self._logger.error(f"Test case execution INTERRUPTED by user=
:
> {test_case_name}")
>              test_case_result.update(Result.SKIP)
>              raise KeyboardInterrupt("Stop DTS")
>
> @@ -464,9 +437,7 @@ def is_test_suite(object) -> bool:
>      try:
>          testcase_module =3D importlib.import_module(testsuite_module_pat=
h)
>      except ModuleNotFoundError as e:
> -        raise ConfigurationError(
> -            f"Test suite '{testsuite_module_path}' not found."
> -        ) from e
> +        raise ConfigurationError(f"Test suite '{testsuite_module_path}'
> not found.") from e
>      return [
>          test_suite_class
>          for _, test_suite_class in inspect.getmembers(testcase_module,
> is_test_suite)
> diff --git a/dts/framework/testbed_model/capturing_traffic_generator.py
> b/dts/framework/testbed_model/capturing_traffic_generator.py
> index ab98987f8e..48d019ab21 100644
> --- a/dts/framework/testbed_model/capturing_traffic_generator.py
> +++ b/dts/framework/testbed_model/capturing_traffic_generator.py
> @@ -110,9 +110,7 @@ def send_packets_and_capture(
>              duration,
>          )
>
> -        self._logger.debug(
> -            f"Received packets: {get_packet_summaries(received_packets)}=
"
> -        )
> +        self._logger.debug(f"Received packets:
> {get_packet_summaries(received_packets)}")
>          self._write_capture_from_packets(capture_name, received_packets)
>          return received_packets
>
> diff --git a/dts/framework/testbed_model/hw/cpu.py
> b/dts/framework/testbed_model/hw/cpu.py
> index d1918a12dc..cbc5fe7fff 100644
> --- a/dts/framework/testbed_model/hw/cpu.py
> +++ b/dts/framework/testbed_model/hw/cpu.py
> @@ -54,9 +54,7 @@ def __init__(self, lcore_list: list[int] | list[str] |
> list[LogicalCore] | str):
>
>          # the input lcores may not be sorted
>          self._lcore_list.sort()
> -        self._lcore_str =3D (
> -
> f'{",".join(self._get_consecutive_lcores_range(self._lcore_list))}'
> -        )
> +        self._lcore_str =3D
> f'{",".join(self._get_consecutive_lcores_range(self._lcore_list))}'
>
>      @property
>      def lcore_list(self) -> list[int]:
> @@ -70,15 +68,11 @@ def _get_consecutive_lcores_range(self,
> lcore_ids_list: list[int]) -> list[str]:
>                  segment.append(lcore_id)
>              else:
>                  formatted_core_list.append(
> -                    f"{segment[0]}-{segment[-1]}"
> -                    if len(segment) > 1
> -                    else f"{segment[0]}"
> +                    f"{segment[0]}-{segment[-1]}" if len(segment) > 1
> else f"{segment[0]}"
>                  )
>                  current_core_index =3D lcore_ids_list.index(lcore_id)
>                  formatted_core_list.extend(
> -                    self._get_consecutive_lcores_range(
> -                        lcore_ids_list[current_core_index:]
> -                    )
> +
> self._get_consecutive_lcores_range(lcore_ids_list[current_core_index:])
>                  )
>                  segment.clear()
>                  break
> @@ -125,9 +119,7 @@ def __init__(
>          self._filter_specifier =3D filter_specifier
>
>          # sorting by core is needed in case hyperthreading is enabled
> -        self._lcores_to_filter =3D sorted(
> -            lcore_list, key=3Dlambda x: x.core, reverse=3Dnot ascending
> -        )
> +        self._lcores_to_filter =3D sorted(lcore_list, key=3Dlambda x: x.=
core,
> reverse=3Dnot ascending)
>          self.filter()
>
>      @abstractmethod
> @@ -220,9 +212,7 @@ def _filter_cores_from_socket(
>                  else:
>                      # we have enough lcores per this core
>                      continue
> -            elif self._filter_specifier.cores_per_socket > len(
> -                lcore_count_per_core_map
> -            ):
> +            elif self._filter_specifier.cores_per_socket >
> len(lcore_count_per_core_map):
>                  # only add cores if we need more
>                  lcore_count_per_core_map[lcore.core] =3D 1
>                  filtered_lcores.append(lcore)
> diff --git a/dts/framework/testbed_model/node.py
> b/dts/framework/testbed_model/node.py
> index fc01e0bf8e..ef700d8114 100644
> --- a/dts/framework/testbed_model/node.py
> +++ b/dts/framework/testbed_model/node.py
> @@ -103,18 +103,14 @@ def _tear_down_execution(self) -> None:
>          is not decorated so that the derived class doesn't have to use
> the decorator.
>          """
>
> -    def set_up_build_target(
> -        self, build_target_config: BuildTargetConfiguration
> -    ) -> None:
> +    def set_up_build_target(self, build_target_config:
> BuildTargetConfiguration) -> None:
>          """
>          Perform the build target setup that will be done for each build
> target
>          tested on this node.
>          """
>          self._set_up_build_target(build_target_config)
>
> -    def _set_up_build_target(
> -        self, build_target_config: BuildTargetConfiguration
> -    ) -> None:
> +    def _set_up_build_target(self, build_target_config:
> BuildTargetConfiguration) -> None:
>          """
>          This method exists to be optionally overwritten by derived
> classes and
>          is not decorated so that the derived class doesn't have to use
> the decorator.
> diff --git a/dts/framework/testbed_model/scapy.py
> b/dts/framework/testbed_model/scapy.py
> index af0d4dbb25..7948424951 100644
> --- a/dts/framework/testbed_model/scapy.py
> +++ b/dts/framework/testbed_model/scapy.py
> @@ -96,9 +96,7 @@ def scapy_send_packets_and_capture(
>      return [scapy_packet.build() for scapy_packet in
> sniffer.stop(join=3DTrue)]
>
>
> -def scapy_send_packets(
> -    xmlrpc_packets: list[xmlrpc.client.Binary], send_iface: str
> -) -> None:
> +def scapy_send_packets(xmlrpc_packets: list[xmlrpc.client.Binary],
> send_iface: str) -> None:
>      """RPC function to send packets.
>
>      The function is meant to be executed on the remote TG node.
> @@ -197,9 +195,7 @@ class ScapyTrafficGenerator(CapturingTrafficGenerator=
):
>      def __init__(self, tg_node: TGNode, config:
> ScapyTrafficGeneratorConfig):
>          self._config =3D config
>          self._tg_node =3D tg_node
> -        self._logger =3D getLogger(
> -            f"{self._tg_node.name} {self._config.traffic_generator_type}=
"
> -        )
> +        self._logger =3D getLogger(f"{self._tg_node.name}
> {self._config.traffic_generator_type}")
>
>          assert (
>              self._tg_node.config.os =3D=3D OS.linux
> @@ -218,9 +214,7 @@ def __init__(self, tg_node: TGNode, config:
> ScapyTrafficGeneratorConfig):
>
>  self._start_xmlrpc_server_in_remote_python(xmlrpc_server_listen_port)
>
>          # connect to the server
> -        server_url =3D (
> -            f"http://
> {self._tg_node.config.hostname}:{xmlrpc_server_listen_port}"
> -        )
> +        server_url =3D f"http://
> {self._tg_node.config.hostname}:{xmlrpc_server_listen_port}"
>          self.rpc_server_proxy =3D xmlrpc.client.ServerProxy(
>              server_url, allow_none=3DTrue, verbose=3DSETTINGS.verbose
>          )
> @@ -240,9 +234,7 @@ def _start_xmlrpc_server_in_remote_python(self,
> listen_port: int):
>          src =3D inspect.getsource(QuittableXMLRPCServer)
>          # Lines with only whitespace break the repl if in the middle of =
a
> function
>          # or class, so strip all lines containing only whitespace
> -        src =3D "\n".join(
> -            [line for line in src.splitlines() if not line.isspace() and
> line !=3D ""]
> -        )
> +        src =3D "\n".join([line for line in src.splitlines() if not
> line.isspace() and line !=3D ""])
>
>          spacing =3D "\n" * 4
>
> diff --git a/dts/framework/testbed_model/sut_node.py
> b/dts/framework/testbed_model/sut_node.py
> index 202aebfd06..dfd8c755b4 100644
> --- a/dts/framework/testbed_model/sut_node.py
> +++ b/dts/framework/testbed_model/sut_node.py
> @@ -129,9 +129,7 @@ def remote_dpdk_build_dir(self) -> PurePath:
>      @property
>      def dpdk_version(self) -> str:
>          if self._dpdk_version is None:
> -            self._dpdk_version =3D self.main_session.get_dpdk_version(
> -                self._remote_dpdk_dir
> -            )
> +            self._dpdk_version =3D
> self.main_session.get_dpdk_version(self._remote_dpdk_dir)
>          return self._dpdk_version
>
>      @property
> @@ -149,8 +147,7 @@ def compiler_version(self) -> str:
>                  )
>              else:
>                  self._logger.warning(
> -                    "Failed to get compiler version because"
> -                    "_build_target_config is None."
> +                    "Failed to get compiler version because"
> "_build_target_config is None."
>

Double string here.


>                  )
>                  return ""
>          return self._compiler_version
> @@ -163,9 +160,7 @@ def get_build_target_info(self) -> BuildTargetInfo:
>      def _guess_dpdk_remote_dir(self) -> PurePath:
>          return
> self.main_session.guess_dpdk_remote_dir(self._remote_tmp_dir)
>
> -    def _set_up_build_target(
> -        self, build_target_config: BuildTargetConfiguration
> -    ) -> None:
> +    def _set_up_build_target(self, build_target_config:
> BuildTargetConfiguration) -> None:
>          """
>          Setup DPDK on the SUT node.
>          """
> @@ -177,22 +172,17 @@ def _set_up_build_target(
>          self._copy_dpdk_tarball()
>          self._build_dpdk()
>
> -    def _configure_build_target(
> -        self, build_target_config: BuildTargetConfiguration
> -    ) -> None:
> +    def _configure_build_target(self, build_target_config:
> BuildTargetConfiguration) -> None:
>          """
>          Populate common environment variables and set build target confi=
g.
>          """
>          self._env_vars =3D {}
>          self._build_target_config =3D build_target_config
> -        self._env_vars.update(
> -
> self.main_session.get_dpdk_build_env_vars(build_target_config.arch)
> -        )
> +
> self._env_vars.update(self.main_session.get_dpdk_build_env_vars(build_tar=
get_config.arch))
>          self._env_vars["CC"] =3D build_target_config.compiler.name
>          if build_target_config.compiler_wrapper:
>              self._env_vars["CC"] =3D (
> -                f"'{build_target_config.compiler_wrapper} "
> -                f"{build_target_config.compiler.name}'"
> +                f"'{build_target_config.compiler_wrapper} " f"{
> build_target_config.compiler.name}'"
>

Double string here.


>              )
>
>      @Node.skip_setup
> @@ -224,9 +214,7 @@ def _copy_dpdk_tarball(self) -> None:
>          self.main_session.remove_remote_dir(self._remote_dpdk_dir)
>
>          # then extract to remote path
> -        self.main_session.extract_remote_tarball(
> -            remote_tarball_path, self._remote_dpdk_dir
> -        )
> +        self.main_session.extract_remote_tarball(remote_tarball_path,
> self._remote_dpdk_dir)
>
>      @Node.skip_setup
>      def _build_dpdk(self) -> None:
> @@ -263,9 +251,7 @@ def build_dpdk_app(self, app_name: str,
> **meson_dpdk_args: str | bool) -> PurePa
>          )
>
>          if app_name =3D=3D "all":
> -            return self.main_session.join_remote_path(
> -                self.remote_dpdk_build_dir, "examples"
> -            )
> +            return
> self.main_session.join_remote_path(self.remote_dpdk_build_dir, "examples"=
)
>          return self.main_session.join_remote_path(
>              self.remote_dpdk_build_dir, "examples", f"dpdk-{app_name}"
>          )
> @@ -319,9 +305,7 @@ def create_eal_parameters(
>                  '-c 0xf -a 0000:88:00.0
> --file-prefix=3Ddpdk_1112_20190809143420';
>          """
>
> -        lcore_list =3D LogicalCoreList(
> -            self.filter_lcores(lcore_filter_specifier, ascending_cores)
> -        )
> +        lcore_list =3D
> LogicalCoreList(self.filter_lcores(lcore_filter_specifier, ascending_core=
s))
>
>          if append_prefix_timestamp:
>              prefix =3D f"{prefix}_{self._dpdk_timestamp}"
> @@ -386,6 +370,4 @@ def create_interactive_shell(
>                  self.remote_dpdk_build_dir, shell_cls.path
>              )
>
> -        return super().create_interactive_shell(
> -            shell_cls, timeout, privileged, str(eal_parameters)
> -        )
> +        return super().create_interactive_shell(shell_cls, timeout,
> privileged, str(eal_parameters))
> diff --git a/dts/framework/testbed_model/tg_node.py
> b/dts/framework/testbed_model/tg_node.py
> index 27025cfa31..dca4ec0849 100644
> --- a/dts/framework/testbed_model/tg_node.py
> +++ b/dts/framework/testbed_model/tg_node.py
> @@ -45,9 +45,7 @@ class TGNode(Node):
>
>      def __init__(self, node_config: TGNodeConfiguration):
>          super(TGNode, self).__init__(node_config)
> -        self.traffic_generator =3D create_traffic_generator(
> -            self, node_config.traffic_generator
> -        )
> +        self.traffic_generator =3D create_traffic_generator(self,
> node_config.traffic_generator)
>          self._logger.info(f"Created node: {self.name}")
>
>      def send_packet_and_capture(
> @@ -94,6 +92,5 @@ def create_traffic_generator(
>              return ScapyTrafficGenerator(tg_node,
> traffic_generator_config)
>          case _:
>              raise ConfigurationError(
> -                "Unknown traffic generator: "
> -                f"{traffic_generator_config.traffic_generator_type}"
> +                "Unknown traffic generator: "
> f"{traffic_generator_config.traffic_generator_type}"
>

Double string but one that needs the whole thing to be an f-string.


>              )
> diff --git a/dts/framework/utils.py b/dts/framework/utils.py
> index d27c2c5b5f..d098d364ff 100644
> --- a/dts/framework/utils.py
> +++ b/dts/framework/utils.py
> @@ -19,9 +19,7 @@
>
>  class StrEnum(Enum):
>      @staticmethod
> -    def _generate_next_value_(
> -        name: str, start: int, count: int, last_values: object
> -    ) -> str:
> +    def _generate_next_value_(name: str, start: int, count: int,
> last_values: object) -> str:
>          return name
>
>      def __str__(self) -> str:
> @@ -32,9 +30,7 @@ def __str__(self) -> str:
>
>
>  def check_dts_python_version() -> None:
> -    if sys.version_info.major < 3 or (
> -        sys.version_info.major =3D=3D 3 and sys.version_info.minor < 10
> -    ):
> +    if sys.version_info.major < 3 or (sys.version_info.major =3D=3D 3 an=
d
> sys.version_info.minor < 10):
>          print(
>              RED(
>                  (
> @@ -60,9 +56,7 @@ def expand_range(range_str: str) -> list[int]:
>          range_boundaries =3D range_str.split("-")
>          # will throw an exception when items in range_boundaries can't b=
e
> converted,
>          # serving as type check
> -        expanded_range.extend(
> -            range(int(range_boundaries[0]), int(range_boundaries[-1]) + =
1)
> -        )
> +        expanded_range.extend(range(int(range_boundaries[0]),
> int(range_boundaries[-1]) + 1))
>
>      return expanded_range
>
> @@ -71,9 +65,7 @@ def get_packet_summaries(packets: list[Packet]):
>      if len(packets) =3D=3D 1:
>          packet_summaries =3D packets[0].summary()
>      else:
> -        packet_summaries =3D json.dumps(
> -            list(map(lambda pkt: pkt.summary(), packets)), indent=3D4
> -        )
> +        packet_summaries =3D json.dumps(list(map(lambda pkt: pkt.summary=
(),
> packets)), indent=3D4)
>      return f"Packet contents: \n{packet_summaries}"
>
>
> @@ -94,9 +86,7 @@ class MesonArgs(object):
>      _default_library: str
>
>      def __init__(self, default_library: str | None =3D None, **dpdk_args=
:
> str | bool):
> -        self._default_library =3D (
> -            f"--default-library=3D{default_library}" if default_library
> else ""
> -        )
> +        self._default_library =3D f"--default-library=3D{default_library=
}" if
> default_library else ""
>          self._dpdk_args =3D " ".join(
>              (
>                  f"-D{dpdk_arg_name}=3D{dpdk_arg_value}"
> diff --git a/dts/pyproject.toml b/dts/pyproject.toml
> index 6762edfa6b..980ac3c7db 100644
> --- a/dts/pyproject.toml
> +++ b/dts/pyproject.toml
> @@ -41,7 +41,7 @@ build-backend =3D "poetry.core.masonry.api"
>  [tool.pylama]
>  linters =3D "mccabe,pycodestyle,pyflakes"
>  format =3D "pylint"
> -max_line_length =3D 88 #
> https://black.readthedocs.io/en/stable/the_black_code_style/current_style=
.html#line-length
> +max_line_length =3D 100
>
>  [tool.mypy]
>  python_version =3D "3.10"
> @@ -55,4 +55,4 @@ profile =3D "black"
>  [tool.black]
>  target-version =3D ['py310']
>  include =3D '\.pyi?$'
> -line-length =3D 88 #
> https://black.readthedocs.io/en/stable/the_black_code_style/current_style=
.html#line-length
> +line-length
> <https://black.readthedocs.io/en/stable/the_black_code_style/current_styl=
e.html#line-length+line-length>
> =3D 100
> diff --git a/dts/tests/TestSuite_hello_world.py
> b/dts/tests/TestSuite_hello_world.py
> index 7e3d95c0cf..768ba1cfa8 100644
> --- a/dts/tests/TestSuite_hello_world.py
> +++ b/dts/tests/TestSuite_hello_world.py
> @@ -34,9 +34,7 @@ def test_hello_world_single_core(self) -> None:
>          # get the first usable core
>          lcore_amount =3D LogicalCoreCount(1, 1, 1)
>          lcores =3D LogicalCoreCountFilter(self.sut_node.lcores,
> lcore_amount).filter()
> -        eal_para =3D self.sut_node.create_eal_parameters(
> -            lcore_filter_specifier=3Dlcore_amount
> -        )
> +        eal_para =3D
> self.sut_node.create_eal_parameters(lcore_filter_specifier=3Dlcore_amount=
)
>          result =3D self.sut_node.run_dpdk_app(self.app_helloworld_path,
> eal_para)
>          self.verify(
>              f"hello from core {int(lcores[0])}" in result.stdout,
> diff --git a/dts/tests/TestSuite_smoke_tests.py
> b/dts/tests/TestSuite_smoke_tests.py
> index 4a269df75b..36119e6469 100644
> --- a/dts/tests/TestSuite_smoke_tests.py
> +++ b/dts/tests/TestSuite_smoke_tests.py
> @@ -45,13 +45,10 @@ def test_driver_tests(self) -> None:
>          for dev in self.sut_node.virtual_devices:
>              vdev_args +=3D f"--vdev {dev} "
>          vdev_args =3D vdev_args[:-1]
> -        driver_tests_command =3D (
> -            f"meson test -C {self.dpdk_build_dir_path} --suite
> driver-tests"
> -        )
> +        driver_tests_command =3D f"meson test -C {self.dpdk_build_dir_pa=
th}
> --suite driver-tests"
>          if vdev_args:
>              self._logger.info(
> -                "Running driver tests with the following virtual "
> -                f"devices: {vdev_args}"
> +                "Running driver tests with the following virtual "
> f"devices: {vdev_args}"
>

Double string that should be an f-string.


>              )
>              driver_tests_command +=3D f' --test-args "{vdev_args}"'
>
> @@ -67,9 +64,7 @@ def test_devices_listed_in_testpmd(self) -> None:
>          Test:
>              Uses testpmd driver to verify that devices have been found b=
y
> testpmd.
>          """
> -        testpmd_driver =3D self.sut_node.create_interactive_shell(
> -            TestPmdShell, privileged=3DTrue
> -        )
> +        testpmd_driver =3D
> self.sut_node.create_interactive_shell(TestPmdShell, privileged=3DTrue)
>          dev_list =3D [str(x) for x in testpmd_driver.get_devices()]
>          for nic in self.nics_in_node:
>              self.verify(
> --
> 2.34.1
>
>

--000000000000a26bf306064a1647
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div dir=3D"ltr"><div class=3D"gmail_default" style=3D"fon=
t-family:arial,sans-serif"><br></div></div><br><div class=3D"gmail_quote"><=
div dir=3D"ltr" class=3D"gmail_attr"><div style=3D"font-family:arial,sans-s=
erif" class=3D"gmail_default">I think this is a good idea because of all th=
e weird places we had to break things up with the 88 character cap. I do ho=
wever also notice that in some cases where these multi-line strings were co=
mbined back into one line it would just have two string literals on the sam=
e line rather than them being just oen string. I tried to point out everywh=
ere I found this behavoir below as it looks a little awkward in the code.</=
div><div style=3D"font-family:arial,sans-serif" class=3D"gmail_default"><br=
></div><div style=3D"font-family:arial,sans-serif" class=3D"gmail_default">=
It looks good to me otherwise though.<br></div><br></div><div dir=3D"ltr" c=
lass=3D"gmail_attr"><br></div><div dir=3D"ltr" class=3D"gmail_attr">On Tue,=
 Sep 26, 2023 at 8:10=E2=80=AFAM Juraj Linke=C5=A1 &lt;juraj.linkes@pantheo=
n.tech&gt; wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex=
">Reformat to 100 from the previous 88 to unify with C recommendations.<br>
<br>
Signed-off-by: Juraj Linke=C5=A1 &lt;juraj.linkes@pantheon.tech&gt;<br>
---<br>
=C2=A0dts/framework/config/__init__.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 | 20 ++-----<br>
=C2=A0dts/framework/dts.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | 12 +---<br>
=C2=A0dts/framework/exception.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 |=C2=A0 3 +-<br>
=C2=A0dts/framework/remote_session/__init__.py=C2=A0 =C2=A0 =C2=A0 |=C2=A0 =
4 +-<br>
=C2=A0dts/framework/remote_session/linux_session.py | 39 ++++---------<br>
=C2=A0dts/framework/remote_session/posix_session.py | 30 +++-------<br>
=C2=A0.../remote/interactive_remote_session.py=C2=A0 =C2=A0 =C2=A0 |=C2=A0 =
7 +--<br>
=C2=A0.../remote/interactive_shell.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0|=C2=A0 4 +-<br>
=C2=A0.../remote_session/remote/remote_session.py=C2=A0 =C2=A0|=C2=A0 8 +--=
<br>
=C2=A0.../remote_session/remote/ssh_session.py=C2=A0 =C2=A0 =C2=A0 | 16 ++-=
---<br>
=C2=A0.../remote_session/remote/testpmd_shell.py=C2=A0 =C2=A0 |=C2=A0 8 +--=
<br>
=C2=A0dts/framework/settings.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0|=C2=A0 4 +-<br>
=C2=A0dts/framework/test_result.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 | 16 ++----<br>
=C2=A0dts/framework/test_suite.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0| 57 +++++--------------<br>
=C2=A0.../capturing_traffic_generator.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 |=C2=A0 4 +-<br>
=C2=A0dts/framework/testbed_model/hw/cpu.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0| 20 ++-----<br>
=C2=A0dts/framework/testbed_model/node.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0|=C2=A0 8 +--<br>
=C2=A0dts/framework/testbed_model/scapy.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 | 16 ++----<br>
=C2=A0dts/framework/testbed_model/sut_node.py=C2=A0 =C2=A0 =C2=A0 =C2=A0| 3=
8 ++++---------<br>
=C2=A0dts/framework/testbed_model/tg_node.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 |=
=C2=A0 7 +--<br>
=C2=A0dts/framework/utils.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | 20 ++-----<br>
=C2=A0dts/pyproject.toml=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 |=C2=A0 4 +-<br>
=C2=A0dts/tests/TestSuite_hello_world.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 |=C2=A0 4 +-<br>
=C2=A0dts/tests/TestSuite_smoke_tests.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 | 11 +---<br>
=C2=A024 files changed, 93 insertions(+), 267 deletions(-)<br>
<br>
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init=
__.py<br>
index cb7e00ba34..9b32cf0532 100644<br>
--- a/dts/framework/config/__init__.py<br>
+++ b/dts/framework/config/__init__.py<br>
@@ -140,9 +140,7 @@ def from_dict(d: dict) -&gt; Union[&quot;SutNodeConfigu=
ration&quot;, &quot;TGNodeConfiguration&quot;]:<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if &quot;traffic_generator&quot; in d:<br=
>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return TGNodeConfiguration(=
<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 traffic_generator=
=3DTrafficGeneratorConfig.from_dict(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 d[&q=
uot;traffic_generator&quot;]<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ),<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 traffic_generator=
=3DTrafficGeneratorConfig.from_dict(d[&quot;traffic_generator&quot;]),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0**common_conf=
ig,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else:<br>
@@ -249,9 +247,7 @@ def from_dict(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0build_targets: list[BuildTargetConfigurat=
ion] =3D list(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0map(BuildTargetConfiguratio=
n.from_dict, d[&quot;build_targets&quot;])<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 test_suites: list[TestSuiteConfig] =3D list(<b=
r>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 map(TestSuiteConfig.from_dict, d=
[&quot;test_suites&quot;])<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 test_suites: list[TestSuiteConfig] =3D list(ma=
p(TestSuiteConfig.from_dict, d[&quot;test_suites&quot;]))<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0sut_name =3D d[&quot;system_under_test_no=
de&quot;][&quot;node_name&quot;]<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0skip_smoke_tests =3D d.get(&quot;skip_smo=
ke_tests&quot;, False)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0assert sut_name in node_map, f&quot;Unkno=
wn SUT {sut_name} in execution {d}&quot;<br>
@@ -268,9 +264,7 @@ def from_dict(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0), f&quot;Invalid TG configuration {traff=
ic_generator_node}&quot;<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0vdevs =3D (<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 d[&quot;system_under_test_node&q=
uot;][&quot;vdevs&quot;]<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if &quot;vdevs&quot; in d[&quot;=
system_under_test_node&quot;]<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 else []<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 d[&quot;system_under_test_node&q=
uot;][&quot;vdevs&quot;] if &quot;vdevs&quot; in d[&quot;system_under_test_=
node&quot;] else []<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return ExecutionConfiguration(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0build_targets=3Dbuild_targe=
ts,<br>
@@ -299,9 +293,7 @@ def from_dict(d: dict) -&gt; &quot;Configuration&quot;:=
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0assert len(nodes) =3D=3D len(node_map), &=
quot;Duplicate node names are not allowed&quot;<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0executions: list[ExecutionConfiguration] =
=3D list(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 map(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ExecutionConfigura=
tion.from_dict, d[&quot;executions&quot;], [node_map for _ in d]<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 map(ExecutionConfiguration.from_=
dict, d[&quot;executions&quot;], [node_map for _ in d])<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return Configuration(executions=3Dexecuti=
ons)<br>
@@ -315,9 +307,7 @@ def load_config() -&gt; Configuration:<br>
=C2=A0 =C2=A0 =C2=A0with open(SETTINGS.config_file_path, &quot;r&quot;) as =
f:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0config_data =3D yaml.safe_load(f)<br>
<br>
-=C2=A0 =C2=A0 schema_path =3D os.path.join(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 pathlib.Path(__file__).parent.resolve(), &quot=
;conf_yaml_schema.json&quot;<br>
-=C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 schema_path =3D os.path.join(pathlib.Path(__file__).parent.r=
esolve(), &quot;conf_yaml_schema.json&quot;)<br>
<br>
=C2=A0 =C2=A0 =C2=A0with open(schema_path, &quot;r&quot;) as f:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0schema =3D json.load(f)<br>
diff --git a/dts/framework/dts.py b/dts/framework/dts.py<br>
index f773f0c38d..e2aada5a23 100644<br>
--- a/dts/framework/dts.py<br>
+++ b/dts/framework/dts.py<br>
@@ -92,9 +92,7 @@ def _run_execution(<br>
=C2=A0 =C2=A0 =C2=A0Run the given execution. This involves running the exec=
ution setup as well as<br>
=C2=A0 =C2=A0 =C2=A0running all build targets in the given execution.<br>
=C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
-=C2=A0 =C2=A0 <a href=3D"http://dts_logger.info" rel=3D"noreferrer" target=
=3D"_blank">dts_logger.info</a>(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;Running execution with SUT &#39;{<a hre=
f=3D"http://execution.system_under_test_node.name" rel=3D"noreferrer" targe=
t=3D"_blank">execution.system_under_test_node.name</a>}&#39;.&quot;<br>
-=C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 <a href=3D"http://dts_logger.info" rel=3D"noreferrer" target=
=3D"_blank">dts_logger.info</a>(f&quot;Running execution with SUT &#39;{<a =
href=3D"http://execution.system_under_test_node.name" rel=3D"noreferrer" ta=
rget=3D"_blank">execution.system_under_test_node.name</a>}&#39;.&quot;)<br>
=C2=A0 =C2=A0 =C2=A0execution_result =3D result.add_execution(sut_node.conf=
ig)<br>
=C2=A0 =C2=A0 =C2=A0execution_result.add_sut_info(sut_node.node_info)<br>
<br>
@@ -107,9 +105,7 @@ def _run_execution(<br>
<br>
=C2=A0 =C2=A0 =C2=A0else:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for build_target in execution.build_targe=
ts:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _run_build_target(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 sut_node, tg_node,=
 build_target, execution, execution_result<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _run_build_target(sut_node, tg_n=
ode, build_target, execution, execution_result)<br>
<br>
=C2=A0 =C2=A0 =C2=A0finally:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0try:<br>
@@ -170,9 +166,7 @@ def _run_all_suites(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0execution.test_suites[:0] =3D [TestSuiteC=
onfig.from_dict(&quot;smoke_tests&quot;)]<br>
=C2=A0 =C2=A0 =C2=A0for test_suite_config in execution.test_suites:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0try:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _run_single_suite(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 sut_node, tg_node,=
 execution, build_target_result, test_suite_config<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _run_single_suite(sut_node, tg_n=
ode, execution, build_target_result, test_suite_config)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0except BlockingTestSuiteError as e:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dts_logger.exception(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0f&quot;An err=
or occurred within {test_suite_config.test_suite}. &quot;<br>
diff --git a/dts/framework/exception.py b/dts/framework/exception.py<br>
index 001a5a5496..59cf9fd12a 100644<br>
--- a/dts/framework/exception.py<br>
+++ b/dts/framework/exception.py<br>
@@ -117,8 +117,7 @@ def __init__(self, command: str, command_return_code: i=
nt):<br>
<br>
=C2=A0 =C2=A0 =C2=A0def __str__(self) -&gt; str:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;Command {self.command} re=
turned a non-zero exit code: &quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;{self.command_return_code=
}&quot;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 <span class=3D"gmail_default" st=
yle=3D"font-family:arial,sans-serif"></span>f&quot;Command {self.command} r=
eturned a non-zero exit code: &quot; f&quot;{self.command_return_code}&quot=
;<br></blockquote><div><br></div><div><div style=3D"font-family:arial,sans-=
serif" class=3D"gmail_default">If you modify this to be on the same line yo=
u actually don&#39;t need the separate string on this line. The line could =
instead be the following:</div><div style=3D"font-family:arial,sans-serif" =
class=3D"gmail_default"><br></div><div style=3D"font-family:arial,sans-seri=
f" class=3D"gmail_default"><span class=3D"gmail_default" style=3D"font-fami=
ly:arial,sans-serif"></span>f&quot;Command {self.command} returned a non-ze=
ro exit code: {self.command_return_code}&quot;</div></div><div>=C2=A0</div>=
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left:1px solid rgb(204,204,204);padding-left:1ex">
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
<br>
<br>
diff --git a/dts/framework/remote_session/__init__.py b/dts/framework/remot=
e_session/__init__.py<br>
index 00b6d1f03a..6124417bd7 100644<br>
--- a/dts/framework/remote_session/__init__.py<br>
+++ b/dts/framework/remote_session/__init__.py<br>
@@ -30,9 +30,7 @@<br>
=C2=A0)<br>
<br>
<br>
-def create_session(<br>
-=C2=A0 =C2=A0 node_config: NodeConfiguration, name: str, logger: DTSLOG<br=
>
-) -&gt; OSSession:<br>
+def create_session(node_config: NodeConfiguration, name: str, logger: DTSL=
OG) -&gt; OSSession:<br>
=C2=A0 =C2=A0 =C2=A0match node_config.os:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0case OS.linux:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return LinuxSession(node_co=
nfig, name, logger)<br>
diff --git a/dts/framework/remote_session/linux_session.py b/dts/framework/=
remote_session/linux_session.py<br>
index a3f1a6bf3b..aa76e25436 100644<br>
--- a/dts/framework/remote_session/linux_session.py<br>
+++ b/dts/framework/remote_session/linux_session.py<br>
@@ -82,9 +82,7 @@ def setup_hugepages(self, hugepage_amount: int, force_fir=
st_numa: bool) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._mount_huge_pages()<br>
<br>
=C2=A0 =C2=A0 =C2=A0def _get_hugepage_size(self) -&gt; int:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 hugepage_size =3D self.send_command(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot;awk &#39;/Hugepagesize/ {p=
rint $2}&#39; /proc/meminfo&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 ).stdout<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 hugepage_size =3D self.send_command(&quot;awk =
&#39;/Hugepagesize/ {print $2}&#39; /proc/meminfo&quot;).stdout<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return int(hugepage_size)<br>
<br>
=C2=A0 =C2=A0 =C2=A0def _get_hugepages_total(self) -&gt; int:<br>
@@ -120,13 +118,9 @@ def _supports_numa(self) -&gt; bool:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# there&#39;s no reason to do any numa sp=
ecific configuration)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return len(self._numa_nodes) &gt; 1<br>
<br>
-=C2=A0 =C2=A0 def _configure_huge_pages(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, amount: int, size: int, force_first_numa=
: bool<br>
-=C2=A0 =C2=A0 ) -&gt; None:<br>
+=C2=A0 =C2=A0 def _configure_huge_pages(self, amount: int, size: int, forc=
e_first_numa: bool) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._<a href=3D"http://logger.info" rel=
=3D"noreferrer" target=3D"_blank">logger.info</a>(&quot;Configuring Hugepag=
es.&quot;)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 hugepage_config_path =3D (<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;/sys/kernel/mm/hugepages/=
hugepages-{size}kB/nr_hugepages&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 hugepage_config_path =3D f&quot;/sys/kernel/mm=
/hugepages/hugepages-{size}kB/nr_hugepages&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if force_first_numa and self._supports_nu=
ma():<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# clear non-numa hugepages<=
br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.send_command(f&quot;ec=
ho 0 | tee {hugepage_config_path}&quot;, privileged=3DTrue)<br>
@@ -135,24 +129,18 @@ def _configure_huge_pages(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0f&quot;/hugep=
ages-{size}kB/nr_hugepages&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self.send_command(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;echo {amount} | tee {huge=
page_config_path}&quot;, privileged=3DTrue<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self.send_command(f&quot;echo {amount} | tee {=
hugepage_config_path}&quot;, privileged=3DTrue)<br>
<br>
=C2=A0 =C2=A0 =C2=A0def update_ports(self, ports: list[Port]) -&gt; None:<b=
r>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.debug(&quot;Gathering port i=
nfo.&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for port in ports:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 assert (<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 port.node =3D=3D <=
a href=3D"http://self.name" rel=3D"noreferrer" target=3D"_blank">self.name<=
/a><br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ), &quot;Attempted to gather por=
t info on the wrong node&quot;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 assert port.node =3D=3D <a href=
=3D"http://self.name" rel=3D"noreferrer" target=3D"_blank">self.name</a>, &=
quot;Attempted to gather port info on the wrong node&quot;<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0port_info_list =3D self._get_lshw_info()<=
br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for port in ports:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for port_info in port_info_=
list:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if f&quot;pci=
@{port.pci}&quot; =3D=3D port_info.get(&quot;businfo&quot;):<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self=
._update_port_attr(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 port, port_info.get(&quot;logicalname&quot;), &quot;logical_name=
&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br=
>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self=
._update_port_attr(port, port_info.get(&quot;logicalname&quot;), &quot;logi=
cal_name&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0self._update_port_attr(port, port_info.get(&quot;serial&quot;), &quot;ma=
c_address&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0port_info_list.remove(port_info)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0break<br>
@@ -163,25 +151,18 @@ def _get_lshw_info(self) -&gt; list[LshwOutput]:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0output =3D self.send_command(&quot;lshw -=
quiet -json -C network&quot;, verify=3DTrue)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return json.loads(output.stdout)<br>
<br>
-=C2=A0 =C2=A0 def _update_port_attr(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, port: Port, attr_value: str | None, attr=
_name: str<br>
-=C2=A0 =C2=A0 ) -&gt; None:<br>
+=C2=A0 =C2=A0 def _update_port_attr(self, port: Port, attr_value: str | No=
ne, attr_name: str) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if attr_value:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0setattr(port, attr_name, at=
tr_value)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.debug(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;Found &#39;=
{attr_name}&#39; of port {port.pci}: &#39;{attr_value}&#39;.&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.debug(f&quot;Found =
&#39;{attr_name}&#39; of port {port.pci}: &#39;{attr_value}&#39;.&quot;)<br=
>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.warning(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;Attempted t=
o get &#39;{attr_name}&#39; of port {port.pci}, &quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;but it does=
n&#39;t exist.&quot;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;Attempted t=
o get &#39;{attr_name}&#39; of port {port.pci}, &quot; f&quot;but it doesn&=
#39;t exist.&quot;<br></blockquote><div><br></div><div><div style=3D"font-f=
amily:arial,sans-serif" class=3D"gmail_default">This is another case where =
the two different strings aren&#39;t needed<br></div></div><div>=C2=A0</div=
><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left:1px solid rgb(204,204,204);padding-left:1ex">
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
<br>
=C2=A0 =C2=A0 =C2=A0def configure_port_state(self, port: Port, enable: bool=
) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0state =3D &quot;up&quot; if enable else &=
quot;down&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self.send_command(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;ip link set dev {port.log=
ical_name} {state}&quot;, privileged=3DTrue<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self.send_command(f&quot;ip link set dev {port=
.logical_name} {state}&quot;, privileged=3DTrue)<br>
<br>
=C2=A0 =C2=A0 =C2=A0def configure_port_ip_address(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self,<br>
diff --git a/dts/framework/remote_session/posix_session.py b/dts/framework/=
remote_session/posix_session.py<br>
index 5da0516e05..eb59252dd1 100644<br>
--- a/dts/framework/remote_session/posix_session.py<br>
+++ b/dts/framework/remote_session/posix_session.py<br>
@@ -94,8 +94,7 @@ def extract_remote_tarball(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0expected_dir: str | PurePath | None =3D N=
one,<br>
=C2=A0 =C2=A0 =C2=A0) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.send_command(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;tar xfm {remote_tarball_p=
ath} &quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;-C {PurePosixPath(remote_=
tarball_path).parent}&quot;,<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;tar xfm {remote_tarball_p=
ath} &quot; f&quot;-C {PurePosixPath(remote_tarball_path).parent}&quot;,<br=
></blockquote><div><br></div><div><div style=3D"font-family:arial,sans-seri=
f" class=3D"gmail_default">Double string here as well.<br></div></div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A060,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if expected_dir:<br>
@@ -125,8 +124,7 @@ def build_dpdk(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._<a href=
=3D"http://logger.info" rel=3D"noreferrer" target=3D"_blank">logger.info</a=
>(&quot;Configuring DPDK build from scratch.&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.remove_r=
emote_dir(remote_dpdk_build_dir)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.send_com=
mand(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&qu=
ot;meson setup &quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&qu=
ot;{meson_args} {remote_dpdk_dir} {remote_dpdk_build_dir}&quot;,<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&qu=
ot;meson setup &quot; f&quot;{meson_args} {remote_dpdk_dir} {remote_dpdk_bu=
ild_dir}&quot;,<br></blockquote><div><br></div><div><div style=3D"font-fami=
ly:arial,sans-serif" class=3D"gmail_default">Double string.<br></div></div>=
<div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0timeout,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0verify=3DTrue,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0env=3Denv_vars,<br>
@@ -140,9 +138,7 @@ def build_dpdk(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0raise DPDKBuildError(f&quot=
;DPDK build failed when doing &#39;{e.command}&#39;.&quot;)<br>
<br>
=C2=A0 =C2=A0 =C2=A0def get_dpdk_version(self, build_dir: str | PurePath) -=
&gt; str:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 out =3D self.send_command(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;cat {self.join_remote_pat=
h(build_dir, &#39;VERSION&#39;)}&quot;, verify=3DTrue<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 out =3D self.send_command(f&quot;cat {self.joi=
n_remote_path(build_dir, &#39;VERSION&#39;)}&quot;, verify=3DTrue)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return out.stdout<br>
<br>
=C2=A0 =C2=A0 =C2=A0def kill_cleanup_dpdk_apps(self, dpdk_prefix_list: Iter=
able[str]) -&gt; None:<br>
@@ -156,9 +152,7 @@ def kill_cleanup_dpdk_apps(self, dpdk_prefix_list: Iter=
able[str]) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._check_dpdk_hugepages(=
dpdk_runtime_dirs)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._remove_dpdk_runtime_d=
irs(dpdk_runtime_dirs)<br>
<br>
-=C2=A0 =C2=A0 def _get_dpdk_runtime_dirs(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, dpdk_prefix_list: Iterable[str]<br>
-=C2=A0 =C2=A0 ) -&gt; list[PurePosixPath]:<br>
+=C2=A0 =C2=A0 def _get_dpdk_runtime_dirs(self, dpdk_prefix_list: Iterable[=
str]) -&gt; list[PurePosixPath]:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0prefix =3D PurePosixPath(&quot;/var&quot;=
, &quot;run&quot;, &quot;dpdk&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if not dpdk_prefix_list:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0remote_prefixes =3D self._l=
ist_remote_dirs(prefix)<br>
@@ -174,9 +168,7 @@ def _list_remote_dirs(self, remote_path: str | PurePath=
) -&gt; list[str] | None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Return a list of directories of the remot=
e_dir.<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0If remote_path doesn&#39;t exist, return =
None.<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 out =3D self.send_command(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;ls -l {remote_path} | awk=
 &#39;/^d/ {{print $NF}}&#39;&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 ).stdout<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 out =3D self.send_command(f&quot;ls -l {remote=
_path} | awk &#39;/^d/ {{print $NF}}&#39;&quot;).stdout<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if &quot;No such file or directory&quot; =
in out:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return None<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else:<br>
@@ -200,9 +192,7 @@ def _remote_files_exists(self, remote_path: PurePath) -=
&gt; bool:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0result =3D self.send_command(f&quot;test =
-e {remote_path}&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return not result.return_code<br>
<br>
-=C2=A0 =C2=A0 def _check_dpdk_hugepages(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, dpdk_runtime_dirs: Iterable[str | PurePa=
th]<br>
-=C2=A0 =C2=A0 ) -&gt; None:<br>
+=C2=A0 =C2=A0 def _check_dpdk_hugepages(self, dpdk_runtime_dirs: Iterable[=
str | PurePath]) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for dpdk_runtime_dir in dpdk_runtime_dirs=
:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0hugepage_info =3D PurePosix=
Path(dpdk_runtime_dir, &quot;hugepage_info&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if self._remote_files_exist=
s(hugepage_info):<br>
@@ -213,9 +203,7 @@ def _check_dpdk_hugepages(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0self._logger.warning(out)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0self._logger.warning(&quot;*******************************************&q=
uot;)<br>
<br>
-=C2=A0 =C2=A0 def _remove_dpdk_runtime_dirs(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, dpdk_runtime_dirs: Iterable[str | PurePa=
th]<br>
-=C2=A0 =C2=A0 ) -&gt; None:<br>
+=C2=A0 =C2=A0 def _remove_dpdk_runtime_dirs(self, dpdk_runtime_dirs: Itera=
ble[str | PurePath]) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for dpdk_runtime_dir in dpdk_runtime_dirs=
:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.remove_remote_dir(dpdk=
_runtime_dir)<br>
<br>
@@ -245,6 +233,4 @@ def get_node_info(self) -&gt; NodeInfo:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SETTINGS.timeout,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0).stdout.split(&quot;\n&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0kernel_version =3D self.send_command(&quo=
t;uname -r&quot;, SETTINGS.timeout).stdout<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return NodeInfo(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 os_release_info[0].strip(), os_r=
elease_info[1].strip(), kernel_version<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return NodeInfo(os_release_info[0].strip(), os=
_release_info[1].strip(), kernel_version)<br>
diff --git a/dts/framework/remote_session/remote/interactive_remote_session=
.py b/dts/framework/remote_session/remote/interactive_remote_session.py<br>
index 9085a668e8..42c99b2525 100644<br>
--- a/dts/framework/remote_session/remote/interactive_remote_session.py<br>
+++ b/dts/framework/remote_session/remote/interactive_remote_session.py<br>
@@ -73,9 +73,7 @@ def __init__(self, node_config: NodeConfiguration, _logge=
r: DTSLOG) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0f&quot;Initializing interac=
tive connection for {self.username}@{self.hostname}&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._connect()<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._<a href=3D"http://logger.info" rel=3D"no=
referrer" target=3D"_blank">logger.info</a>(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;Interactive connection su=
ccessful for {self.username}@{self.hostname}&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._<a href=3D"http://logger.info" rel=3D"no=
referrer" target=3D"_blank">logger.info</a>(f&quot;Interactive connection s=
uccessful for {self.username}@{self.hostname}&quot;)<br>
<br>
=C2=A0 =C2=A0 =C2=A0def _connect(self) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;Establish a connection =
to the node.<br>
@@ -108,8 +106,7 @@ def _connect(self) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.=
debug(traceback.format_exc())<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.=
warning(e)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._<a href=
=3D"http://logger.info" rel=3D"noreferrer" target=3D"_blank">logger.info</a=
>(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quo=
t;Retrying interactive session connection: &quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&qu=
ot;retry number {retry_attempt +1}&quot;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quo=
t;Retrying interactive session connection: &quot; f&quot;retry number {retr=
y_attempt +1}&quot;<br></blockquote><div><br></div><div><div style=3D"font-=
family:arial,sans-serif" class=3D"gmail_default">Here you can get rid of th=
e double string, but you would have to make sure to add the f to the start =
to make the whole thing and f-string.<br></div></div><div>=C2=A0</div><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:=
1px solid rgb(204,204,204);padding-left:1ex">
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0break<br>
diff --git a/dts/framework/remote_session/remote/interactive_shell.py b/dts=
/framework/remote_session/remote/interactive_shell.py<br>
index c24376b2a8..4db19fb9b3 100644<br>
--- a/dts/framework/remote_session/remote/interactive_shell.py<br>
+++ b/dts/framework/remote_session/remote/interactive_shell.py<br>
@@ -85,9 +85,7 @@ def __init__(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._app_args =3D app_args<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._start_application(get_privileged_co=
mmand)<br>
<br>
-=C2=A0 =C2=A0 def _start_application(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, get_privileged_command: Callable[[str], =
str] | None<br>
-=C2=A0 =C2=A0 ) -&gt; None:<br>
+=C2=A0 =C2=A0 def _start_application(self, get_privileged_command: Callabl=
e[[str], str] | None) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;Starts a new interactiv=
e application based on the path to the app.<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This method is often overridden by subcla=
sses as their process for<br>
diff --git a/dts/framework/remote_session/remote/remote_session.py b/dts/fr=
amework/remote_session/remote/remote_session.py<br>
index 0647d93de4..719f7d1ef7 100644<br>
--- a/dts/framework/remote_session/remote/remote_session.py<br>
+++ b/dts/framework/remote_session/remote/remote_session.py<br>
@@ -96,9 +96,7 @@ def send_command(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0If verify is True, check the return code =
of the executed command<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0and raise a RemoteCommandExecutionError i=
f the command failed.<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._<a href=3D"http://logger.info" rel=3D"no=
referrer" target=3D"_blank">logger.info</a>(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;Sending: &#39;{command}&#=
39;&quot; + (f&quot; with env vars: &#39;{env}&#39;&quot; if env else &quot=
;&quot;)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._<a href=3D"http://logger.info" rel=3D"no=
referrer" target=3D"_blank">logger.info</a>(f&quot;Sending: &#39;{command}&=
#39;&quot; + (f&quot; with env vars: &#39;{env}&#39;&quot; if env else &quo=
t;&quot;))<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0result =3D self._send_command(command, ti=
meout, env)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if verify and result.return_code:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.debug(<br>
@@ -112,9 +110,7 @@ def send_command(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return result<br>
<br>
=C2=A0 =C2=A0 =C2=A0@abstractmethod<br>
-=C2=A0 =C2=A0 def _send_command(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, command: str, timeout: float, env: dict =
| None<br>
-=C2=A0 =C2=A0 ) -&gt; CommandResult:<br>
+=C2=A0 =C2=A0 def _send_command(self, command: str, timeout: float, env: d=
ict | None) -&gt; CommandResult:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Use the underlying protocol to execute th=
e command using optional env vars<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0and return CommandResult.<br>
diff --git a/dts/framework/remote_session/remote/ssh_session.py b/dts/frame=
work/remote_session/remote/ssh_session.py<br>
index 8d127f1601..1a7ee649ab 100644<br>
--- a/dts/framework/remote_session/remote/ssh_session.py<br>
+++ b/dts/framework/remote_session/remote/ssh_session.py<br>
@@ -80,9 +80,7 @@ def _connect(self) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if error not =
in errors:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0errors.append(error)<br>
<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._<a href=3D"h=
ttp://logger.info" rel=3D"noreferrer" target=3D"_blank">logger.info</a>(<br=
>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&qu=
ot;Retrying connection: retry number {retry_attempt + 1}.&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._<a href=3D"h=
ttp://logger.info" rel=3D"noreferrer" target=3D"_blank">logger.info</a>(f&q=
uot;Retrying connection: retry number {retry_attempt + 1}.&quot;)<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0break<br>
@@ -92,9 +90,7 @@ def _connect(self) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0def is_alive(self) -&gt; bool:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return self.session.is_connected<br>
<br>
-=C2=A0 =C2=A0 def _send_command(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, command: str, timeout: float, env: dict =
| None<br>
-=C2=A0 =C2=A0 ) -&gt; CommandResult:<br>
+=C2=A0 =C2=A0 def _send_command(self, command: str, timeout: float, env: d=
ict | None) -&gt; CommandResult:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;Send a command and retu=
rn the result of the execution.<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Args:<br>
@@ -107,9 +103,7 @@ def _send_command(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SSHTimeoutError: The comman=
d execution timed out.<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0try:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 output =3D self.session.run(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 command, env=3Denv=
, warn=3DTrue, hide=3DTrue, timeout=3Dtimeout<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 output =3D self.session.run(comm=
and, env=3Denv, warn=3DTrue, hide=3DTrue, timeout=3Dtimeout)<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0except (UnexpectedExit, ThreadException) =
as e:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.exception(e)<b=
r>
@@ -119,9 +113,7 @@ def _send_command(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.exception(e)<b=
r>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0raise SSHTimeoutError(comma=
nd, e.result.stderr) from e<br>
<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return CommandResult(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 <a href=3D"http://self.name" rel=
=3D"noreferrer" target=3D"_blank">self.name</a>, command, output.stdout, ou=
tput.stderr, output.return_code<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return CommandResult(<a href=3D"http://self.na=
me" rel=3D"noreferrer" target=3D"_blank">self.name</a>, command, output.std=
out, output.stderr, output.return_code)<br>
<br>
=C2=A0 =C2=A0 =C2=A0def copy_from(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self,<br>
diff --git a/dts/framework/remote_session/remote/testpmd_shell.py b/dts/fra=
mework/remote_session/remote/testpmd_shell.py<br>
index 1455b5a199..08ac311016 100644<br>
--- a/dts/framework/remote_session/remote/testpmd_shell.py<br>
+++ b/dts/framework/remote_session/remote/testpmd_shell.py<br>
@@ -21,13 +21,9 @@ class TestPmdShell(InteractiveShell):<br>
=C2=A0 =C2=A0 =C2=A0path: PurePath =3D PurePath(&quot;app&quot;, &quot;dpdk=
-testpmd&quot;)<br>
=C2=A0 =C2=A0 =C2=A0dpdk_app: bool =3D True<br>
=C2=A0 =C2=A0 =C2=A0_default_prompt: str =3D &quot;testpmd&gt;&quot;<br>
-=C2=A0 =C2=A0 _command_extra_chars: str =3D (<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot;\n&quot;=C2=A0 # We want to append an ex=
tra newline to every command<br>
-=C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 _command_extra_chars: str =3D &quot;\n&quot;=C2=A0 # We want=
 to append an extra newline to every command<br>
<br>
-=C2=A0 =C2=A0 def _start_application(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, get_privileged_command: Callable[[str], =
str] | None<br>
-=C2=A0 =C2=A0 ) -&gt; None:<br>
+=C2=A0 =C2=A0 def _start_application(self, get_privileged_command: Callabl=
e[[str], str] | None) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;See &quot;_start_applic=
ation&quot; in InteractiveShell.&quot;&quot;&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._app_args +=3D &quot; -- -i&quot;<br=
>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0super()._start_application(get_privileged=
_command)<br>
diff --git a/dts/framework/settings.py b/dts/framework/settings.py<br>
index cfa39d011b..aad444e99c 100644<br>
--- a/dts/framework/settings.py<br>
+++ b/dts/framework/settings.py<br>
@@ -170,9 +170,7 @@ def _get_settings() -&gt; _Settings:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0timeout=3Dparsed_args.timeout,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0verbose=3D(parsed_args.verbose =3D=3D &qu=
ot;Y&quot;),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0skip_setup=3D(parsed_args.skip_setup =3D=
=3D &quot;Y&quot;),<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 dpdk_tarball_path=3DPath(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DPDKGitTarball(parsed_args.tarba=
ll, parsed_args.output_dir)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 dpdk_tarball_path=3DPath(DPDKGitTarball(parsed=
_args.tarball, parsed_args.output_dir))<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if not os.path.exists(parsed_args.tarball=
)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else Path(parsed_args.tarball),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0compile_timeout=3Dparsed_args.compile_tim=
eout,<br>
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py<br=
>
index f0fbe80f6f..4c2e7e2418 100644<br>
--- a/dts/framework/test_result.py<br>
+++ b/dts/framework/test_result.py<br>
@@ -83,9 +83,7 @@ def __iadd__(self, other: Result) -&gt; &quot;Statistics&=
quot;:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self[<a href=3D"http://other.name" rel=3D=
"noreferrer" target=3D"_blank">other.name</a>] +=3D 1<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self[&quot;PASS RATE&quot;] =3D (<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 float(self[<a href=3D"http://Res=
ult.PASS.name" rel=3D"noreferrer" target=3D"_blank">Result.PASS.name</a>])<=
br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 * 100<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 / sum(self[<a href=3D"http://res=
ult.name" rel=3D"noreferrer" target=3D"_blank">result.name</a>] for result =
in Result)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 float(self[<a href=3D"http://Res=
ult.PASS.name" rel=3D"noreferrer" target=3D"_blank">Result.PASS.name</a>]) =
* 100 / sum(self[<a href=3D"http://result.name" rel=3D"noreferrer" target=
=3D"_blank">result.name</a>] for result in Result)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return self<br>
<br>
@@ -135,9 +133,7 @@ def _get_setup_teardown_errors(self) -&gt; list[Excepti=
on]:<br>
<br>
=C2=A0 =C2=A0 =C2=A0def _get_inner_errors(self) -&gt; list[Exception]:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return [<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 error<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 for inner_result in self._inner_=
results<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 for error in inner_result.get_er=
rors()<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 error for inner_result in self._=
inner_results for error in inner_result.get_errors()<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0]<br>
<br>
=C2=A0 =C2=A0 =C2=A0def get_errors(self) -&gt; list[Exception]:<br>
@@ -174,9 +170,7 @@ def add_stats(self, statistics: Statistics) -&gt; None:=
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0statistics +=3D self.result<br>
<br>
=C2=A0 =C2=A0 =C2=A0def __bool__(self) -&gt; bool:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return (<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 bool(self.setup_result) and bool=
(self.teardown_result) and bool(self.result)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return bool(self.setup_result) and bool(self.t=
eardown_result) and bool(self.result)<br>
<br>
<br>
=C2=A0class TestSuiteResult(BaseResult):<br>
@@ -247,9 +241,7 @@ def __init__(self, sut_node: NodeConfiguration):<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0super(ExecutionResult, self).__init__()<b=
r>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.sut_node =3D sut_node<br>
<br>
-=C2=A0 =C2=A0 def add_build_target(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, build_target: BuildTargetConfiguration<b=
r>
-=C2=A0 =C2=A0 ) -&gt; BuildTargetResult:<br>
+=C2=A0 =C2=A0 def add_build_target(self, build_target: BuildTargetConfigur=
ation) -&gt; BuildTargetResult:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0build_target_result =3D BuildTargetResult=
(build_target)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._inner_results.append(build_target_r=
esult)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return build_target_result<br>
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py<br>
index 3b890c0451..46d3de4944 100644<br>
--- a/dts/framework/test_suite.py<br>
+++ b/dts/framework/test_suite.py<br>
@@ -102,9 +102,7 @@ def _process_links(self) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0tg_port.peer,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0tg_port.identifier,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0):<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self=
._port_links.append(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 PortLink(sut_port=3Dsut_port, tg_port=3Dtg_port)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br=
>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self=
._port_links.append(PortLink(sut_port=3Dsut_port, tg_port=3Dtg_port))<br>
<br>
=C2=A0 =C2=A0 =C2=A0def set_up_suite(self) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
@@ -151,9 +149,7 @@ def configure_testbed_ipv4(self, restore: bool =3D Fals=
e) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0def _configure_ipv4_forwarding(self, enable: bool) -&gt=
; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.sut_node.configure_ipv4_forwarding(e=
nable)<br>
<br>
-=C2=A0 =C2=A0 def send_packet_and_capture(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, packet: Packet, duration: float =3D 1<br=
>
-=C2=A0 =C2=A0 ) -&gt; list[Packet]:<br>
+=C2=A0 =C2=A0 def send_packet_and_capture(self, packet: Packet, duration: =
float =3D 1) -&gt; list[Packet]:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Send a packet through the appropriate int=
erface and<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0receive on the appropriate interface.<br>
@@ -202,21 +198,15 @@ def verify(self, condition: bool, failure_description=
: str) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._fail_test_case_verify=
(failure_description)<br>
<br>
=C2=A0 =C2=A0 =C2=A0def _fail_test_case_verify(self, failure_description: s=
tr) -&gt; None:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.debug(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot;A test case failed, showin=
g the last 10 commands executed on SUT:&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.debug(&quot;A test case failed, s=
howing the last 10 commands executed on SUT:&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for command_res in self.sut_node.main_ses=
sion.remote_session.history[-10:]:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.debug(command_=
res.command)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.debug(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot;A test case failed, showin=
g the last 10 commands executed on TG:&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.debug(&quot;A test case failed, s=
howing the last 10 commands executed on TG:&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for command_res in self.tg_node.main_sess=
ion.remote_session.history[-10:]:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.debug(command_=
res.command)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0raise TestCaseVerifyError(failure_descrip=
tion)<br>
<br>
-=C2=A0 =C2=A0 def verify_packets(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, expected_packet: Packet, received_packet=
s: list[Packet]<br>
-=C2=A0 =C2=A0 ) -&gt; None:<br>
+=C2=A0 =C2=A0 def verify_packets(self, expected_packet: Packet, received_p=
ackets: list[Packet]) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for received_packet in received_packets:<=
br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if self._compare_packets(ex=
pected_packet, received_packet):<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0break<br>
@@ -225,17 +215,11 @@ def verify_packets(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0f&quot;The ex=
pected packet {get_packet_summaries(expected_packet)} &quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0f&quot;not fo=
und among received {get_packet_summaries(received_packets)}&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._fail_test_case_verify(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot;An expected =
packet not found among received packets.&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._fail_test_case_verify(&quo=
t;An expected packet not found among received packets.&quot;)<br>
<br>
-=C2=A0 =C2=A0 def _compare_packets(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, expected_packet: Packet, received_packet=
: Packet<br>
-=C2=A0 =C2=A0 ) -&gt; bool:<br>
+=C2=A0 =C2=A0 def _compare_packets(self, expected_packet: Packet, received=
_packet: Packet) -&gt; bool:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.debug(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot;Comparing packets: \n&quot=
;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;{expected_packet.summary(=
)}\n&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;{received_packet.summary(=
)}&quot;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot;Comparing packets: \n&quot=
; f&quot;{expected_packet.summary()}\n&quot; f&quot;{received_packet.summar=
y()}&quot;<br></blockquote><div><br></div><div><div style=3D"font-family:ar=
ial,sans-serif" class=3D"gmail_default">Same situation as above where you w=
ould want to make sure to put the f at the start.<br></div></div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left:1px solid rgb(204,204,204);padding-left:1ex">
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0l3 =3D IP in expected_packet.layers()<br>
@@ -262,14 +246,10 @@ def _compare_packets(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0expected_payload =3D expect=
ed_payload.payload<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if expected_payload:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.debug(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;The expecte=
d packet did not contain {expected_payload}.&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.debug(f&quot;The ex=
pected packet did not contain {expected_payload}.&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return False<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if received_payload and received_payload.=
__class__ !=3D Padding:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.debug(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot;The received=
 payload had extra layers which were not padding.&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.debug(&quot;The rec=
eived payload had extra layers which were not padding.&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return False<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return True<br>
<br>
@@ -296,10 +276,7 @@ def _verify_l2_frame(self, received_packet: Ether, l3:=
 bool) -&gt; bool:<br>
<br>
=C2=A0 =C2=A0 =C2=A0def _verify_l3_packet(self, received_packet: IP, expect=
ed_packet: IP) -&gt; bool:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.debug(&quot;Looking at the I=
P layer.&quot;)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 received_packet.src !=3D expecte=
d_packet.src<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 or received_packet.dst !=3D expe=
cted_packet.dst<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 ):<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if received_packet.src !=3D expected_packet.sr=
c or received_packet.dst !=3D expected_packet.dst:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return False<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return True<br>
<br>
@@ -373,9 +350,7 @@ def _get_test_cases(self, test_case_regex: str) -&gt; l=
ist[MethodType]:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if self._should_be_executed=
(test_case_name, test_case_regex):<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0filtered_test=
_cases.append(test_case)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0cases_str =3D &quot;, &quot;.join((x.__na=
me__ for x in filtered_test_cases))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.debug(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;Found test cases &#39;{ca=
ses_str}&#39; in {self.__class__.__name__}.&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.debug(f&quot;Found test cases &#3=
9;{cases_str}&#39; in {self.__class__.__name__}.&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return filtered_test_cases<br>
<br>
=C2=A0 =C2=A0 =C2=A0def _should_be_executed(self, test_case_name: str, test=
_case_regex: str) -&gt; bool:<br>
@@ -445,9 +420,7 @@ def _execute_test_case(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.exception(f&qu=
ot;Test case execution ERROR: {test_case_name}&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0test_case_result.update(Res=
ult.ERROR, e)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0except KeyboardInterrupt:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.error(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;Test case e=
xecution INTERRUPTED by user: {test_case_name}&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.error(f&quot;Test c=
ase execution INTERRUPTED by user: {test_case_name}&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0test_case_result.update(Res=
ult.SKIP)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0raise KeyboardInterrupt(&qu=
ot;Stop DTS&quot;)<br>
<br>
@@ -464,9 +437,7 @@ def is_test_suite(object) -&gt; bool:<br>
=C2=A0 =C2=A0 =C2=A0try:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0testcase_module =3D importlib.import_modu=
le(testsuite_module_path)<br>
=C2=A0 =C2=A0 =C2=A0except ModuleNotFoundError as e:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 raise ConfigurationError(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;Test suite &#39;{testsuit=
e_module_path}&#39; not found.&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 ) from e<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 raise ConfigurationError(f&quot;Test suite &#3=
9;{testsuite_module_path}&#39; not found.&quot;) from e<br>
=C2=A0 =C2=A0 =C2=A0return [<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0test_suite_class<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for _, test_suite_class in inspect.getmem=
bers(testcase_module, is_test_suite)<br>
diff --git a/dts/framework/testbed_model/capturing_traffic_generator.py b/d=
ts/framework/testbed_model/capturing_traffic_generator.py<br>
index ab98987f8e..48d019ab21 100644<br>
--- a/dts/framework/testbed_model/capturing_traffic_generator.py<br>
+++ b/dts/framework/testbed_model/capturing_traffic_generator.py<br>
@@ -110,9 +110,7 @@ def send_packets_and_capture(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0duration,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.debug(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;Received packets: {get_pa=
cket_summaries(received_packets)}&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger.debug(f&quot;Received packets: {g=
et_packet_summaries(received_packets)}&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._write_capture_from_packets(capture_=
name, received_packets)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return received_packets<br>
<br>
diff --git a/dts/framework/testbed_model/hw/cpu.py b/dts/framework/testbed_=
model/hw/cpu.py<br>
index d1918a12dc..cbc5fe7fff 100644<br>
--- a/dts/framework/testbed_model/hw/cpu.py<br>
+++ b/dts/framework/testbed_model/hw/cpu.py<br>
@@ -54,9 +54,7 @@ def __init__(self, lcore_list: list[int] | list[str] | li=
st[LogicalCore] | str):<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# the input lcores may not be sorted<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._lcore_list.sort()<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._lcore_str =3D (<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&#39;{&quot;,&quot;.join(self._=
get_consecutive_lcores_range(self._lcore_list))}&#39;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._lcore_str =3D f&#39;{&quot;,&quot;.join(=
self._get_consecutive_lcores_range(self._lcore_list))}&#39;<br>
<br>
=C2=A0 =C2=A0 =C2=A0@property<br>
=C2=A0 =C2=A0 =C2=A0def lcore_list(self) -&gt; list[int]:<br>
@@ -70,15 +68,11 @@ def _get_consecutive_lcores_range(self, lcore_ids_list:=
 list[int]) -&gt; list[str]:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0segment.appen=
d(lcore_id)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0formatted_cor=
e_list.append(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&qu=
ot;{segment[0]}-{segment[-1]}&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if l=
en(segment) &gt; 1<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 else=
 f&quot;{segment[0]}&quot;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&qu=
ot;{segment[0]}-{segment[-1]}&quot; if len(segment) &gt; 1 else f&quot;{seg=
ment[0]}&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0current_core_=
index =3D lcore_ids_list.index(lcore_id)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0formatted_cor=
e_list.extend(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self=
._get_consecutive_lcores_range(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 lcore_ids_list[current_core_index:]<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br=
>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self=
._get_consecutive_lcores_range(lcore_ids_list[current_core_index:])<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0segment.clear=
()<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0break<br>
@@ -125,9 +119,7 @@ def __init__(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._filter_specifier =3D filter_specifi=
er<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# sorting by core is needed in case hyper=
threading is enabled<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._lcores_to_filter =3D sorted(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 lcore_list, key=3Dlambda x: x.co=
re, reverse=3Dnot ascending<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._lcores_to_filter =3D sorted(lcore_list, =
key=3Dlambda x: x.core, reverse=3Dnot ascending)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.filter()<br>
<br>
=C2=A0 =C2=A0 =C2=A0@abstractmethod<br>
@@ -220,9 +212,7 @@ def _filter_cores_from_socket(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0# we have enough lcores per this core<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0continue<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 elif self._filter_specifier.core=
s_per_socket &gt; len(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 lcore_count_per_co=
re_map<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ):<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 elif self._filter_specifier.core=
s_per_socket &gt; len(lcore_count_per_core_map):<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# only add co=
res if we need more<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0lcore_count_p=
er_core_map[lcore.core] =3D 1<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0filtered_lcor=
es.append(lcore)<br>
diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_mo=
del/node.py<br>
index fc01e0bf8e..ef700d8114 100644<br>
--- a/dts/framework/testbed_model/node.py<br>
+++ b/dts/framework/testbed_model/node.py<br>
@@ -103,18 +103,14 @@ def _tear_down_execution(self) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0is not decorated so that the derived clas=
s doesn&#39;t have to use the decorator.<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
<br>
-=C2=A0 =C2=A0 def set_up_build_target(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, build_target_config: BuildTargetConfigur=
ation<br>
-=C2=A0 =C2=A0 ) -&gt; None:<br>
+=C2=A0 =C2=A0 def set_up_build_target(self, build_target_config: BuildTarg=
etConfiguration) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Perform the build target setup that will =
be done for each build target<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0tested on this node.<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._set_up_build_target(build_target_co=
nfig)<br>
<br>
-=C2=A0 =C2=A0 def _set_up_build_target(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, build_target_config: BuildTargetConfigur=
ation<br>
-=C2=A0 =C2=A0 ) -&gt; None:<br>
+=C2=A0 =C2=A0 def _set_up_build_target(self, build_target_config: BuildTar=
getConfiguration) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This method exists to be optionally overw=
ritten by derived classes and<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0is not decorated so that the derived clas=
s doesn&#39;t have to use the decorator.<br>
diff --git a/dts/framework/testbed_model/scapy.py b/dts/framework/testbed_m=
odel/scapy.py<br>
index af0d4dbb25..7948424951 100644<br>
--- a/dts/framework/testbed_model/scapy.py<br>
+++ b/dts/framework/testbed_model/scapy.py<br>
@@ -96,9 +96,7 @@ def scapy_send_packets_and_capture(<br>
=C2=A0 =C2=A0 =C2=A0return [scapy_packet.build() for scapy_packet in sniffe=
r.stop(join=3DTrue)]<br>
<br>
<br>
-def scapy_send_packets(<br>
-=C2=A0 =C2=A0 xmlrpc_packets: list[xmlrpc.client.Binary], send_iface: str<=
br>
-) -&gt; None:<br>
+def scapy_send_packets(xmlrpc_packets: list[xmlrpc.client.Binary], send_if=
ace: str) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;RPC function to send packets.<br>
<br>
=C2=A0 =C2=A0 =C2=A0The function is meant to be executed on the remote TG n=
ode.<br>
@@ -197,9 +195,7 @@ class ScapyTrafficGenerator(CapturingTrafficGenerator):=
<br>
=C2=A0 =C2=A0 =C2=A0def __init__(self, tg_node: TGNode, config: ScapyTraffi=
cGeneratorConfig):<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._config =3D config<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._tg_node =3D tg_node<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger =3D getLogger(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;{self._<a href=3D"http://=
tg_node.name" rel=3D"noreferrer" target=3D"_blank">tg_node.name</a>} {self.=
_config.traffic_generator_type}&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._logger =3D getLogger(f&quot;{self._<a hr=
ef=3D"http://tg_node.name" rel=3D"noreferrer" target=3D"_blank">tg_node.nam=
e</a>} {self._config.traffic_generator_type}&quot;)<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0assert (<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._tg_node.config.os =3D=
=3D OS.linux<br>
@@ -218,9 +214,7 @@ def __init__(self, tg_node: TGNode, config: ScapyTraffi=
cGeneratorConfig):<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._start_xmlrpc_server_in_remote_pytho=
n(xmlrpc_server_listen_port)<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# connect to the server<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 server_url =3D (<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;http://{self._tg_node.con=
fig.hostname}:{xmlrpc_server_listen_port}&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 server_url =3D f&quot;http://{self._tg_node.co=
nfig.hostname}:{xmlrpc_server_listen_port}&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.rpc_server_proxy =3D xmlrpc.client.S=
erverProxy(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0server_url, allow_none=3DTr=
ue, verbose=3DSETTINGS.verbose<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
@@ -240,9 +234,7 @@ def _start_xmlrpc_server_in_remote_python(self, listen_=
port: int):<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0src =3D inspect.getsource(QuittableXMLRPC=
Server)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# Lines with only whitespace break the re=
pl if in the middle of a function<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# or class, so strip all lines containing=
 only whitespace<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 src =3D &quot;\n&quot;.join(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [line for line in src.splitlines=
() if not line.isspace() and line !=3D &quot;&quot;]<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 src =3D &quot;\n&quot;.join([line for line in =
src.splitlines() if not line.isspace() and line !=3D &quot;&quot;])<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0spacing =3D &quot;\n&quot; * 4<br>
<br>
diff --git a/dts/framework/testbed_model/sut_node.py b/dts/framework/testbe=
d_model/sut_node.py<br>
index 202aebfd06..dfd8c755b4 100644<br>
--- a/dts/framework/testbed_model/sut_node.py<br>
+++ b/dts/framework/testbed_model/sut_node.py<br>
@@ -129,9 +129,7 @@ def remote_dpdk_build_dir(self) -&gt; PurePath:<br>
=C2=A0 =C2=A0 =C2=A0@property<br>
=C2=A0 =C2=A0 =C2=A0def dpdk_version(self) -&gt; str:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if self._dpdk_version is None:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._dpdk_version =3D self.main=
_session.get_dpdk_version(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._remote_dpdk_=
dir<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self._dpdk_version =3D self.main=
_session.get_dpdk_version(self._remote_dpdk_dir)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return self._dpdk_version<br>
<br>
=C2=A0 =C2=A0 =C2=A0@property<br>
@@ -149,8 +147,7 @@ def compiler_version(self) -&gt; str:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._logger.=
warning(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quo=
t;Failed to get compiler version because&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quo=
t;_build_target_config is None.&quot;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quo=
t;Failed to get compiler version because&quot; &quot;_build_target_config i=
s None.&quot;<br></blockquote><div><br></div><div><div style=3D"font-family=
:arial,sans-serif" class=3D"gmail_default">Double string here.<br></div></d=
iv><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0=
px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return &quot;=
&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return self._compiler_version<br>
@@ -163,9 +160,7 @@ def get_build_target_info(self) -&gt; BuildTargetInfo:<=
br>
=C2=A0 =C2=A0 =C2=A0def _guess_dpdk_remote_dir(self) -&gt; PurePath:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return self.main_session.guess_dpdk_remot=
e_dir(self._remote_tmp_dir)<br>
<br>
-=C2=A0 =C2=A0 def _set_up_build_target(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, build_target_config: BuildTargetConfigur=
ation<br>
-=C2=A0 =C2=A0 ) -&gt; None:<br>
+=C2=A0 =C2=A0 def _set_up_build_target(self, build_target_config: BuildTar=
getConfiguration) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Setup DPDK on the SUT node.<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
@@ -177,22 +172,17 @@ def _set_up_build_target(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._copy_dpdk_tarball()<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._build_dpdk()<br>
<br>
-=C2=A0 =C2=A0 def _configure_build_target(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self, build_target_config: BuildTargetConfigur=
ation<br>
-=C2=A0 =C2=A0 ) -&gt; None:<br>
+=C2=A0 =C2=A0 def _configure_build_target(self, build_target_config: Build=
TargetConfiguration) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Populate common environment variables and=
 set build target config.<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._env_vars =3D {}<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._build_target_config =3D build_targe=
t_config<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._env_vars.update(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self.main_session.get_dpdk_build=
_env_vars(build_target_config.arch)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._env_vars.update(self.main_session.get_dp=
dk_build_env_vars(build_target_config.arch))<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._env_vars[&quot;CC&quot;] =3D <a hre=
f=3D"http://build_target_config.compiler.name" rel=3D"noreferrer" target=3D=
"_blank">build_target_config.compiler.name</a><br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if build_target_config.compiler_wrapper:<=
br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._env_vars[&quot;CC&quo=
t;] =3D (<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;&#39;{build=
_target_config.compiler_wrapper} &quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;{<a href=3D=
"http://build_target_config.compiler.name" rel=3D"noreferrer" target=3D"_bl=
ank">build_target_config.compiler.name</a>}&#39;&quot;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;&#39;{build=
_target_config.compiler_wrapper} &quot; f&quot;{<a href=3D"http://build_tar=
get_config.compiler.name" rel=3D"noreferrer" target=3D"_blank">build_target=
_config.compiler.name</a>}&#39;&quot;<br></blockquote><div><br></div><div><=
div style=3D"font-family:arial,sans-serif" class=3D"gmail_default">Double s=
tring here.<br></div></div><div>=C2=A0</div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204)=
;padding-left:1ex">
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
<br>
=C2=A0 =C2=A0 =C2=A0@Node.skip_setup<br>
@@ -224,9 +214,7 @@ def _copy_dpdk_tarball(self) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.main_session.remove_remote_dir(self.=
_remote_dpdk_dir)<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# then extract to remote path<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self.main_session.extract_remote_tarball(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 remote_tarball_path, self._remot=
e_dpdk_dir<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self.main_session.extract_remote_tarball(remot=
e_tarball_path, self._remote_dpdk_dir)<br>
<br>
=C2=A0 =C2=A0 =C2=A0@Node.skip_setup<br>
=C2=A0 =C2=A0 =C2=A0def _build_dpdk(self) -&gt; None:<br>
@@ -263,9 +251,7 @@ def build_dpdk_app(self, app_name: str, **meson_dpdk_ar=
gs: str | bool) -&gt; PurePa<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if app_name =3D=3D &quot;all&quot;:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return self.main_session.join_re=
mote_path(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self.remote_dpdk_b=
uild_dir, &quot;examples&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return self.main_session.join_re=
mote_path(self.remote_dpdk_build_dir, &quot;examples&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return self.main_session.join_remote_path=
(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.remote_dpdk_build_dir,=
 &quot;examples&quot;, f&quot;dpdk-{app_name}&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
@@ -319,9 +305,7 @@ def create_eal_parameters(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&#39;-c 0xf -=
a 0000:88:00.0 --file-prefix=3Ddpdk_1112_20190809143420&#39;;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 lcore_list =3D LogicalCoreList(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self.filter_lcores(lcore_filter_=
specifier, ascending_cores)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 lcore_list =3D LogicalCoreList(self.filter_lco=
res(lcore_filter_specifier, ascending_cores))<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if append_prefix_timestamp:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0prefix =3D f&quot;{prefix}_=
{self._dpdk_timestamp}&quot;<br>
@@ -386,6 +370,4 @@ def create_interactive_shell(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.remote_d=
pdk_build_dir, shell_cls.path<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return super().create_interactive_shell(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 shell_cls, timeout, privileged, =
str(eal_parameters)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return super().create_interactive_shell(shell_=
cls, timeout, privileged, str(eal_parameters))<br>
diff --git a/dts/framework/testbed_model/tg_node.py b/dts/framework/testbed=
_model/tg_node.py<br>
index 27025cfa31..dca4ec0849 100644<br>
--- a/dts/framework/testbed_model/tg_node.py<br>
+++ b/dts/framework/testbed_model/tg_node.py<br>
@@ -45,9 +45,7 @@ class TGNode(Node):<br>
<br>
=C2=A0 =C2=A0 =C2=A0def __init__(self, node_config: TGNodeConfiguration):<b=
r>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0super(TGNode, self).__init__(node_config)=
<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self.traffic_generator =3D create_traffic_gene=
rator(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 self, node_config.traffic_genera=
tor<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self.traffic_generator =3D create_traffic_gene=
rator(self, node_config.traffic_generator)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._<a href=3D"http://logger.info" rel=
=3D"noreferrer" target=3D"_blank">logger.info</a>(f&quot;Created node: {<a =
href=3D"http://self.name" rel=3D"noreferrer" target=3D"_blank">self.name</a=
>}&quot;)<br>
<br>
=C2=A0 =C2=A0 =C2=A0def send_packet_and_capture(<br>
@@ -94,6 +92,5 @@ def create_traffic_generator(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return ScapyTrafficGenerato=
r(tg_node, traffic_generator_config)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0case _:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0raise ConfigurationError(<b=
r>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot;Unknown traf=
fic generator: &quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;{traffic_ge=
nerator_config.traffic_generator_type}&quot;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot;Unknown traf=
fic generator: &quot; f&quot;{traffic_generator_config.traffic_generator_ty=
pe}&quot;<br></blockquote><div><br></div><div><div style=3D"font-family:ari=
al,sans-serif" class=3D"gmail_default">Double string but one that needs the=
 whole thing to be an f-string.<br></div></div><div>=C2=A0</div><blockquote=
 class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px so=
lid rgb(204,204,204);padding-left:1ex">
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
diff --git a/dts/framework/utils.py b/dts/framework/utils.py<br>
index d27c2c5b5f..d098d364ff 100644<br>
--- a/dts/framework/utils.py<br>
+++ b/dts/framework/utils.py<br>
@@ -19,9 +19,7 @@<br>
<br>
=C2=A0class StrEnum(Enum):<br>
=C2=A0 =C2=A0 =C2=A0@staticmethod<br>
-=C2=A0 =C2=A0 def _generate_next_value_(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 name: str, start: int, count: int, last_values=
: object<br>
-=C2=A0 =C2=A0 ) -&gt; str:<br>
+=C2=A0 =C2=A0 def _generate_next_value_(name: str, start: int, count: int,=
 last_values: object) -&gt; str:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return name<br>
<br>
=C2=A0 =C2=A0 =C2=A0def __str__(self) -&gt; str:<br>
@@ -32,9 +30,7 @@ def __str__(self) -&gt; str:<br>
<br>
<br>
=C2=A0def check_dts_python_version() -&gt; None:<br>
-=C2=A0 =C2=A0 if sys.version_info.major &lt; 3 or (<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 sys.version_info.major =3D=3D 3 and sys.versio=
n_info.minor &lt; 10<br>
-=C2=A0 =C2=A0 ):<br>
+=C2=A0 =C2=A0 if sys.version_info.major &lt; 3 or (sys.version_info.major =
=3D=3D 3 and sys.version_info.minor &lt; 10):<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0print(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0RED(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(<br>
@@ -60,9 +56,7 @@ def expand_range(range_str: str) -&gt; list[int]:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0range_boundaries =3D range_str.split(&quo=
t;-&quot;)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# will throw an exception when items in r=
ange_boundaries can&#39;t be converted,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# serving as type check<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 expanded_range.extend(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 range(int(range_boundaries[0]), =
int(range_boundaries[-1]) + 1)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 expanded_range.extend(range(int(range_boundari=
es[0]), int(range_boundaries[-1]) + 1))<br>
<br>
=C2=A0 =C2=A0 =C2=A0return expanded_range<br>
<br>
@@ -71,9 +65,7 @@ def get_packet_summaries(packets: list[Packet]):<br>
=C2=A0 =C2=A0 =C2=A0if len(packets) =3D=3D 1:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0packet_summaries =3D packets[0].summary()=
<br>
=C2=A0 =C2=A0 =C2=A0else:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 packet_summaries =3D json.dumps(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 list(map(lambda pkt: pkt.summary=
(), packets)), indent=3D4<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 packet_summaries =3D json.dumps(list(map(lambd=
a pkt: pkt.summary(), packets)), indent=3D4)<br>
=C2=A0 =C2=A0 =C2=A0return f&quot;Packet contents: \n{packet_summaries}&quo=
t;<br>
<br>
<br>
@@ -94,9 +86,7 @@ class MesonArgs(object):<br>
=C2=A0 =C2=A0 =C2=A0_default_library: str<br>
<br>
=C2=A0 =C2=A0 =C2=A0def __init__(self, default_library: str | None =3D None=
, **dpdk_args: str | bool):<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._default_library =3D (<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;--default-library=3D{defa=
ult_library}&quot; if default_library else &quot;&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 self._default_library =3D f&quot;--default-lib=
rary=3D{default_library}&quot; if default_library else &quot;&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._dpdk_args =3D &quot; &quot;.join(<b=
r>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0f&quot;-D{dpd=
k_arg_name}=3D{dpdk_arg_value}&quot;<br>
diff --git a/dts/pyproject.toml b/dts/pyproject.toml<br>
index 6762edfa6b..980ac3c7db 100644<br>
--- a/dts/pyproject.toml<br>
+++ b/dts/pyproject.toml<br>
@@ -41,7 +41,7 @@ build-backend =3D &quot;poetry.core.masonry.api&quot;<br>
=C2=A0[tool.pylama]<br>
=C2=A0linters =3D &quot;mccabe,pycodestyle,pyflakes&quot;<br>
=C2=A0format =3D &quot;pylint&quot;<br>
-max_line_length =3D 88 # <a href=3D"https://black.readthedocs.io/en/stable=
/the_black_code_style/current_style.html#line-length" rel=3D"noreferrer" ta=
rget=3D"_blank">https://black.readthedocs.io/en/stable/the_black_code_style=
/current_style.html#line-length</a><br>
+max_line_length =3D 100<br>
<br>
=C2=A0[tool.mypy]<br>
=C2=A0python_version =3D &quot;3.10&quot;<br>
@@ -55,4 +55,4 @@ profile =3D &quot;black&quot;<br>
=C2=A0[tool.black]<br>
=C2=A0target-version =3D [&#39;py310&#39;]<br>
=C2=A0include =3D &#39;\.pyi?$&#39;<br>
-line-length =3D 88 # <a href=3D"https://black.readthedocs.io/en/stable/the=
_black_code_style/current_style.html#line-length+line-length" rel=3D"norefe=
rrer" target=3D"_blank">https://black.readthedocs.io/en/stable/the_black_co=
de_style/current_style.html#line-length<br>
+line-length</a> =3D 100<br>
diff --git a/dts/tests/TestSuite_hello_world.py b/dts/tests/TestSuite_hello=
_world.py<br>
index 7e3d95c0cf..768ba1cfa8 100644<br>
--- a/dts/tests/TestSuite_hello_world.py<br>
+++ b/dts/tests/TestSuite_hello_world.py<br>
@@ -34,9 +34,7 @@ def test_hello_world_single_core(self) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# get the first usable core<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0lcore_amount =3D LogicalCoreCount(1, 1, 1=
)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0lcores =3D LogicalCoreCountFilter(self.su=
t_node.lcores, lcore_amount).filter()<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 eal_para =3D self.sut_node.create_eal_paramete=
rs(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 lcore_filter_specifier=3Dlcore_a=
mount<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 eal_para =3D self.sut_node.create_eal_paramete=
rs(lcore_filter_specifier=3Dlcore_amount)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0result =3D self.sut_node.run_dpdk_app(sel=
f.app_helloworld_path, eal_para)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.verify(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0f&quot;hello from core {int=
(lcores[0])}&quot; in result.stdout,<br>
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke=
_tests.py<br>
index 4a269df75b..36119e6469 100644<br>
--- a/dts/tests/TestSuite_smoke_tests.py<br>
+++ b/dts/tests/TestSuite_smoke_tests.py<br>
@@ -45,13 +45,10 @@ def test_driver_tests(self) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for dev in self.sut_node.virtual_devices:=
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0vdev_args +=3D f&quot;--vde=
v {dev} &quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0vdev_args =3D vdev_args[:-1]<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 driver_tests_command =3D (<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;meson test -C {self.dpdk_=
build_dir_path} --suite driver-tests&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 driver_tests_command =3D f&quot;meson test -C =
{self.dpdk_build_dir_path} --suite driver-tests&quot;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if vdev_args:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._<a href=3D"http://log=
ger.info" rel=3D"noreferrer" target=3D"_blank">logger.info</a>(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot;Running driv=
er tests with the following virtual &quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 f&quot;devices: {v=
dev_args}&quot;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot;Running driv=
er tests with the following virtual &quot; f&quot;devices: {vdev_args}&quot=
;<br></blockquote><div><br></div><div><div style=3D"font-family:arial,sans-=
serif" class=3D"gmail_default">Double string that should be an f-string.<br=
></div></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:=
1ex">
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0driver_tests_command +=3D f=
&#39; --test-args &quot;{vdev_args}&quot;&#39;<br>
<br>
@@ -67,9 +64,7 @@ def test_devices_listed_in_testpmd(self) -&gt; None:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Test:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Uses testpmd driver to veri=
fy that devices have been found by testpmd.<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&quot;&quot;&quot;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 testpmd_driver =3D self.sut_node.create_intera=
ctive_shell(<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 TestPmdShell, privileged=3DTrue<=
br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 )<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 testpmd_driver =3D self.sut_node.create_intera=
ctive_shell(TestPmdShell, privileged=3DTrue)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dev_list =3D [str(x) for x in testpmd_dri=
ver.get_devices()]<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for nic in self.nics_in_node:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.verify(<br>
-- <br>
2.34.1<br>
<br>
</blockquote></div></div>

--000000000000a26bf306064a1647--