[PATCH v3] dts: add missing type hints to method signatures
Luca Vizzarro
Luca.Vizzarro at arm.com
Wed Aug 20 11:52:41 CEST 2025
Hi Andrew,
we are almost there! Just a few functional issues with the changes.
On 18/08/2025 17:50, Andrew Bailey wrote:
> diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
> index d4aa02f39b..18ce4e6011 100644
> --- a/dts/framework/remote_session/dpdk_shell.py
> +++ b/dts/framework/remote_session/dpdk_shell.py
> @@ -78,9 +78,14 @@ def __init__(
> def path(self) -> PurePath:
> """Relative path to the shell executable from the build folder."""
>
> - def _make_real_path(self):
> + def _make_real_path(self) -> PurePath | str:
> """Overrides :meth:`~.interactive_shell.InteractiveShell._make_real_path`.
>
> Adds the remote DPDK build directory to the path.
> """
> - return get_ctx().dpdk_build.remote_dpdk_build_dir.joinpath(self.path)
> + real_path = get_ctx().dpdk_build.remote_dpdk_build_dir
> + match real_path:
> + case PurePath():
> + return real_path.joinpath(self.path)
> + case _:
> + return ""
Rightfully, mypy is complaining about this, that is because this should
only return PurePath. The implementation as written is also broken,
because returning an empty string is not acceptable.
The problem here stems from the fact that remote_dpdk_build_dir can be
str. In this case we wrap it in PurePath:
return
PurePath(get_ctx().dpdk_build.remote_dpdk_build_dir).joinpath(self.path)
But looking into remote_dpdk_build_dir it looks like that is only
returning an empty str in case it's not present. In this case I would
just change that property to return an empty PurePath instead:
PurePath()
or change the whole signature to return None.
> diff --git a/dts/framework/remote_session/remote_session.py b/dts/framework/remote_session/remote_session.py
> index 89d4618c41..ba15b3baa3 100644
> --- a/dts/framework/remote_session/remote_session.py
> +++ b/dts/framework/remote_session/remote_session.py
> @@ -57,9 +57,7 @@ def __post_init__(self, init_stdout: str, init_stderr: str) -> None:
> def __str__(self) -> str:
> """Format the command outputs."""
> return (
> - f"stdout: '{self.stdout}'\n"
> - f"stderr: '{self.stderr}'\n"
> - f"return_code: '{self.return_code}'"
> + f"stdout: '{self.stdout}'\nstderr: '{self.stderr}'\nreturn_code: '{self.return_code}'"
this was split across lines to reflect the actual output, i.e. for
clarity. Why this change?
I noticed some other formatting changes as well like spacing in
formatted strings. Changes which don't really pertain to this patch.
Do you have an IDE with a misconfigured formatter? If that's the case,
please fix your settings to use ruff and the existing ruff format
configuration.
> )
>
>
> diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py
> index ad8cb273dc..7b981111f6 100644
> --- a/dts/framework/remote_session/testpmd_shell.py
> +++ b/dts/framework/remote_session/testpmd_shell.py
> @@ -237,13 +237,17 @@ def find_action(
>
> return action
>
> - def error(self, message):
> + def error(self, message) -> NoReturn:
> """Augments :meth:`~argparse.ArgumentParser.error` with environment variable awareness."""
> for action in self._actions:
> if _is_from_env(action):
> action_name = _get_action_name(action)
> env_var_name = _get_env_var_name(action)
> - env_var_value = os.environ.get(env_var_name)
> + match env_var_name:
> + case None:
> + env_var_value = None
> + case nonEmpty:
> + env_var_value = os.environ.get(nonEmpty)
This is a bit too verbose for something as simple as an if. But this is
not a reasonable solution in this case.
Because of `if _is_from_env(action)` then `env_var_name` cannot be None.
The only case in which this could be None is a bug. This is the case
where an assertion should go in instead:
assert env_var_name is not None, "Action was set from environment,
but no environment variable name was found."
>
> message = message.replace(
> f"argument {action_name}",
> diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
> index 4355aeeb4b..4db7de2487 100644
> --- a/dts/framework/test_run.py
> +++ b/dts/framework/test_run.py
> @@ -162,7 +162,7 @@ class TestRun:
> config: TestRunConfiguration
> logger: DTSLogger
>
> - state: "State"
> + state: "State" | None
the docs builder doesn't like using the piping operator with a string
annotation. I am surprised the CI didn't complain here. To avoid this
issue you should use Union from typing instead:
Union["State", None]
> ctx: Context
> result: TestRunResult
> selected_tests: list[TestScenario]
> @@ -235,7 +235,7 @@ def spin(self):
> self.state.before()
> next_state = self.state.next()
> except (KeyboardInterrupt, Exception) as e:
> - next_state = self.state.handle_exception(e)
> + next_state = self.state.handle_exception(Exception(e))
This is a breaking change. All of the underlying exception checks will
no longer work if you wrap a custom exception with a generic exception.
The correct solution is to let the signature of handle_exception accept
BaseException instead which will also cover KeyboardInterrupt.
> finally:
> self.state.after()
> if next_state is not None:
Thank you,
Luca
More information about the dev
mailing list