From: Tamir Duberstein <tamird@kernel.org>
To: "Kernel.org Tools" <tools@kernel.org>
Cc: Konstantin Ryabitsev <konstantin@linuxfoundation.org>,
Tamir Duberstein <tamird@kernel.org>
Subject: [PATCH ezgb 4/6] Add pyright checks
Date: Sun, 19 Apr 2026 21:39:25 -0700 [thread overview]
Message-ID: <20260419-stronger-type-checking-v1-4-222775b987e5@kernel.org> (raw)
In-Reply-To: <20260419-stronger-type-checking-v1-0-222775b987e5@kernel.org>
Add pyright to local CI with strict source checking.
Signed-off-by: Tamir Duberstein <tamird@kernel.org>
---
ci.sh | 1 +
pyproject.toml | 7 +++++++
src/ezgb/__init__.py | 8 +++-----
src/ezgb/_git.py | 2 +-
src/ezgb/_models.py | 4 ++--
src/ezgb/_reader.py | 38 +++++++++++++++++++++-----------------
src/ezgb/_writer.py | 14 +++++++-------
7 files changed, 42 insertions(+), 32 deletions(-)
diff --git a/ci.sh b/ci.sh
index db7914f..fbc433d 100755
--- a/ci.sh
+++ b/ci.sh
@@ -5,4 +5,5 @@ set -eu
uv run ruff check
uv run ruff format --check
uv run mypy .
+uv run pyright
uv run pytest --durations=0
diff --git a/pyproject.toml b/pyproject.toml
index c043817..452bd6a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -26,6 +26,7 @@ classifiers = [
[dependency-groups]
dev = [
"mypy",
+ "pyright",
"pytest",
"ruff",
]
@@ -50,3 +51,9 @@ select = ["E", "F", "W", "I"]
[tool.ruff.format]
quote-style = "single"
+
+[tool.pyright]
+typeCheckingMode = "strict"
+executionEnvironments = [
+ { root = "tests", reportPrivateUsage = false },
+]
diff --git a/src/ezgb/__init__.py b/src/ezgb/__init__.py
index 5cb23ae..f2f5d3d 100644
--- a/src/ezgb/__init__.py
+++ b/src/ezgb/__init__.py
@@ -23,7 +23,7 @@ from ezgb._models import (
Status,
UnsupportedFormatError,
)
-from ezgb._reader import BugReader
+from ezgb._reader import BugReader, parse_since
from ezgb._types import JsonValue
from ezgb._writer import BugWriter
@@ -77,9 +77,7 @@ class GitBugRepo:
since = since.replace(tzinfo=timezone.utc)
return int(since.timestamp())
# str -- delegate to the reader's parser
- from ezgb._reader import BugReader
-
- return BugReader._parse_since(since)
+ return parse_since(since)
def list_bugs(
self,
@@ -206,7 +204,7 @@ class GitBugRepo:
author_id = author.get('id', '') if isinstance(author, dict) else ''
raw_labels = raw.get('labels') or []
if isinstance(raw_labels, list):
- labels = frozenset(str(lb) for lb in raw_labels)
+ labels: frozenset[str] = frozenset(str(lb) for lb in raw_labels)
else:
labels = frozenset()
comment_count = raw.get('comments', 0)
diff --git a/src/ezgb/_git.py b/src/ezgb/_git.py
index 4e29646..c1c326b 100644
--- a/src/ezgb/_git.py
+++ b/src/ezgb/_git.py
@@ -45,7 +45,7 @@ def git_run(
def git_lines(repo_path: str, args: list[str]) -> list[str]:
"""Run a git command and return non-empty output lines."""
- ecode, out = git_run(repo_path, args)
+ _ecode, out = git_run(repo_path, args)
if not isinstance(out, str):
out = out.decode(errors='replace')
return [line for line in out.split('\n') if line]
diff --git a/src/ezgb/_models.py b/src/ezgb/_models.py
index b8716f0..22e45a7 100644
--- a/src/ezgb/_models.py
+++ b/src/ezgb/_models.py
@@ -96,7 +96,7 @@ class Comment:
text: str
created_at: datetime
count: int
- attachment_ids: list[str] = field(default_factory=list)
+ attachment_ids: list[str] = field(default_factory=list[str])
@dataclass
@@ -110,7 +110,7 @@ class Bug:
created_at: datetime
labels: set[str]
comments: list[Comment]
- metadata: dict[str, str] = field(default_factory=dict)
+ metadata: dict[str, str] = field(default_factory=dict[str, str])
@dataclass(frozen=True)
diff --git a/src/ezgb/_reader.py b/src/ezgb/_reader.py
index 735d41d..2d44478 100644
--- a/src/ezgb/_reader.py
+++ b/src/ezgb/_reader.py
@@ -57,6 +57,26 @@ def _is_dict_values(value: dict[_K, _T], value_ty: type[_U]) -> TypeGuard[dict[_
return all(isinstance(value, value_ty) for value in value.values())
+def parse_since(since: str) -> int:
+ """Parse a datetime string to a unix timestamp.
+
+ Accepts ISO-8601 variants and ``YYYYMMDDHHMMSS``.
+ """
+ since = since.strip()
+ for fmt in (
+ '%Y-%m-%d %H:%M:%S',
+ '%Y%m%d%H%M%S',
+ '%Y-%m-%dT%H:%M:%SZ',
+ '%Y-%m-%dT%H:%M:%S',
+ ):
+ try:
+ dt = datetime.strptime(since, fmt).replace(tzinfo=timezone.utc)
+ return int(dt.timestamp())
+ except ValueError:
+ continue
+ raise ValueError('cannot parse since=%s' % since)
+
+
def _combine_ids(primary: str, secondary: str) -> str:
"""Interleave primary and secondary IDs into a CombinedId.
@@ -415,23 +435,7 @@ class BugReader:
@staticmethod
def _parse_since(since: str) -> int:
- """Parse a datetime string to a unix timestamp.
-
- Accepts ISO-8601 variants and ``YYYYMMDDHHMMSS``.
- """
- since = since.strip()
- for fmt in (
- '%Y-%m-%d %H:%M:%S',
- '%Y%m%d%H%M%S',
- '%Y-%m-%dT%H:%M:%SZ',
- '%Y-%m-%dT%H:%M:%S',
- ):
- try:
- dt = datetime.strptime(since, fmt).replace(tzinfo=timezone.utc)
- return int(dt.timestamp())
- except ValueError:
- continue
- raise ValueError('cannot parse since=%s' % since)
+ return parse_since(since)
def build_bug(
self,
diff --git a/src/ezgb/_writer.py b/src/ezgb/_writer.py
index ae1d45f..adacfa1 100644
--- a/src/ezgb/_writer.py
+++ b/src/ezgb/_writer.py
@@ -77,7 +77,7 @@ class BugWriter:
'-',
'--non-interactive',
]
- ecode, out, err = self._cli(args, stdin=text)
+ ecode, _out, err = self._cli(args, stdin=text)
if ecode != 0:
raise CliError('git bug comment new failed: %s' % err)
self._reader.invalidate(bid)
@@ -100,7 +100,7 @@ class BugWriter:
'-',
'--non-interactive',
]
- ecode, out, err = self._cli(args, stdin=text)
+ ecode, _out, err = self._cli(args, stdin=text)
if ecode != 0:
raise CliError('git bug comment edit failed: %s' % err)
self._reader.invalidate(bid)
@@ -112,7 +112,7 @@ class BugWriter:
subcmd = 'close'
else:
subcmd = 'open'
- ecode, out, err = self._cli(['bug', 'status', subcmd, bid])
+ ecode, _out, err = self._cli(['bug', 'status', subcmd, bid])
if ecode != 0:
raise CliError('git bug status %s failed: %s' % (subcmd, err))
self._reader.invalidate(bid)
@@ -121,7 +121,7 @@ class BugWriter:
"""Edit a bug's title."""
bid = self._reader.resolve_bug_id(bid)
args = ['bug', 'title', 'edit', bid, '-t', title]
- ecode, out, err = self._cli(args)
+ ecode, _out, err = self._cli(args)
if ecode != 0:
raise CliError('git bug title edit failed: %s' % err)
self._reader.invalidate(bid)
@@ -129,7 +129,7 @@ class BugWriter:
def add_label(self, bid: str, label: str) -> None:
"""Add a label to a bug."""
bid = self._reader.resolve_bug_id(bid)
- ecode, out, err = self._cli(
+ ecode, _out, err = self._cli(
['bug', 'label', 'new', bid, label],
)
if ecode != 0:
@@ -139,7 +139,7 @@ class BugWriter:
def remove_label(self, bid: str, label: str) -> None:
"""Remove a label from a bug."""
bid = self._reader.resolve_bug_id(bid)
- ecode, out, err = self._cli(
+ ecode, _out, err = self._cli(
['bug', 'label', 'rm', bid, label],
)
if ecode != 0:
@@ -153,7 +153,7 @@ class BugWriter:
remote copies. This is irreversible.
"""
bid = self._reader.resolve_bug_id(bid)
- ecode, out, err = self._cli(['bug', 'rm', bid])
+ ecode, _out, err = self._cli(['bug', 'rm', bid])
if ecode != 0:
raise CliError('git bug rm failed: %s' % err)
# Invalidate everything — the refs list has changed
--
2.53.0
next prev parent reply other threads:[~2026-04-20 4:39 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-20 4:39 [PATCH ezgb 0/6] Harden local CI checks Tamir Duberstein
2026-04-20 4:39 ` [PATCH ezgb 1/6] Add local CI script Tamir Duberstein
2026-04-20 4:39 ` [PATCH ezgb 2/6] Add mypy checks Tamir Duberstein
2026-04-20 4:39 ` [PATCH ezgb 3/6] Add Ruff format check Tamir Duberstein
2026-04-20 4:39 ` Tamir Duberstein [this message]
2026-04-20 4:39 ` [PATCH ezgb 5/6] Add ty checks Tamir Duberstein
2026-04-20 4:39 ` [PATCH ezgb 6/6] Document local CI checks Tamir Duberstein
2026-04-27 20:20 ` [PATCH ezgb 0/6] Harden " Tamir Duberstein
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260419-stronger-type-checking-v1-4-222775b987e5@kernel.org \
--to=tamird@kernel.org \
--cc=konstantin@linuxfoundation.org \
--cc=tools@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox