[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.