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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.