Avoid recommending Self usages in metaclasses (#8639)

PEP 673 forbids the use of `typing(_extensions).Self` in metaclasses, so
we want to avoid flagging `PYI034` on metaclasses. This is based on an
analogous change in `flake8-pyi`:
https://github.com/PyCQA/flake8-pyi/pull/436.

Closes https://github.com/astral-sh/ruff/issues/8353.
This commit is contained in:
Charlie Marsh 2023-11-12 16:47:48 -08:00 committed by GitHub
parent 7fd95e15d9
commit 213d315373
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 175 additions and 97 deletions

View file

@ -3,9 +3,11 @@
import abc import abc
import builtins import builtins
import collections.abc import collections.abc
import enum
import typing import typing
from abc import abstractmethod from abc import ABCMeta, abstractmethod
from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator
from enum import EnumMeta
from typing import Any, overload from typing import Any, overload
import typing_extensions import typing_extensions
@ -199,6 +201,31 @@ class AsyncIteratorReturningAsyncIterable:
... # Y045 "__aiter__" methods should return an AsyncIterator, not an AsyncIterable ... # Y045 "__aiter__" methods should return an AsyncIterator, not an AsyncIterable
class MetaclassInWhichSelfCannotBeUsed(type):
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed: ...
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed: ...
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed: ...
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed) -> MetaclassInWhichSelfCannotBeUsed: ...
class MetaclassInWhichSelfCannotBeUsed2(EnumMeta):
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed2: ...
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed2: ...
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed2: ...
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed2) -> MetaclassInWhichSelfCannotBeUsed2: ...
class MetaclassInWhichSelfCannotBeUsed3(enum.EnumType):
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed3: ...
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed3: ...
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed3: ...
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed3) -> MetaclassInWhichSelfCannotBeUsed3: ...
class MetaclassInWhichSelfCannotBeUsed4(ABCMeta):
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed4: ...
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed4: ...
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed4: ...
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed4) -> MetaclassInWhichSelfCannotBeUsed4: ...
class Abstract(Iterator[str]): class Abstract(Iterator[str]):
@abstractmethod @abstractmethod
def __iter__(self) -> Iterator[str]: def __iter__(self) -> Iterator[str]:

View file

@ -3,9 +3,11 @@
import abc import abc
import builtins import builtins
import collections.abc import collections.abc
import enum
import typing import typing
from abc import abstractmethod from abc import ABCMeta, abstractmethod
from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator
from enum import EnumMeta
from typing import Any, overload from typing import Any, overload
import typing_extensions import typing_extensions
@ -152,6 +154,30 @@ class AsyncIteratorReturningAsyncIterable:
str str
]: ... # Y045 "__aiter__" methods should return an AsyncIterator, not an AsyncIterable ]: ... # Y045 "__aiter__" methods should return an AsyncIterator, not an AsyncIterable
class MetaclassInWhichSelfCannotBeUsed(type):
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed: ...
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed: ...
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed: ...
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed) -> MetaclassInWhichSelfCannotBeUsed: ...
class MetaclassInWhichSelfCannotBeUsed2(EnumMeta):
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed2: ...
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed2: ...
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed2: ...
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed2) -> MetaclassInWhichSelfCannotBeUsed2: ...
class MetaclassInWhichSelfCannotBeUsed3(enum.EnumType):
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed3: ...
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed3: ...
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed3: ...
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed3) -> MetaclassInWhichSelfCannotBeUsed3: ...
class MetaclassInWhichSelfCannotBeUsed4(ABCMeta):
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed4: ...
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed4: ...
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed4: ...
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed4) -> MetaclassInWhichSelfCannotBeUsed4: ...
class Abstract(Iterator[str]): class Abstract(Iterator[str]):
@abstractmethod @abstractmethod
def __iter__(self) -> Iterator[str]: ... def __iter__(self) -> Iterator[str]: ...

View file

@ -131,6 +131,11 @@ pub(crate) fn non_self_return_type(
return; return;
}; };
// PEP 673 forbids the use of `typing(_extensions).Self` in metaclasses.
if is_metaclass(class_def, checker.semantic()) {
return;
}
// Skip any abstract or overloaded methods. // Skip any abstract or overloaded methods.
if is_abstract(decorator_list, checker.semantic()) if is_abstract(decorator_list, checker.semantic())
|| is_overload(decorator_list, checker.semantic()) || is_overload(decorator_list, checker.semantic())
@ -214,6 +219,26 @@ pub(crate) fn non_self_return_type(
} }
} }
/// Returns `true` if the given class is a metaclass.
fn is_metaclass(class_def: &ast::StmtClassDef, semantic: &SemanticModel) -> bool {
class_def.arguments.as_ref().is_some_and(|arguments| {
arguments
.args
.iter()
.any(|expr| is_metaclass_base(expr, semantic))
})
}
/// Returns `true` if the given expression resolves to a metaclass.
fn is_metaclass_base(base: &Expr, semantic: &SemanticModel) -> bool {
semantic.resolve_call_path(base).is_some_and(|call_path| {
matches!(
call_path.as_slice(),
["" | "builtins", "type"] | ["abc", "ABCMeta"] | ["enum", "EnumMeta" | "EnumType"]
)
})
}
/// Returns `true` if the method is an in-place binary operator. /// Returns `true` if the method is an in-place binary operator.
fn is_inplace_bin_op(name: &str) -> bool { fn is_inplace_bin_op(name: &str) -> bool {
matches!( matches!(

View file

@ -1,91 +1,91 @@
--- ---
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
--- ---
PYI034.py:19:9: PYI034 `__new__` methods in classes like `Bad` usually return `self` at runtime PYI034.py:21:9: PYI034 `__new__` methods in classes like `Bad` usually return `self` at runtime
| |
17 | object 19 | object
18 | ): # Y040 Do not inherit from "object" explicitly, as it is redundant in Python 3 20 | ): # Y040 Do not inherit from "object" explicitly, as it is redundant in Python 3
19 | def __new__(cls, *args: Any, **kwargs: Any) -> Bad: 21 | def __new__(cls, *args: Any, **kwargs: Any) -> Bad:
| ^^^^^^^ PYI034 | ^^^^^^^ PYI034
20 | ... # Y034 "__new__" methods usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__new__", e.g. "def __new__(cls, *args: Any, **kwargs: Any) -> Self: ..." 22 | ... # Y034 "__new__" methods usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__new__", e.g. "def __new__(cls, *args: Any, **kwargs: Any) -> Self: ..."
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.py:34:9: PYI034 `__enter__` methods in classes like `Bad` usually return `self` at runtime PYI034.py:36:9: PYI034 `__enter__` methods in classes like `Bad` usually return `self` at runtime
| |
32 | ... # Y032 Prefer "object" to "Any" for the second parameter in "__ne__" methods 34 | ... # Y032 Prefer "object" to "Any" for the second parameter in "__ne__" methods
33 | 35 |
34 | def __enter__(self) -> Bad: 36 | def __enter__(self) -> Bad:
| ^^^^^^^^^ PYI034 | ^^^^^^^^^ PYI034
35 | ... # Y034 "__enter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__enter__", e.g. "def __enter__(self) -> Self: ..." 37 | ... # Y034 "__enter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__enter__", e.g. "def __enter__(self) -> Self: ..."
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.py:37:15: PYI034 `__aenter__` methods in classes like `Bad` usually return `self` at runtime PYI034.py:39:15: PYI034 `__aenter__` methods in classes like `Bad` usually return `self` at runtime
| |
35 | ... # Y034 "__enter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__enter__", e.g. "def __enter__(self) -> Self: ..." 37 | ... # Y034 "__enter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__enter__", e.g. "def __enter__(self) -> Self: ..."
36 | 38 |
37 | async def __aenter__(self) -> Bad: 39 | async def __aenter__(self) -> Bad:
| ^^^^^^^^^^ PYI034 | ^^^^^^^^^^ PYI034
38 | ... # Y034 "__aenter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__aenter__", e.g. "async def __aenter__(self) -> Self: ..." 40 | ... # Y034 "__aenter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__aenter__", e.g. "async def __aenter__(self) -> Self: ..."
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.py:40:9: PYI034 `__iadd__` methods in classes like `Bad` usually return `self` at runtime PYI034.py:42:9: PYI034 `__iadd__` methods in classes like `Bad` usually return `self` at runtime
| |
38 | ... # Y034 "__aenter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__aenter__", e.g. "async def __aenter__(self) -> Self: ..." 40 | ... # Y034 "__aenter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__aenter__", e.g. "async def __aenter__(self) -> Self: ..."
39 | 41 |
40 | def __iadd__(self, other: Bad) -> Bad: 42 | def __iadd__(self, other: Bad) -> Bad:
| ^^^^^^^^ PYI034 | ^^^^^^^^ PYI034
41 | ... # Y034 "__iadd__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__iadd__", e.g. "def __iadd__(self, other: Bad) -> Self: ..." 43 | ... # Y034 "__iadd__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__iadd__", e.g. "def __iadd__(self, other: Bad) -> Self: ..."
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.py:163:9: PYI034 `__iter__` methods in classes like `BadIterator1` usually return `self` at runtime PYI034.py:165:9: PYI034 `__iter__` methods in classes like `BadIterator1` usually return `self` at runtime
| |
162 | class BadIterator1(Iterator[int]): 164 | class BadIterator1(Iterator[int]):
163 | def __iter__(self) -> Iterator[int]: 165 | def __iter__(self) -> Iterator[int]:
| ^^^^^^^^ PYI034 | ^^^^^^^^ PYI034
164 | ... # Y034 "__iter__" methods in classes like "BadIterator1" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadIterator1.__iter__", e.g. "def __iter__(self) -> Self: ..." 166 | ... # Y034 "__iter__" methods in classes like "BadIterator1" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadIterator1.__iter__", e.g. "def __iter__(self) -> Self: ..."
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.py:170:9: PYI034 `__iter__` methods in classes like `BadIterator2` usually return `self` at runtime PYI034.py:172:9: PYI034 `__iter__` methods in classes like `BadIterator2` usually return `self` at runtime
| |
168 | typing.Iterator[int] 170 | typing.Iterator[int]
169 | ): # Y022 Use "collections.abc.Iterator[T]" instead of "typing.Iterator[T]" (PEP 585 syntax) 171 | ): # Y022 Use "collections.abc.Iterator[T]" instead of "typing.Iterator[T]" (PEP 585 syntax)
170 | def __iter__(self) -> Iterator[int]: 172 | def __iter__(self) -> Iterator[int]:
| ^^^^^^^^ PYI034 | ^^^^^^^^ PYI034
171 | ... # Y034 "__iter__" methods in classes like "BadIterator2" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadIterator2.__iter__", e.g. "def __iter__(self) -> Self: ..." 173 | ... # Y034 "__iter__" methods in classes like "BadIterator2" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadIterator2.__iter__", e.g. "def __iter__(self) -> Self: ..."
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.py:177:9: PYI034 `__iter__` methods in classes like `BadIterator3` usually return `self` at runtime PYI034.py:179:9: PYI034 `__iter__` methods in classes like `BadIterator3` usually return `self` at runtime
| |
175 | typing.Iterator[int] 177 | typing.Iterator[int]
176 | ): # Y022 Use "collections.abc.Iterator[T]" instead of "typing.Iterator[T]" (PEP 585 syntax) 178 | ): # Y022 Use "collections.abc.Iterator[T]" instead of "typing.Iterator[T]" (PEP 585 syntax)
177 | def __iter__(self) -> collections.abc.Iterator[int]: 179 | def __iter__(self) -> collections.abc.Iterator[int]:
| ^^^^^^^^ PYI034 | ^^^^^^^^ PYI034
178 | ... # Y034 "__iter__" methods in classes like "BadIterator3" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadIterator3.__iter__", e.g. "def __iter__(self) -> Self: ..." 180 | ... # Y034 "__iter__" methods in classes like "BadIterator3" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadIterator3.__iter__", e.g. "def __iter__(self) -> Self: ..."
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.py:183:9: PYI034 `__iter__` methods in classes like `BadIterator4` usually return `self` at runtime PYI034.py:185:9: PYI034 `__iter__` methods in classes like `BadIterator4` usually return `self` at runtime
| |
181 | class BadIterator4(Iterator[int]): 183 | class BadIterator4(Iterator[int]):
182 | # Note: *Iterable*, not *Iterator*, returned! 184 | # Note: *Iterable*, not *Iterator*, returned!
183 | def __iter__(self) -> Iterable[int]: 185 | def __iter__(self) -> Iterable[int]:
| ^^^^^^^^ PYI034 | ^^^^^^^^ PYI034
184 | ... # Y034 "__iter__" methods in classes like "BadIterator4" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadIterator4.__iter__", e.g. "def __iter__(self) -> Self: ..." 186 | ... # Y034 "__iter__" methods in classes like "BadIterator4" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadIterator4.__iter__", e.g. "def __iter__(self) -> Self: ..."
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.py:193:9: PYI034 `__aiter__` methods in classes like `BadAsyncIterator` usually return `self` at runtime PYI034.py:195:9: PYI034 `__aiter__` methods in classes like `BadAsyncIterator` usually return `self` at runtime
| |
192 | class BadAsyncIterator(collections.abc.AsyncIterator[str]): 194 | class BadAsyncIterator(collections.abc.AsyncIterator[str]):
193 | def __aiter__(self) -> typing.AsyncIterator[str]: 195 | def __aiter__(self) -> typing.AsyncIterator[str]:
| ^^^^^^^^^ PYI034 | ^^^^^^^^^ PYI034
194 | ... # Y034 "__aiter__" methods in classes like "BadAsyncIterator" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadAsyncIterator.__aiter__", e.g. "def __aiter__(self) -> Self: ..." # Y022 Use "collections.abc.AsyncIterator[T]" instead of "typing.AsyncIterator[T]" (PEP 585 syntax) 196 | ... # Y034 "__aiter__" methods in classes like "BadAsyncIterator" usually return "self" at runtime. Consider using "typing_extensions.Self" in "BadAsyncIterator.__aiter__", e.g. "def __aiter__(self) -> Self: ..." # Y022 Use "collections.abc.AsyncIterator[T]" instead of "typing.AsyncIterator[T]" (PEP 585 syntax)
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type

View file

@ -1,100 +1,100 @@
--- ---
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
--- ---
PYI034.pyi:18:9: PYI034 `__new__` methods in classes like `Bad` usually return `self` at runtime PYI034.pyi:20:9: PYI034 `__new__` methods in classes like `Bad` usually return `self` at runtime
| |
16 | object 18 | object
17 | ): # Y040 Do not inherit from "object" explicitly, as it is redundant in Python 3 19 | ): # Y040 Do not inherit from "object" explicitly, as it is redundant in Python 3
18 | def __new__( 20 | def __new__(
| ^^^^^^^ PYI034 | ^^^^^^^ PYI034
19 | cls, *args: Any, **kwargs: Any 21 | cls, *args: Any, **kwargs: Any
20 | ) -> Bad: ... # Y034 "__new__" methods usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__new__", e.g. "def __new__(cls, *args: Any, **kwargs: Any) -> Self: ..." 22 | ) -> Bad: ... # Y034 "__new__" methods usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__new__", e.g. "def __new__(cls, *args: Any, **kwargs: Any) -> Self: ..."
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.pyi:33:9: PYI034 `__enter__` methods in classes like `Bad` usually return `self` at runtime PYI034.pyi:35:9: PYI034 `__enter__` methods in classes like `Bad` usually return `self` at runtime
| |
31 | self, other: typing.Any 33 | self, other: typing.Any
32 | ) -> typing.Any: ... # Y032 Prefer "object" to "Any" for the second parameter in "__ne__" methods 34 | ) -> typing.Any: ... # Y032 Prefer "object" to "Any" for the second parameter in "__ne__" methods
33 | def __enter__( 35 | def __enter__(
| ^^^^^^^^^ PYI034 | ^^^^^^^^^ PYI034
34 | self, 36 | self,
35 | ) -> Bad: ... # Y034 "__enter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__enter__", e.g. "def __enter__(self) -> Self: ..." 37 | ) -> Bad: ... # Y034 "__enter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__enter__", e.g. "def __enter__(self) -> Self: ..."
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.pyi:36:15: PYI034 `__aenter__` methods in classes like `Bad` usually return `self` at runtime PYI034.pyi:38:15: PYI034 `__aenter__` methods in classes like `Bad` usually return `self` at runtime
| |
34 | self, 36 | self,
35 | ) -> Bad: ... # Y034 "__enter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__enter__", e.g. "def __enter__(self) -> Self: ..." 37 | ) -> Bad: ... # Y034 "__enter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__enter__", e.g. "def __enter__(self) -> Self: ..."
36 | async def __aenter__( 38 | async def __aenter__(
| ^^^^^^^^^^ PYI034 | ^^^^^^^^^^ PYI034
37 | self, 39 | self,
38 | ) -> Bad: ... # Y034 "__aenter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__aenter__", e.g. "async def __aenter__(self) -> Self: ..." 40 | ) -> Bad: ... # Y034 "__aenter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__aenter__", e.g. "async def __aenter__(self) -> Self: ..."
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.pyi:39:9: PYI034 `__iadd__` methods in classes like `Bad` usually return `self` at runtime PYI034.pyi:41:9: PYI034 `__iadd__` methods in classes like `Bad` usually return `self` at runtime
| |
37 | self, 39 | self,
38 | ) -> Bad: ... # Y034 "__aenter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__aenter__", e.g. "async def __aenter__(self) -> Self: ..." 40 | ) -> Bad: ... # Y034 "__aenter__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__aenter__", e.g. "async def __aenter__(self) -> Self: ..."
39 | def __iadd__( 41 | def __iadd__(
| ^^^^^^^^ PYI034 | ^^^^^^^^ PYI034
40 | self, other: Bad 42 | self, other: Bad
41 | ) -> Bad: ... # Y034 "__iadd__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__iadd__", e.g. "def __iadd__(self, other: Bad) -> Self: ..." 43 | ) -> Bad: ... # Y034 "__iadd__" methods in classes like "Bad" usually return "self" at runtime. Consider using "typing_extensions.Self" in "Bad.__iadd__", e.g. "def __iadd__(self, other: Bad) -> Self: ..."
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.pyi:102:9: PYI034 `__iter__` methods in classes like `BadIterator1` usually return `self` at runtime PYI034.pyi:104:9: PYI034 `__iter__` methods in classes like `BadIterator1` usually return `self` at runtime
| |
101 | class BadIterator1(Iterator[int]): 103 | class BadIterator1(Iterator[int]):
102 | def __iter__( 104 | def __iter__(
| ^^^^^^^^ PYI034 | ^^^^^^^^ PYI034
103 | self, 105 | self,
104 | ) -> Iterator[ 106 | ) -> Iterator[
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.pyi:111:9: PYI034 `__iter__` methods in classes like `BadIterator2` usually return `self` at runtime PYI034.pyi:113:9: PYI034 `__iter__` methods in classes like `BadIterator2` usually return `self` at runtime
| |
109 | typing.Iterator[int] 111 | typing.Iterator[int]
110 | ): # Y022 Use "collections.abc.Iterator[T]" instead of "typing.Iterator[T]" (PEP 585 syntax) 112 | ): # Y022 Use "collections.abc.Iterator[T]" instead of "typing.Iterator[T]" (PEP 585 syntax)
111 | def __iter__( 113 | def __iter__(
| ^^^^^^^^ PYI034 | ^^^^^^^^ PYI034
112 | self, 114 | self,
113 | ) -> Iterator[ 115 | ) -> Iterator[
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.pyi:120:9: PYI034 `__iter__` methods in classes like `BadIterator3` usually return `self` at runtime PYI034.pyi:122:9: PYI034 `__iter__` methods in classes like `BadIterator3` usually return `self` at runtime
| |
118 | typing.Iterator[int] 120 | typing.Iterator[int]
119 | ): # Y022 Use "collections.abc.Iterator[T]" instead of "typing.Iterator[T]" (PEP 585 syntax) 121 | ): # Y022 Use "collections.abc.Iterator[T]" instead of "typing.Iterator[T]" (PEP 585 syntax)
120 | def __iter__( 122 | def __iter__(
| ^^^^^^^^ PYI034 | ^^^^^^^^ PYI034
121 | self, 123 | self,
122 | ) -> collections.abc.Iterator[ 124 | ) -> collections.abc.Iterator[
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.pyi:128:9: PYI034 `__iter__` methods in classes like `BadIterator4` usually return `self` at runtime PYI034.pyi:130:9: PYI034 `__iter__` methods in classes like `BadIterator4` usually return `self` at runtime
| |
126 | class BadIterator4(Iterator[int]): 128 | class BadIterator4(Iterator[int]):
127 | # Note: *Iterable*, not *Iterator*, returned! 129 | # Note: *Iterable*, not *Iterator*, returned!
128 | def __iter__( 130 | def __iter__(
| ^^^^^^^^ PYI034 | ^^^^^^^^ PYI034
129 | self, 131 | self,
130 | ) -> Iterable[ 132 | ) -> Iterable[
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type
PYI034.pyi:142:9: PYI034 `__aiter__` methods in classes like `BadAsyncIterator` usually return `self` at runtime PYI034.pyi:144:9: PYI034 `__aiter__` methods in classes like `BadAsyncIterator` usually return `self` at runtime
| |
141 | class BadAsyncIterator(collections.abc.AsyncIterator[str]): 143 | class BadAsyncIterator(collections.abc.AsyncIterator[str]):
142 | def __aiter__( 144 | def __aiter__(
| ^^^^^^^^^ PYI034 | ^^^^^^^^^ PYI034
143 | self, 145 | self,
144 | ) -> typing.AsyncIterator[ 146 | ) -> typing.AsyncIterator[
| |
= help: Consider using `typing_extensions.Self` as return type = help: Consider using `typing_extensions.Self` as return type