[PATCH v2 05/14] Add pyright strict checks to CI

Tamir Duberstein <[email protected]>
Newsgroups org.kernel.linux.tools
Message-ID <[email protected]>
Configure pyright in strict mode and run it from the b4 CI checker.

Allow private-usage checks to be disabled only for tests via a pyright
execution environment override, and silence missing type stubs for the
optional authheaders dependency.

Add a small number of casts in tests to satisfy pyright. These casts
should be removed in a follow-up commit by tightening the mocked types
further.
---
 ci.sh               |  1 +
 pyproject.toml      | 11 ++++++++---
 src/liblore/node.py |  2 +-
 tests/test_node.py  | 11 ++++++++---
 4 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/ci.sh b/ci.sh
index ec0baf8..4b07fa2 100755
--- a/ci.sh
+++ b/ci.sh
@@ -5,4 +5,5 @@ set -eu
 uv run ruff format --check
 uv run ruff check
 uv run mypy .
+uv run pyright
 uv run pytest --durations=0
diff --git a/pyproject.toml b/pyproject.toml
index 9bfadbe..7a96d23 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -39,6 +39,7 @@ Repository = "https://git.kernel.org/pub/scm/utils/liblore/liblore.git"
 dev = [
     "build",
     "mypy",
+    "pyright",
     "pytest",
     "pytest-asyncio",
     "ruff",
@@ -53,9 +54,13 @@ asyncio_default_fixture_loop_scope = "function"
 [tool.mypy]
 strict = true
 
-[[tool.mypy.overrides]]
-module = "authheaders"
-ignore_missing_imports = true
+[tool.pyright]
+typeCheckingMode = "strict"
+
+executionEnvironments = [
+    # We're testing private APIs quite a bit.
+    { root = "tests", reportPrivateUsage = false },
+]
 
 [tool.ruff.lint]
 extend-select = ["I"]
diff --git a/src/liblore/node.py b/src/liblore/node.py
index 503428b..095ba4f 100644
--- a/src/liblore/node.py
+++ b/src/liblore/node.py
@@ -195,7 +195,7 @@ class LoreNode:
         self._authheaders: types.ModuleType | None = None
         if add_auth_headers:
             try:
-                import authheaders
+                import authheaders  # type: ignore[import-untyped]
 
                 self._authheaders = authheaders
             except ImportError:
diff --git a/tests/test_node.py b/tests/test_node.py
index 8f4ccac..af140db 100644
--- a/tests/test_node.py
+++ b/tests/test_node.py
@@ -7,6 +7,7 @@ import gzip
 import os
 from datetime import datetime, timezone
 from email.message import EmailMessage
+from typing import cast
 from unittest.mock import MagicMock, call, patch
 
 import pytest
@@ -25,7 +26,9 @@ class TestSessionManagement:
         node = LoreNode()
         s = node._get_session()
         assert s is not None
-        assert 'liblore/' in s.headers['User-Agent']
+        user_agent = s.headers['User-Agent']
+        assert isinstance(user_agent, str)
+        assert 'liblore/' in user_agent
         node.close()
 
     def test_returns_same_session(self) -> None:
@@ -74,7 +77,9 @@ class TestSessionManagement:
     def test_default_no_plus(self) -> None:
         node = LoreNode()
         s = node._get_session()
-        assert '+' not in s.headers['User-Agent']
+        user_agent = s.headers['User-Agent']
+        assert isinstance(user_agent, str)
+        assert '+' not in user_agent
         node.close()
 
     def test_set_requests_session(self) -> None:
@@ -1008,7 +1013,7 @@ class TestProbeOrigins:
         def fake_head(url: str, **kwargs: object) -> MagicMock:
             headers = kwargs.get('headers', {})
             assert isinstance(headers, dict)
-            captured_headers.append(headers)
+            captured_headers.append(cast(dict[str, str], headers))
             resp = MagicMock()
             resp.status_code = 200
             return resp

-- 
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.