Thanks Dean. Series applied to next-dts.

On Thu, Jan 22, 2026 at 12:47 PM Dean Marx <[email protected]> wrote:
>
> Add a python script that checks all test cases
> to ensure each docstring contains a steps and
> verify section in accordance with coding guidelines.
> Add a section within the check-format script which
> calls the docstring script after linting with ruff.
>
> Bugzilla ID: 1623
>
> Signed-off-by: Dean Marx <[email protected]>
> Reviewed-by: Patrick Robb <[email protected]>
> ---
>  devtools/dts-check-docstrings.py | 54 ++++++++++++++++++++++++++++++++
>  devtools/dts-check-format.sh     |  5 +++
>  2 files changed, 59 insertions(+)
>  create mode 100755 devtools/dts-check-docstrings.py
>
> diff --git a/devtools/dts-check-docstrings.py 
> b/devtools/dts-check-docstrings.py
> new file mode 100755
> index 0000000000..3b0d2a42a1
> --- /dev/null
> +++ b/devtools/dts-check-docstrings.py
> @@ -0,0 +1,54 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: BSD-3-Clause
> +# Copyright(c) 2025 University of New Hampshire
> +
> +import sys
> +from ast import FunctionDef, Name, walk, get_docstring, parse
> +from pathlib import Path
> +
> +BASE_DIR = Path(__file__).resolve().parent.parent  # dpdk/
> +TESTS_DIR = BASE_DIR / "dts" / "tests"  # dts/tests/
> +DECORATOR_NAMES = {"func_test", "perf_test"}
> +
> +
> +def has_test_decorator(node: FunctionDef) -> bool:
> +    """Return True if function has @func_test or @perf_test decorator."""
> +    for decorator in node.decorator_list:
> +        if isinstance(decorator, Name) and decorator.id in DECORATOR_NAMES:
> +            return True
> +    return False
> +
> +
> +def check_file(path: Path) -> bool:
> +    """Return True if file has steps and verify sections in each test case 
> docstring."""
> +    source = path.read_text(encoding="utf-8")
> +    tree = parse(source, filename=str(path))
> +    ok = True
> +
> +    for node in walk(tree):
> +        if isinstance(node, FunctionDef):
> +            if has_test_decorator(node):
> +                doc = get_docstring(node)
> +                if not doc:
> +                    print(f"{path}:{node.lineno} missing docstring for test 
> case")
> +                    ok = False
> +                else:
> +                    if "Steps:" not in doc:
> +                        print(f"{path}:{node.lineno} missing 'Steps:' 
> section")
> +                        ok = False
> +                    if "Verify:" not in doc:
> +                        print(f"{path}:{node.lineno} missing 'Verify:' 
> section")
> +                        ok = False
> +    return ok
> +
> +
> +def main():
> +    all_ok = True
> +    for path in TESTS_DIR.rglob("*.py"):
> +        if not check_file(path):
> +            all_ok = False
> +    sys.exit(0 if all_ok else 1)
> +
> +
> +if __name__ == "__main__":
> +    main()
> diff --git a/devtools/dts-check-format.sh b/devtools/dts-check-format.sh
> index 907eed1293..23c0a5f1da 100755
> --- a/devtools/dts-check-format.sh
> +++ b/devtools/dts-check-format.sh
> @@ -13,6 +13,7 @@ usage() {
>  format=true
>  lint=true
>  typecheck=true
> +docstringcheck=true
>
>  # Comments after args serve as documentation; must be present
>  while getopts "hflt" arg; do
> @@ -97,6 +98,10 @@ if $lint; then
>                 echo "ruff not found, unable to run linter"
>                 errors=$((errors + 1))
>         fi
> +       if $docstringcheck; then
> +               python3 ../devtools/dts-check-docstrings.py
> +               errors=$((errors + $?))
> +       fi
>  fi
>
>  if $typecheck; then
> --
> 2.52.0
>

Reply via email to