Skip to content

Commit 23ac9bf

Browse files
authored
Check for unused pyright: ignore and differentiate from mypy ignores (#9397)
1 parent 07f587d commit 23ac9bf

File tree

17 files changed

+44
-21
lines changed

17 files changed

+44
-21
lines changed

CONTRIBUTING.md

+5
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,11 @@ Some further tips for good type hints:
467467
platform-dependent APIs;
468468
* use mypy error codes for mypy-specific `# type: ignore` annotations,
469469
e.g. `# type: ignore[override]` for Liskov Substitution Principle violations.
470+
* use pyright error codes for pyright-specific suppressions,
471+
e.g. `# pyright: ignore[reportGeneralTypeIssues]`.
472+
- pyright is configured to discard `# type: ignore` annotations.
473+
If you need both on the same line, mypy's annotation needs to go first,
474+
e.g. `# type: ignore[override] # pyright: ignore[reportGeneralTypeIssues]`.
470475

471476
Imports in stubs are considered private (not part of the exported API)
472477
unless:

pyrightconfig.json

+6
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@
3535
"reportInconsistentConstructor": "error",
3636
"reportTypeCommentUsage": "error",
3737
"reportUnnecessaryComparison": "error",
38+
"reportUnnecessaryTypeIgnoreComment": "error",
39+
// Leave "type: ignore" comments to mypy
40+
"enableTypeIgnoreComments": false,
41+
// Stubs are allowed to use private variables
42+
"reportPrivateUsage": "none",
43+
// Stubs don't need the actual modules to be installed
3844
"reportMissingModuleSource": "none",
3945
// Incompatible overrides and property type mismatches are out of typeshed's control
4046
// as they are inherited from the implementation.

pyrightconfig.stricter.json

+6
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,14 @@
7373
"stubs/vobject",
7474
],
7575
"typeCheckingMode": "strict",
76+
"reportUnnecessaryTypeIgnoreComment": "error",
77+
// Leave "type: ignore" comments to mypy
78+
"enableTypeIgnoreComments": false,
79+
// Stubs are allowed to use private variables
7680
"reportPrivateUsage": "none",
81+
// TODO: Complete incomplete stubs
7782
"reportIncompleteStub": "none",
83+
// Stubs don't need the actual modules to be installed
7884
"reportMissingModuleSource": "none",
7985
// Incompatible overrides and property type mismatches are out of typeshed's control
8086
// as they are inherited from the implementation.

pyrightconfig.testcases.json

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
"test_cases",
66
],
77
"typeCheckingMode": "strict",
8+
// Using unspecific "type ignore" comments in test_cases.
9+
// See https://github.com/python/typeshed/pull/8083
10+
"enableTypeIgnoreComments": true,
811
"reportPropertyTypeMismatch": "error",
912
"reportUnnecessaryTypeIgnoreComment": "error",
1013
"reportMissingModuleSource": "none",

stdlib/asyncio/tasks.pyi

+1-1
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ else:
270270
# While this is true in general, here it's sort-of okay to have a covariant subclass,
271271
# since the only reason why `asyncio.Future` is invariant is the `set_result()` method,
272272
# and `asyncio.Task.set_result()` always raises.
273-
class Task(Future[_T_co], Generic[_T_co]): # type: ignore[type-var]
273+
class Task(Future[_T_co], Generic[_T_co]): # type: ignore[type-var] # pyright: ignore[reportGeneralTypeIssues]
274274
if sys.version_info >= (3, 8):
275275
def __init__(
276276
self,

stdlib/builtins.pyi

+1-1
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,7 @@ class property:
11881188
class _NotImplementedType(Any): # type: ignore[misc]
11891189
# A little weird, but typing the __call__ as NotImplemented makes the error message
11901190
# for NotImplemented() much better
1191-
__call__: NotImplemented # type: ignore[valid-type]
1191+
__call__: NotImplemented # type: ignore[valid-type] # pyright: ignore[reportGeneralTypeIssues]
11921192

11931193
NotImplemented: _NotImplementedType
11941194

stdlib/collections/__init__.pyi

+4-3
Original file line numberDiff line numberDiff line change
@@ -327,16 +327,17 @@ class _OrderedDictValuesView(ValuesView[_VT_co], Reversible[_VT_co]):
327327
# The C implementations of the "views" classes
328328
# (At runtime, these are called `odict_keys`, `odict_items` and `odict_values`,
329329
# but they are not exposed anywhere)
330+
# pyright doesn't have a specific error code for subclassing error!
330331
@final
331-
class _odict_keys(dict_keys[_KT_co, _VT_co], Reversible[_KT_co]): # type: ignore[misc]
332+
class _odict_keys(dict_keys[_KT_co, _VT_co], Reversible[_KT_co]): # type: ignore[misc] # pyright: ignore
332333
def __reversed__(self) -> Iterator[_KT_co]: ...
333334

334335
@final
335-
class _odict_items(dict_items[_KT_co, _VT_co], Reversible[tuple[_KT_co, _VT_co]]): # type: ignore[misc]
336+
class _odict_items(dict_items[_KT_co, _VT_co], Reversible[tuple[_KT_co, _VT_co]]): # type: ignore[misc] # pyright: ignore
336337
def __reversed__(self) -> Iterator[tuple[_KT_co, _VT_co]]: ...
337338

338339
@final
339-
class _odict_values(dict_values[_KT_co, _VT_co], Reversible[_VT_co], Generic[_KT_co, _VT_co]): # type: ignore[misc]
340+
class _odict_values(dict_values[_KT_co, _VT_co], Reversible[_VT_co], Generic[_KT_co, _VT_co]): # type: ignore[misc] # pyright: ignore
340341
def __reversed__(self) -> Iterator[_VT_co]: ...
341342

342343
class OrderedDict(dict[_KT, _VT], Reversible[_KT], Generic[_KT, _VT]):

stdlib/ctypes/__init__.pyi

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ class _CDataMeta(type):
6464
# By default mypy complains about the following two methods, because strictly speaking cls
6565
# might not be a Type[_CT]. However this can never actually happen, because the only class that
6666
# uses _CDataMeta as its metaclass is _CData. So it's safe to ignore the errors here.
67-
def __mul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc]
68-
def __rmul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc]
67+
def __mul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
68+
def __rmul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
6969

7070
class _CData(metaclass=_CDataMeta):
7171
_b_base: int

stdlib/subprocess.pyi

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class CompletedProcess(Generic[_T]):
9797
args: _CMD,
9898
returncode: int,
9999
stdout: _T | None = ..., # pyright: ignore[reportInvalidTypeVarUse]
100-
stderr: _T | None = ..., # pyright: ignore[reportInvalidTypeVarUse]
100+
stderr: _T | None = ...,
101101
) -> None: ...
102102
def check_returncode(self) -> None: ...
103103
if sys.version_info >= (3, 9):

stubs/SQLAlchemy/sqlalchemy/orm/path_registry.pyi

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from _typeshed import Incomplete
12
from typing import Any, ClassVar
23

34
from ..sql.traversals import HasCacheKey
@@ -100,7 +101,7 @@ class AbstractEntityRegistry(PathRegistry):
100101
class SlotsEntityRegistry(AbstractEntityRegistry):
101102
inherit_cache: bool
102103

103-
class CachingEntityRegistry(AbstractEntityRegistry, dict): # type: ignore[misc]
104+
class CachingEntityRegistry(AbstractEntityRegistry, dict[Incomplete, Incomplete]): # type: ignore[misc]
104105
inherit_cache: bool
105106
def __getitem__(self, entity): ...
106107
def __missing__(self, key): ...

stubs/SQLAlchemy/sqlalchemy/util/_collections.pyi

+4-4
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,13 @@ class OrderedSet(set[_T], Generic[_T]):
8585
def update(self: Self, iterable: Iterable[_T]) -> Self: ... # type: ignore[override]
8686
__ior__ = update # type: ignore[assignment]
8787
def union(self, other: Iterable[_S]) -> OrderedSet[_S | _T]: ... # type: ignore[override]
88-
__or__ = union # type: ignore[assignment]
88+
__or__ = union # type: ignore[assignment] # pyright: ignore[reportGeneralTypeIssues]
8989
def intersection(self: Self, other: Iterable[Any]) -> Self: ... # type: ignore[override]
90-
__and__ = intersection # type: ignore[assignment]
90+
__and__ = intersection # type: ignore[assignment] # pyright: ignore[reportGeneralTypeIssues]
9191
def symmetric_difference(self, other: Iterable[_S]) -> OrderedSet[_S | _T]: ...
92-
__xor__ = symmetric_difference # type: ignore[assignment]
92+
__xor__ = symmetric_difference # type: ignore[assignment] # pyright: ignore[reportGeneralTypeIssues]
9393
def difference(self: Self, other: Iterable[Any]) -> Self: ... # type: ignore[override]
94-
__sub__ = difference # type: ignore[assignment]
94+
__sub__ = difference # type: ignore[assignment] # pyright: ignore[reportGeneralTypeIssues]
9595
def intersection_update(self: Self, other: Iterable[Any]) -> Self: ... # type: ignore[override]
9696
__iand__ = intersection_update # type: ignore[assignment]
9797
def symmetric_difference_update(self: Self, other: Iterable[_T]) -> Self: ... # type: ignore[override]

stubs/invoke/invoke/tasks.pyi

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from _typeshed import Self
1+
from _typeshed import Incomplete, Self
22
from collections.abc import Callable, Iterable
33
from typing import Any, Generic, TypeVar, overload
44
from typing_extensions import ParamSpec
@@ -48,7 +48,7 @@ class Task(Generic[_P, _R_co]):
4848
) -> None: ...
4949
@property
5050
def name(self): ...
51-
def __eq__(self, other: Task) -> bool: ... # type: ignore[override]
51+
def __eq__(self, other: Task[Incomplete, Incomplete]) -> bool: ... # type: ignore[override]
5252
def __hash__(self) -> int: ...
5353
def __call__(self, *args: _P.args, **kwargs: _P.kwargs) -> _R_co: ...
5454
@property

stubs/prettytable/prettytable/colortable.pyi

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class Theme:
2727
junction_color: str = ...,
2828
) -> None: ...
2929
# The following method is broken in upstream code.
30-
def format_code(s: str) -> str: ... # type: ignore[misc]
30+
def format_code(s: str) -> str: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
3131

3232
class Themes:
3333
DEFAULT: ClassVar[Theme]

stubs/pywin32/win32comext/axdebug/documents.pyi

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ class DebugDocumentProvider(gateways.DebugDocumentProvider):
1414
def GetDocument(self): ...
1515

1616
# error: Cannot determine consistent method resolution order (MRO) for "DebugDocumentText"
17-
class DebugDocumentText(gateways.DebugDocumentInfo, gateways.DebugDocumentText, gateways.DebugDocument): # type: ignore[misc]
17+
# pyright doesn't have a specific error code for MRO error!
18+
class DebugDocumentText(gateways.DebugDocumentInfo, gateways.DebugDocumentText, gateways.DebugDocument): # type: ignore[misc] # pyright: ignore
1819
codeContainer: Incomplete
1920
def __init__(self, codeContainer) -> None: ...
2021
def GetName(self, dnt): ...

stubs/redis/redis/client.pyi

-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ _StrType = TypeVar("_StrType", bound=str | bytes)
2323

2424
_VT = TypeVar("_VT")
2525
_T = TypeVar("_T")
26-
_ScoreCastFuncReturn = TypeVar("_ScoreCastFuncReturn")
2726

2827
# Keyword arguments that are passed to Redis.parse_response().
2928
_ParseResponseOptions: TypeAlias = Any
@@ -568,7 +567,6 @@ class Pipeline(Redis[_StrType], Generic[_StrType]):
568567
def sscan_iter(self, name: _Key, match: _Key | None = ..., count: int | None = ...) -> Iterator[Any]: ...
569568
def hscan(self, name: _Key, cursor: int = ..., match: _Key | None = ..., count: int | None = ...) -> Pipeline[_StrType]: ... # type: ignore[override]
570569
def hscan_iter(self, name, match: _Key | None = ..., count: int | None = ...) -> Iterator[Any]: ...
571-
def zscan(self, name: _Key, cursor: int = ..., match: _Key | None = ..., count: int | None = ..., score_cast_func: Callable[[_StrType], _ScoreCastFuncReturn] = ...) -> Pipeline[_StrType]: ... # type: ignore[override]
572570
def zscan_iter(
573571
self, name: _Key, match: _Key | None = ..., count: int | None = ..., score_cast_func: Callable[[_StrType], Any] = ...
574572
) -> Iterator[Any]: ...

stubs/redis/redis/commands/json/__init__.pyi

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from _typeshed import Incomplete
12
from typing import Any
23

34
from ...client import Pipeline as ClientPipeline
@@ -11,4 +12,4 @@ class JSON(JSONCommands):
1112
def __init__(self, client, version: Any | None = ..., decoder=..., encoder=...) -> None: ...
1213
def pipeline(self, transaction: bool = ..., shard_hint: Any | None = ...) -> Pipeline: ...
1314

14-
class Pipeline(JSONCommands, ClientPipeline): ... # type: ignore[misc]
15+
class Pipeline(JSONCommands, ClientPipeline[Incomplete]): ... # type: ignore[misc]

stubs/redis/redis/commands/timeseries/__init__.pyi

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from _typeshed import Incomplete
12
from typing import Any
23

34
from ...client import Pipeline as ClientPipeline
@@ -10,4 +11,4 @@ class TimeSeries(TimeSeriesCommands):
1011
def __init__(self, client: Any | None = ..., **kwargs) -> None: ...
1112
def pipeline(self, transaction: bool = ..., shard_hint: Any | None = ...) -> Pipeline: ...
1213

13-
class Pipeline(TimeSeriesCommands, ClientPipeline): ... # type: ignore[misc]
14+
class Pipeline(TimeSeriesCommands, ClientPipeline[Incomplete]): ... # type: ignore[misc]

0 commit comments

Comments
 (0)