[PATCH 01/14] Add b4 CI checks and mypy suppressions
Tamir Duberstein <[email protected]>
| Newsgroups | org.kernel.linux.tools |
|---|---|
| Message-ID | <[email protected]> |
Add a repo-local b4 CI check command and helper script that runs mypy and pytest so review status surfaces local checks in the b4 UI. Introduce targeted mypy suppressions for current test-only issues so the baseline is green before tightening types further. Also add pytest-asyncio so pytest recognizes asyncio_default_fixture_loop_scope and stops warning about it. Signed-off-by: Tamir Duberstein <[email protected]> --- .b4-config | 2 ++ pyproject.toml | 14 ++++++++++ tools/b4-ci-check.py | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) diff --git a/.b4-config b/.b4-config new file mode 100644 index 0000000..ad41b6b --- /dev/null +++ b/.b4-config @@ -0,0 +1,2 @@ +[b4] + review-series-check-cmd = uv run ./tools/b4-ci-check.py diff --git a/pyproject.toml b/pyproject.toml index 2353a18..e31a05c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ dev = [ "build", "mypy", "pytest", + "pytest-asyncio", "ruff", "types-requests", ] @@ -56,5 +57,18 @@ strict = true module = "authheaders" ignore_missing_imports = true +[[tool.mypy.overrides]] +module = [ + "test_email_utils", + "test_formatting", + "test_message", + "test_thread", +] +disable_error_code = ["attr-defined"] + +[[tool.mypy.overrides]] +module = "test_auth_headers" +disable_error_code = ["unused-ignore"] + [tool.ruff] target-version = "py39" diff --git a/tools/b4-ci-check.py b/tools/b4-ci-check.py new file mode 100644 index 0000000..a51e19e --- /dev/null +++ b/tools/b4-ci-check.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-or-later + +from __future__ import annotations + +import json +import os +import sys +from contextlib import redirect_stderr, redirect_stdout +from dataclasses import dataclass +from io import StringIO +from pathlib import Path +from typing import Callable + +import mypy.api +import pytest + + +@dataclass(frozen=True) +class Check: + tool: str + args: list[str] + pass_summary: str + run: Callable[[list[str]], tuple[str, str, int]] + + +def run_pytest(args: list[str]) -> tuple[str, str, int]: + stdout_buffer = StringIO() + stderr_buffer = StringIO() + with redirect_stdout(stdout_buffer), redirect_stderr(stderr_buffer): + status = pytest.main(args) + return stdout_buffer.getvalue(), stderr_buffer.getvalue(), status + + +def main() -> None: + sys.stdin.buffer.read() + + repo_root = Path(__file__).resolve().parent.parent + os.chdir(repo_root) + checks = [ + # Mypy can emit JSON via "--output json", but b4 only renders details + # as plain text, so preserving the normal formatter is more readable. + Check( + tool='mypy', + args=['.'], + pass_summary='mypy passed', + run=mypy.api.run, + ), + Check( + tool='pytest', + args=['--durations=0'], + pass_summary='pytest passed', + run=run_pytest, + ), + ] + + results: list[dict[str, str | int]] = [] + for check in checks: + stdout, stderr, status = check.run(check.args) + details = (stdout + stderr).strip() + results.append( + { + 'tool': check.tool, + 'status': 'pass' if status == 0 else 'fail', + 'summary': ( + check.pass_summary + if status == 0 + else f'{check.tool} failed (exit {status})' + ), + 'details': details, + } + ) + + json.dump(results, sys.stdout, indent=2) + sys.stdout.write('\n') + + +if __name__ == '__main__': + main() -- 2.53.0