Skip to content

Commit

Permalink
Add PYI034 for flake8-pyi plugin (#4764)
Browse files Browse the repository at this point in the history
  • Loading branch information
qdegraaf committed Jun 2, 2023
1 parent c68686b commit fcbf5c3
Show file tree
Hide file tree
Showing 14 changed files with 918 additions and 2 deletions.
280 changes: 280 additions & 0 deletions crates/ruff/resources/test/fixtures/flake8_pyi/PYI034.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
# flags: --extend-ignore=Y023

import abc
import builtins
import collections.abc
import typing
from abc import abstractmethod
from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator
from typing import Any, overload

import typing_extensions
from _typeshed import Self
from typing_extensions import final


class Bad(
object
): # Y040 Do not inherit from "object" explicitly, as it is redundant in Python 3
def __new__(cls, *args: Any, **kwargs: Any) -> 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: ..."

def __repr__(self) -> str:
... # Y029 Defining __repr__ or __str__ in a stub is almost always redundant

def __str__(self) -> builtins.str:
... # Y029 Defining __repr__ or __str__ in a stub is almost always redundant

def __eq__(self, other: Any) -> bool:
... # Y032 Prefer "object" to "Any" for the second parameter in "__eq__" methods

def __ne__(self, other: typing.Any) -> typing.Any:
... # Y032 Prefer "object" to "Any" for the second parameter in "__ne__" methods

def __enter__(self) -> 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: ..."

async def __aenter__(self) -> 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: ..."

def __iadd__(self, other: Bad) -> 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: ..."


class AlsoBad(int, builtins.object):
... # Y040 Do not inherit from "object" explicitly, as it is redundant in Python 3


class Good:
def __new__(cls: type[Self], *args: Any, **kwargs: Any) -> Self:
...

@abstractmethod
def __str__(self) -> str:
...

@abc.abstractmethod
def __repr__(self) -> str:
...

def __eq__(self, other: object) -> bool:
...

def __ne__(self, obj: object) -> int:
...

def __enter__(self: Self) -> Self:
...

async def __aenter__(self: Self) -> Self:
...

def __ior__(self: Self, other: Self) -> Self:
...


class Fine:
@overload
def __new__(cls, foo: int) -> FineSubclass:
...

@overload
def __new__(cls, *args: Any, **kwargs: Any) -> Fine:
...

@abc.abstractmethod
def __str__(self) -> str:
...

@abc.abstractmethod
def __repr__(self) -> str:
...

def __eq__(self, other: Any, strange_extra_arg: list[str]) -> Any:
...

def __ne__(self, *, kw_only_other: Any) -> bool:
...

def __enter__(self) -> None:
...

async def __aenter__(self) -> bool:
...


class FineSubclass(Fine):
...


class StrangeButAcceptable(str):
@typing_extensions.overload
def __new__(cls, foo: int) -> StrangeButAcceptableSubclass:
...

@typing_extensions.overload
def __new__(cls, *args: Any, **kwargs: Any) -> StrangeButAcceptable:
...

def __str__(self) -> StrangeButAcceptable:
...

def __repr__(self) -> StrangeButAcceptable:
...


class StrangeButAcceptableSubclass(StrangeButAcceptable):
...


class FineAndDandy:
def __str__(self, weird_extra_arg) -> str:
...

def __repr__(self, weird_extra_arg_with_default=...) -> str:
...


@final
class WillNotBeSubclassed:
def __new__(cls, *args: Any, **kwargs: Any) -> WillNotBeSubclassed:
...

def __enter__(self) -> WillNotBeSubclassed:
...

async def __aenter__(self) -> WillNotBeSubclassed:
...


# we don't emit an error for these; out of scope for a linter
class InvalidButPluginDoesNotCrash:
def __new__() -> InvalidButPluginDoesNotCrash:
...

def __enter__() -> InvalidButPluginDoesNotCrash:
...

async def __aenter__() -> InvalidButPluginDoesNotCrash:
...


class BadIterator1(Iterator[int]):
def __iter__(self) -> Iterator[int]:
... # 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: ..."


class BadIterator2(
typing.Iterator[int]
): # Y022 Use "collections.abc.Iterator[T]" instead of "typing.Iterator[T]" (PEP 585 syntax)
def __iter__(self) -> Iterator[int]:
... # 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: ..."


class BadIterator3(
typing.Iterator[int]
): # Y022 Use "collections.abc.Iterator[T]" instead of "typing.Iterator[T]" (PEP 585 syntax)
def __iter__(self) -> collections.abc.Iterator[int]:
... # 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: ..."


class BadIterator4(Iterator[int]):
# Note: *Iterable*, not *Iterator*, returned!
def __iter__(self) -> Iterable[int]:
... # 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: ..."


class IteratorReturningIterable:
def __iter__(self) -> Iterable[str]:
... # Y045 "__iter__" methods should return an Iterator, not an Iterable


class BadAsyncIterator(collections.abc.AsyncIterator[str]):
def __aiter__(self) -> typing.AsyncIterator[str]:
... # 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)


class AsyncIteratorReturningAsyncIterable:
def __aiter__(self) -> AsyncIterable[str]:
... # Y045 "__aiter__" methods should return an AsyncIterator, not an AsyncIterable


class Abstract(Iterator[str]):
@abstractmethod
def __iter__(self) -> Iterator[str]:
...

@abstractmethod
def __enter__(self) -> Abstract:
...

@abstractmethod
async def __aenter__(self) -> Abstract:
...


class GoodIterator(Iterator[str]):
def __iter__(self: Self) -> Self:
...


class GoodAsyncIterator(AsyncIterator[int]):
def __aiter__(self: Self) -> Self:
...


class DoesNotInheritFromIterator:
def __iter__(self) -> DoesNotInheritFromIterator:
...


class Unannotated:
def __new__(cls, *args, **kwargs):
...

def __iter__(self):
...

def __aiter__(self):
...

async def __aenter__(self):
...

def __repr__(self):
...

def __str__(self):
...

def __eq__(self):
...

def __ne__(self):
...

def __iadd__(self):
...

def __ior__(self):
...


def __repr__(self) -> str:
...


def __str__(self) -> str:
...


def __eq__(self, other: Any) -> bool:
...


def __ne__(self, other: Any) -> bool:
...


def __imul__(self, other: Any) -> list[str]:
...

0 comments on commit fcbf5c3

Please sign in to comment.