Broaden appropriate flake8-pyi rules to check non-stub code too (#6297)
Of the rules that flake8-pyi enforces for `.pyi` type stubs, many of them equally make sense to check in normal runtime code with type annotations. Broaden these rules to check all files: PYI013 ellipsis-in-non-empty-class-body PYI016 duplicate-union-member PYI018 unused-private-type-var PYI019 custom-type-var-return-type PYI024 collections-named-tuple PYI025 unaliased-collections-abc-set-import PYI030 unnecessary-literal-union PYI032 any-eq-ne-annotation PYI034 non-self-return-type PYI036 bad-exit-annotation PYI041 redundant-numeric-union PYI042 snake-case-type-alias PYI043 t-suffixed-type-alias PYI045 iter-method-return-iterable PYI046 unused-private-protocol PYI047 unused-private-type-alias PYI049 unused-private-typed-dict PYI050 no-return-argument-annotation-in-stub (Python ≥ 3.11) PYI051 redundant-literal-union PYI056 unsupported-method-call-on-all The other rules are stub-specific and remain enabled only in `.pyi` files. PYI001 unprefixed-type-param PYI002 complex-if-statement-in-stub PYI003 unrecognized-version-info-check PYI004 patch-version-comparison PYI005 wrong-tuple-length-version-comparison (could make sense to broaden, see https://github.com/astral-sh/ruff/pull/6297#issuecomment-1663314807) PYI006 bad-version-info-comparison (same) PYI007 unrecognized-platform-check PYI008 unrecognized-platform-name PYI009 pass-statement-stub-body PYI010 non-empty-stub-body PYI011 typed-argument-default-in-stub PYI012 pass-in-class-body PYI014 argument-default-in-stub PYI015 assignment-default-in-stub PYI017 complex-assignment-in-stub PYI020 quoted-annotation-in-stub PYI021 docstring-in-stub PYI026 type-alias-without-annotation (could make sense to broaden, but gives many false positives on runtime code as currently implemented) PYI029 str-or-repr-defined-in-stub PYI033 type-comment-in-stub PYI035 unassigned-special-variable-in-stub PYI044 future-annotations-in-stub PYI048 stub-body-multiple-statements PYI052 unannotated-assignment-in-stub PYI053 string-or-bytes-too-long PYI054 numeric-literal-too-long Signed-off-by: Anders Kaseorg <andersk@mit.edu>
This commit is contained in:
@@ -4,14 +4,14 @@ _S = TypeVar("_S", bound=BadClass)
|
||||
_S2 = TypeVar("_S2", BadClass, GoodClass)
|
||||
|
||||
class BadClass:
|
||||
def __new__(cls: type[_S], *args: str, **kwargs: int) -> _S: ... # Ok
|
||||
def __new__(cls: type[_S], *args: str, **kwargs: int) -> _S: ... # PYI019
|
||||
|
||||
|
||||
def bad_instance_method(self: _S, arg: bytes) -> _S: ... # Ok
|
||||
def bad_instance_method(self: _S, arg: bytes) -> _S: ... # PYI019
|
||||
|
||||
|
||||
@classmethod
|
||||
def bad_class_method(cls: type[_S], arg: int) -> _S: ... # Ok
|
||||
def bad_class_method(cls: type[_S], arg: int) -> _S: ... # PYI019
|
||||
|
||||
|
||||
@classmethod
|
||||
@@ -32,10 +32,10 @@ class GoodClass:
|
||||
|
||||
# Python > 3.12
|
||||
class PEP695BadDunderNew[T]:
|
||||
def __new__[S](cls: type[S], *args: Any, ** kwargs: Any) -> S: ... # Ok
|
||||
def __new__[S](cls: type[S], *args: Any, ** kwargs: Any) -> S: ... # PYI019
|
||||
|
||||
|
||||
def generic_instance_method[S](self: S) -> S: ... # Ok
|
||||
def generic_instance_method[S](self: S) -> S: ... # PYI019
|
||||
|
||||
|
||||
class PEP695GoodDunderNew[T]:
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import collections
|
||||
|
||||
person: collections.namedtuple # OK
|
||||
person: collections.namedtuple # Y024 Use "typing.NamedTuple" instead of "collections.namedtuple"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
person: namedtuple # OK
|
||||
person: namedtuple # Y024 Use "typing.NamedTuple" instead of "collections.namedtuple"
|
||||
|
||||
person = namedtuple("Person", ["name", "age"]) # OK
|
||||
person = namedtuple(
|
||||
"Person", ["name", "age"]
|
||||
) # Y024 Use "typing.NamedTuple" instead of "collections.namedtuple"
|
||||
|
||||
@@ -1,24 +1,38 @@
|
||||
import typing
|
||||
import typing_extensions
|
||||
from typing import Literal
|
||||
# Shouldn't emit for any cases in the non-stub file for compatibility with flake8-pyi.
|
||||
# Note that this rule could be applied here in the future.
|
||||
|
||||
# Shouldn't affect non-union field types.
|
||||
field1: Literal[1] # OK
|
||||
field2: Literal[1] | Literal[2] # OK
|
||||
|
||||
def func1(arg1: Literal[1] | Literal[2]): # OK
|
||||
# Should emit for duplicate field types.
|
||||
field2: Literal[1] | Literal[2] # Error
|
||||
|
||||
# Should emit for union types in arguments.
|
||||
def func1(arg1: Literal[1] | Literal[2]): # Error
|
||||
print(arg1)
|
||||
|
||||
|
||||
def func2() -> Literal[1] | Literal[2]: # OK
|
||||
# Should emit for unions in return types.
|
||||
def func2() -> Literal[1] | Literal[2]: # Error
|
||||
return "my Literal[1]ing"
|
||||
|
||||
|
||||
field3: Literal[1] | Literal[2] | str # OK
|
||||
field4: str | Literal[1] | Literal[2] # OK
|
||||
field5: Literal[1] | str | Literal[2] # OK
|
||||
field6: Literal[1] | bool | Literal[2] | str # OK
|
||||
field7 = Literal[1] | Literal[2] # OK
|
||||
field8: Literal[1] | (Literal[2] | str) # OK
|
||||
field9: Literal[1] | (Literal[2] | str) # OK
|
||||
field10: (Literal[1] | str) | Literal[2] # OK
|
||||
field11: dict[Literal[1] | Literal[2], str] # OK
|
||||
# Should emit in longer unions, even if not directly adjacent.
|
||||
field3: Literal[1] | Literal[2] | str # Error
|
||||
field4: str | Literal[1] | Literal[2] # Error
|
||||
field5: Literal[1] | str | Literal[2] # Error
|
||||
field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
|
||||
# Should emit for non-type unions.
|
||||
field7 = Literal[1] | Literal[2] # Error
|
||||
|
||||
# Should emit for parenthesized unions.
|
||||
field8: Literal[1] | (Literal[2] | str) # Error
|
||||
|
||||
# Should handle user parentheses when fixing.
|
||||
field9: Literal[1] | (Literal[2] | str) # Error
|
||||
field10: (Literal[1] | str) | Literal[2] # Error
|
||||
|
||||
# Should emit for union in generic parent type.
|
||||
field11: dict[Literal[1] | Literal[2], str] # Error
|
||||
|
||||
@@ -3,8 +3,8 @@ import typing
|
||||
|
||||
|
||||
class Bad:
|
||||
def __eq__(self, other: Any) -> bool: ... # Fine because not a stub file
|
||||
def __ne__(self, other: typing.Any) -> typing.Any: ... # Fine because not a stub file
|
||||
def __eq__(self, other: Any) -> bool: ... # Y032
|
||||
def __ne__(self, other: typing.Any) -> typing.Any: ... # Y032
|
||||
|
||||
|
||||
class Good:
|
||||
|
||||
@@ -9,16 +9,16 @@ from typing import (
|
||||
|
||||
just_literals_pipe_union: TypeAlias = (
|
||||
Literal[True] | Literal["idk"]
|
||||
) # not PYI042 (not a stubfile)
|
||||
) # PYI042, since not camel case
|
||||
PublicAliasT: TypeAlias = str | int
|
||||
PublicAliasT2: TypeAlias = Union[str, bytes]
|
||||
_ABCDEFGHIJKLMNOPQRST: TypeAlias = typing.Any
|
||||
_PrivateAliasS: TypeAlias = Literal["I", "guess", "this", "is", "okay"]
|
||||
_PrivateAliasS2: TypeAlias = Annotated[str, "also okay"]
|
||||
|
||||
snake_case_alias1: TypeAlias = str | int # not PYI042 (not a stubfile)
|
||||
_snake_case_alias2: TypeAlias = Literal["whatever"] # not PYI042 (not a stubfile)
|
||||
Snake_case_alias: TypeAlias = int | float # not PYI042 (not a stubfile)
|
||||
snake_case_alias1: TypeAlias = str | int # PYI042, since not camel case
|
||||
_snake_case_alias2: TypeAlias = Literal["whatever"] # PYI042, since not camel case
|
||||
Snake_case_alias: TypeAlias = int | float # PYI042, since not camel case
|
||||
|
||||
# check that this edge case doesn't crash
|
||||
_: TypeAlias = str | int
|
||||
|
||||
@@ -7,11 +7,11 @@ from typing import (
|
||||
Literal,
|
||||
)
|
||||
|
||||
_PrivateAliasT: TypeAlias = str | int # not PYI043 (not a stubfile)
|
||||
_PrivateAliasT2: TypeAlias = typing.Any # not PYI043 (not a stubfile)
|
||||
_PrivateAliasT: TypeAlias = str | int # PYI043, since this ends in a T
|
||||
_PrivateAliasT2: TypeAlias = typing.Any # PYI043, since this ends in a T
|
||||
_PrivateAliasT3: TypeAlias = Literal[
|
||||
"not", "a", "chance"
|
||||
] # not PYI043 (not a stubfile)
|
||||
] # PYI043, since this ends in a T
|
||||
just_literals_pipe_union: TypeAlias = Literal[True] | Literal["idk"]
|
||||
PublicAliasT: TypeAlias = str | int
|
||||
PublicAliasT2: TypeAlias = Union[str, bytes]
|
||||
|
||||
@@ -56,13 +56,11 @@ pub(crate) fn bindings(checker: &mut Checker) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.is_stub {
|
||||
if checker.enabled(Rule::UnaliasedCollectionsAbcSetImport) {
|
||||
if let Some(diagnostic) =
|
||||
flake8_pyi::rules::unaliased_collections_abc_set_import(checker, binding)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
}
|
||||
if checker.enabled(Rule::UnaliasedCollectionsAbcSetImport) {
|
||||
if let Some(diagnostic) =
|
||||
flake8_pyi::rules::unaliased_collections_abc_set_import(checker, binding)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,19 +218,17 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
|
||||
}
|
||||
}
|
||||
|
||||
if checker.is_stub {
|
||||
if checker.enabled(Rule::UnusedPrivateTypeVar) {
|
||||
flake8_pyi::rules::unused_private_type_var(checker, scope, &mut diagnostics);
|
||||
}
|
||||
if checker.enabled(Rule::UnusedPrivateProtocol) {
|
||||
flake8_pyi::rules::unused_private_protocol(checker, scope, &mut diagnostics);
|
||||
}
|
||||
if checker.enabled(Rule::UnusedPrivateTypeAlias) {
|
||||
flake8_pyi::rules::unused_private_type_alias(checker, scope, &mut diagnostics);
|
||||
}
|
||||
if checker.enabled(Rule::UnusedPrivateTypedDict) {
|
||||
flake8_pyi::rules::unused_private_typed_dict(checker, scope, &mut diagnostics);
|
||||
}
|
||||
if checker.enabled(Rule::UnusedPrivateTypeVar) {
|
||||
flake8_pyi::rules::unused_private_type_var(checker, scope, &mut diagnostics);
|
||||
}
|
||||
if checker.enabled(Rule::UnusedPrivateProtocol) {
|
||||
flake8_pyi::rules::unused_private_protocol(checker, scope, &mut diagnostics);
|
||||
}
|
||||
if checker.enabled(Rule::UnusedPrivateTypeAlias) {
|
||||
flake8_pyi::rules::unused_private_type_alias(checker, scope, &mut diagnostics);
|
||||
}
|
||||
if checker.enabled(Rule::UnusedPrivateTypedDict) {
|
||||
flake8_pyi::rules::unused_private_typed_dict(checker, scope, &mut diagnostics);
|
||||
}
|
||||
|
||||
if matches!(
|
||||
|
||||
@@ -30,8 +30,8 @@ pub(crate) fn definitions(checker: &mut Checker) {
|
||||
Rule::MissingTypeKwargs,
|
||||
Rule::MissingTypeSelf,
|
||||
]);
|
||||
let enforce_stubs = checker.is_stub
|
||||
&& checker.any_enabled(&[Rule::DocstringInStub, Rule::IterMethodReturnIterable]);
|
||||
let enforce_stubs = checker.is_stub && checker.enabled(Rule::DocstringInStub);
|
||||
let enforce_stubs_and_runtime = checker.enabled(Rule::IterMethodReturnIterable);
|
||||
let enforce_docstrings = checker.any_enabled(&[
|
||||
Rule::BlankLineAfterLastSection,
|
||||
Rule::BlankLineAfterSummary,
|
||||
@@ -81,7 +81,7 @@ pub(crate) fn definitions(checker: &mut Checker) {
|
||||
Rule::UndocumentedPublicPackage,
|
||||
]);
|
||||
|
||||
if !enforce_annotations && !enforce_docstrings && !enforce_stubs {
|
||||
if !enforce_annotations && !enforce_docstrings && !enforce_stubs && !enforce_stubs_and_runtime {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -141,6 +141,8 @@ pub(crate) fn definitions(checker: &mut Checker) {
|
||||
if checker.enabled(Rule::DocstringInStub) {
|
||||
flake8_pyi::rules::docstring_in_stubs(checker, docstring);
|
||||
}
|
||||
}
|
||||
if enforce_stubs_and_runtime {
|
||||
if checker.enabled(Rule::IterMethodReturnIterable) {
|
||||
flake8_pyi::rules::iter_method_return_iterable(checker, definition);
|
||||
}
|
||||
|
||||
@@ -159,10 +159,8 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
||||
if checker.enabled(Rule::NumpyDeprecatedFunction) {
|
||||
numpy::rules::deprecated_function(checker, expr);
|
||||
}
|
||||
if checker.is_stub {
|
||||
if checker.enabled(Rule::CollectionsNamedTuple) {
|
||||
flake8_pyi::rules::collections_named_tuple(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::CollectionsNamedTuple) {
|
||||
flake8_pyi::rules::collections_named_tuple(checker, expr);
|
||||
}
|
||||
|
||||
// Ex) List[...]
|
||||
@@ -323,10 +321,8 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
||||
if checker.enabled(Rule::PrivateMemberAccess) {
|
||||
flake8_self::rules::private_member_access(checker, expr);
|
||||
}
|
||||
if checker.is_stub {
|
||||
if checker.enabled(Rule::CollectionsNamedTuple) {
|
||||
flake8_pyi::rules::collections_named_tuple(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::CollectionsNamedTuple) {
|
||||
flake8_pyi::rules::collections_named_tuple(checker, expr);
|
||||
}
|
||||
pandas_vet::rules::attr(checker, attr, value, expr);
|
||||
}
|
||||
@@ -868,7 +864,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
||||
if checker.enabled(Rule::DjangoLocalsInRenderFunction) {
|
||||
flake8_django::rules::locals_in_render_function(checker, call);
|
||||
}
|
||||
if checker.is_stub && checker.enabled(Rule::UnsupportedMethodCallOnAll) {
|
||||
if checker.enabled(Rule::UnsupportedMethodCallOnAll) {
|
||||
flake8_pyi::rules::unsupported_method_call_on_all(checker, func);
|
||||
}
|
||||
}
|
||||
@@ -1079,35 +1075,33 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
||||
);
|
||||
}
|
||||
}
|
||||
if checker.is_stub {
|
||||
if checker.enabled(Rule::DuplicateUnionMember)
|
||||
&& checker.semantic.in_type_definition()
|
||||
// Avoid duplicate checks if the parent is an `|`
|
||||
&& !matches!(
|
||||
checker.semantic.expr_parent(),
|
||||
Some(Expr::BinOp(ast::ExprBinOp { op: Operator::BitOr, ..}))
|
||||
)
|
||||
{
|
||||
flake8_pyi::rules::duplicate_union_member(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::UnnecessaryLiteralUnion)
|
||||
// Avoid duplicate checks if the parent is an `|`
|
||||
&& !matches!(
|
||||
checker.semantic.expr_parent(),
|
||||
Some(Expr::BinOp(ast::ExprBinOp { op: Operator::BitOr, ..}))
|
||||
)
|
||||
{
|
||||
flake8_pyi::rules::unnecessary_literal_union(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::RedundantLiteralUnion)
|
||||
// Avoid duplicate checks if the parent is an `|`
|
||||
&& !matches!(
|
||||
checker.semantic.expr_parent(),
|
||||
Some(Expr::BinOp(ast::ExprBinOp { op: Operator::BitOr, ..}))
|
||||
)
|
||||
{
|
||||
flake8_pyi::rules::redundant_literal_union(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::DuplicateUnionMember)
|
||||
&& checker.semantic.in_type_definition()
|
||||
// Avoid duplicate checks if the parent is an `|`
|
||||
&& !matches!(
|
||||
checker.semantic.expr_parent(),
|
||||
Some(Expr::BinOp(ast::ExprBinOp { op: Operator::BitOr, ..}))
|
||||
)
|
||||
{
|
||||
flake8_pyi::rules::duplicate_union_member(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::UnnecessaryLiteralUnion)
|
||||
// Avoid duplicate checks if the parent is an `|`
|
||||
&& !matches!(
|
||||
checker.semantic.expr_parent(),
|
||||
Some(Expr::BinOp(ast::ExprBinOp { op: Operator::BitOr, ..}))
|
||||
)
|
||||
{
|
||||
flake8_pyi::rules::unnecessary_literal_union(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::RedundantLiteralUnion)
|
||||
// Avoid duplicate checks if the parent is an `|`
|
||||
&& !matches!(
|
||||
checker.semantic.expr_parent(),
|
||||
Some(Expr::BinOp(ast::ExprBinOp { op: Operator::BitOr, ..}))
|
||||
)
|
||||
{
|
||||
flake8_pyi::rules::redundant_literal_union(checker, expr);
|
||||
}
|
||||
}
|
||||
Expr::UnaryOp(ast::ExprUnaryOp {
|
||||
|
||||
@@ -143,47 +143,51 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
||||
if checker.enabled(Rule::StubBodyMultipleStatements) {
|
||||
flake8_pyi::rules::stub_body_multiple_statements(checker, stmt, body);
|
||||
}
|
||||
if checker.enabled(Rule::AnyEqNeAnnotation) {
|
||||
flake8_pyi::rules::any_eq_ne_annotation(checker, name, parameters);
|
||||
}
|
||||
if checker.enabled(Rule::NonSelfReturnType) {
|
||||
flake8_pyi::rules::non_self_return_type(
|
||||
checker,
|
||||
stmt,
|
||||
name,
|
||||
decorator_list,
|
||||
returns.as_ref().map(AsRef::as_ref),
|
||||
parameters,
|
||||
stmt.is_async_function_def_stmt(),
|
||||
);
|
||||
}
|
||||
if checker.enabled(Rule::CustomTypeVarReturnType) {
|
||||
flake8_pyi::rules::custom_type_var_return_type(
|
||||
checker,
|
||||
name,
|
||||
decorator_list,
|
||||
returns.as_ref().map(AsRef::as_ref),
|
||||
parameters,
|
||||
type_params.as_ref(),
|
||||
);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::AnyEqNeAnnotation) {
|
||||
flake8_pyi::rules::any_eq_ne_annotation(checker, name, parameters);
|
||||
}
|
||||
if checker.enabled(Rule::NonSelfReturnType) {
|
||||
flake8_pyi::rules::non_self_return_type(
|
||||
checker,
|
||||
stmt,
|
||||
name,
|
||||
decorator_list,
|
||||
returns.as_ref().map(AsRef::as_ref),
|
||||
parameters,
|
||||
stmt.is_async_function_def_stmt(),
|
||||
);
|
||||
}
|
||||
if checker.enabled(Rule::CustomTypeVarReturnType) {
|
||||
flake8_pyi::rules::custom_type_var_return_type(
|
||||
checker,
|
||||
name,
|
||||
decorator_list,
|
||||
returns.as_ref().map(AsRef::as_ref),
|
||||
parameters,
|
||||
type_params.as_ref(),
|
||||
);
|
||||
}
|
||||
if checker.is_stub {
|
||||
if checker.enabled(Rule::StrOrReprDefinedInStub) {
|
||||
flake8_pyi::rules::str_or_repr_defined_in_stub(checker, stmt);
|
||||
}
|
||||
}
|
||||
if checker.is_stub || checker.settings.target_version >= PythonVersion::Py311 {
|
||||
if checker.enabled(Rule::NoReturnArgumentAnnotationInStub) {
|
||||
flake8_pyi::rules::no_return_argument_annotation(checker, parameters);
|
||||
}
|
||||
if checker.enabled(Rule::BadExitAnnotation) {
|
||||
flake8_pyi::rules::bad_exit_annotation(
|
||||
checker,
|
||||
stmt.is_async_function_def_stmt(),
|
||||
name,
|
||||
parameters,
|
||||
);
|
||||
}
|
||||
if checker.enabled(Rule::RedundantNumericUnion) {
|
||||
flake8_pyi::rules::redundant_numeric_union(checker, parameters);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::BadExitAnnotation) {
|
||||
flake8_pyi::rules::bad_exit_annotation(
|
||||
checker,
|
||||
stmt.is_async_function_def_stmt(),
|
||||
name,
|
||||
parameters,
|
||||
);
|
||||
}
|
||||
if checker.enabled(Rule::RedundantNumericUnion) {
|
||||
flake8_pyi::rules::redundant_numeric_union(checker, parameters);
|
||||
}
|
||||
if checker.enabled(Rule::DunderFunctionName) {
|
||||
if let Some(diagnostic) = pep8_naming::rules::dunder_function_name(
|
||||
@@ -470,9 +474,9 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
||||
if checker.enabled(Rule::PassInClassBody) {
|
||||
flake8_pyi::rules::pass_in_class_body(checker, stmt, body);
|
||||
}
|
||||
if checker.enabled(Rule::EllipsisInNonEmptyClassBody) {
|
||||
flake8_pyi::rules::ellipsis_in_non_empty_class_body(checker, stmt, body);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::EllipsisInNonEmptyClassBody) {
|
||||
flake8_pyi::rules::ellipsis_in_non_empty_class_body(checker, stmt, body);
|
||||
}
|
||||
if checker.enabled(Rule::PytestIncorrectMarkParenthesesStyle) {
|
||||
flake8_pytest_style::rules::marks(checker, decorator_list);
|
||||
@@ -1407,13 +1411,13 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
||||
);
|
||||
}
|
||||
}
|
||||
if checker.semantic.match_typing_expr(annotation, "TypeAlias") {
|
||||
if checker.enabled(Rule::SnakeCaseTypeAlias) {
|
||||
flake8_pyi::rules::snake_case_type_alias(checker, target);
|
||||
}
|
||||
if checker.enabled(Rule::TSuffixedTypeAlias) {
|
||||
flake8_pyi::rules::t_suffixed_type_alias(checker, target);
|
||||
}
|
||||
}
|
||||
if checker.semantic.match_typing_expr(annotation, "TypeAlias") {
|
||||
if checker.enabled(Rule::SnakeCaseTypeAlias) {
|
||||
flake8_pyi::rules::snake_case_type_alias(checker, target);
|
||||
}
|
||||
if checker.enabled(Rule::TSuffixedTypeAlias) {
|
||||
flake8_pyi::rules::t_suffixed_type_alias(checker, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,149 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI013.py:3:5: PYI013 [*] Non-empty class body must not contain `...`
|
||||
|
|
||||
1 | class OneAttributeClass:
|
||||
2 | value: int
|
||||
3 | ...
|
||||
| ^^^ PYI013
|
||||
|
|
||||
= help: Remove unnecessary `...`
|
||||
|
||||
ℹ Fix
|
||||
1 1 | class OneAttributeClass:
|
||||
2 2 | value: int
|
||||
3 |- ...
|
||||
4 3 |
|
||||
5 4 |
|
||||
6 5 | class OneAttributeClass2:
|
||||
|
||||
PYI013.py:7:5: PYI013 [*] Non-empty class body must not contain `...`
|
||||
|
|
||||
6 | class OneAttributeClass2:
|
||||
7 | ...
|
||||
| ^^^ PYI013
|
||||
8 | value: int
|
||||
|
|
||||
= help: Remove unnecessary `...`
|
||||
|
||||
ℹ Fix
|
||||
4 4 |
|
||||
5 5 |
|
||||
6 6 | class OneAttributeClass2:
|
||||
7 |- ...
|
||||
8 7 | value: int
|
||||
9 8 |
|
||||
10 9 |
|
||||
|
||||
PYI013.py:12:5: PYI013 [*] Non-empty class body must not contain `...`
|
||||
|
|
||||
11 | class TwoEllipsesClass:
|
||||
12 | ...
|
||||
| ^^^ PYI013
|
||||
13 | ...
|
||||
|
|
||||
= help: Remove unnecessary `...`
|
||||
|
||||
ℹ Fix
|
||||
10 10 |
|
||||
11 11 | class TwoEllipsesClass:
|
||||
12 12 | ...
|
||||
13 |- ...
|
||||
14 13 |
|
||||
15 14 |
|
||||
16 15 | class DocstringClass:
|
||||
|
||||
PYI013.py:13:5: PYI013 [*] Non-empty class body must not contain `...`
|
||||
|
|
||||
11 | class TwoEllipsesClass:
|
||||
12 | ...
|
||||
13 | ...
|
||||
| ^^^ PYI013
|
||||
|
|
||||
= help: Remove unnecessary `...`
|
||||
|
||||
ℹ Fix
|
||||
10 10 |
|
||||
11 11 | class TwoEllipsesClass:
|
||||
12 12 | ...
|
||||
13 |- ...
|
||||
14 13 |
|
||||
15 14 |
|
||||
16 15 | class DocstringClass:
|
||||
|
||||
PYI013.py:21:5: PYI013 [*] Non-empty class body must not contain `...`
|
||||
|
|
||||
19 | """
|
||||
20 |
|
||||
21 | ...
|
||||
| ^^^ PYI013
|
||||
|
|
||||
= help: Remove unnecessary `...`
|
||||
|
||||
ℹ Fix
|
||||
18 18 | My body only contains an ellipsis.
|
||||
19 19 | """
|
||||
20 20 |
|
||||
21 |- ...
|
||||
22 21 |
|
||||
23 22 |
|
||||
24 23 | class NonEmptyChild(Exception):
|
||||
|
||||
PYI013.py:26:5: PYI013 [*] Non-empty class body must not contain `...`
|
||||
|
|
||||
24 | class NonEmptyChild(Exception):
|
||||
25 | value: int
|
||||
26 | ...
|
||||
| ^^^ PYI013
|
||||
|
|
||||
= help: Remove unnecessary `...`
|
||||
|
||||
ℹ Fix
|
||||
23 23 |
|
||||
24 24 | class NonEmptyChild(Exception):
|
||||
25 25 | value: int
|
||||
26 |- ...
|
||||
27 26 |
|
||||
28 27 |
|
||||
29 28 | class NonEmptyChild2(Exception):
|
||||
|
||||
PYI013.py:30:5: PYI013 [*] Non-empty class body must not contain `...`
|
||||
|
|
||||
29 | class NonEmptyChild2(Exception):
|
||||
30 | ...
|
||||
| ^^^ PYI013
|
||||
31 | value: int
|
||||
|
|
||||
= help: Remove unnecessary `...`
|
||||
|
||||
ℹ Fix
|
||||
27 27 |
|
||||
28 28 |
|
||||
29 29 | class NonEmptyChild2(Exception):
|
||||
30 |- ...
|
||||
31 30 | value: int
|
||||
32 31 |
|
||||
33 32 |
|
||||
|
||||
PYI013.py:36:5: PYI013 [*] Non-empty class body must not contain `...`
|
||||
|
|
||||
34 | class NonEmptyWithInit:
|
||||
35 | value: int
|
||||
36 | ...
|
||||
| ^^^ PYI013
|
||||
37 |
|
||||
38 | def __init__():
|
||||
|
|
||||
= help: Remove unnecessary `...`
|
||||
|
||||
ℹ Fix
|
||||
33 33 |
|
||||
34 34 | class NonEmptyWithInit:
|
||||
35 35 | value: int
|
||||
36 |- ...
|
||||
37 36 |
|
||||
38 37 | def __init__():
|
||||
39 38 | pass
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,217 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI016.py:5:15: PYI016 [*] Duplicate union member `str`
|
||||
|
|
||||
4 | # Should emit for duplicate field types.
|
||||
5 | field2: str | str # PYI016: Duplicate union member `str`
|
||||
| ^^^ PYI016
|
||||
|
|
||||
= help: Remove duplicate union member `str`
|
||||
|
||||
ℹ Fix
|
||||
2 2 | field1: str
|
||||
3 3 |
|
||||
4 4 | # Should emit for duplicate field types.
|
||||
5 |-field2: str | str # PYI016: Duplicate union member `str`
|
||||
5 |+field2: str # PYI016: Duplicate union member `str`
|
||||
6 6 |
|
||||
7 7 |
|
||||
8 8 | # Should emit for union types in arguments.
|
||||
|
||||
PYI016.py:9:23: PYI016 [*] Duplicate union member `int`
|
||||
|
|
||||
8 | # Should emit for union types in arguments.
|
||||
9 | def func1(arg1: int | int): # PYI016: Duplicate union member `int`
|
||||
| ^^^ PYI016
|
||||
10 | print(arg1)
|
||||
|
|
||||
= help: Remove duplicate union member `int`
|
||||
|
||||
ℹ Fix
|
||||
6 6 |
|
||||
7 7 |
|
||||
8 8 | # Should emit for union types in arguments.
|
||||
9 |-def func1(arg1: int | int): # PYI016: Duplicate union member `int`
|
||||
9 |+def func1(arg1: int): # PYI016: Duplicate union member `int`
|
||||
10 10 | print(arg1)
|
||||
11 11 |
|
||||
12 12 |
|
||||
|
||||
PYI016.py:14:22: PYI016 [*] Duplicate union member `str`
|
||||
|
|
||||
13 | # Should emit for unions in return types.
|
||||
14 | def func2() -> str | str: # PYI016: Duplicate union member `str`
|
||||
| ^^^ PYI016
|
||||
15 | return "my string"
|
||||
|
|
||||
= help: Remove duplicate union member `str`
|
||||
|
||||
ℹ Fix
|
||||
11 11 |
|
||||
12 12 |
|
||||
13 13 | # Should emit for unions in return types.
|
||||
14 |-def func2() -> str | str: # PYI016: Duplicate union member `str`
|
||||
14 |+def func2() -> str: # PYI016: Duplicate union member `str`
|
||||
15 15 | return "my string"
|
||||
16 16 |
|
||||
17 17 |
|
||||
|
||||
PYI016.py:19:15: PYI016 [*] Duplicate union member `str`
|
||||
|
|
||||
18 | # Should emit in longer unions, even if not directly adjacent.
|
||||
19 | field3: str | str | int # PYI016: Duplicate union member `str`
|
||||
| ^^^ PYI016
|
||||
20 | field4: int | int | str # PYI016: Duplicate union member `int`
|
||||
21 | field5: str | int | str # PYI016: Duplicate union member `str`
|
||||
|
|
||||
= help: Remove duplicate union member `str`
|
||||
|
||||
ℹ Fix
|
||||
16 16 |
|
||||
17 17 |
|
||||
18 18 | # Should emit in longer unions, even if not directly adjacent.
|
||||
19 |-field3: str | str | int # PYI016: Duplicate union member `str`
|
||||
19 |+field3: str | int # PYI016: Duplicate union member `str`
|
||||
20 20 | field4: int | int | str # PYI016: Duplicate union member `int`
|
||||
21 21 | field5: str | int | str # PYI016: Duplicate union member `str`
|
||||
22 22 | field6: int | bool | str | int # PYI016: Duplicate union member `int`
|
||||
|
||||
PYI016.py:20:15: PYI016 [*] Duplicate union member `int`
|
||||
|
|
||||
18 | # Should emit in longer unions, even if not directly adjacent.
|
||||
19 | field3: str | str | int # PYI016: Duplicate union member `str`
|
||||
20 | field4: int | int | str # PYI016: Duplicate union member `int`
|
||||
| ^^^ PYI016
|
||||
21 | field5: str | int | str # PYI016: Duplicate union member `str`
|
||||
22 | field6: int | bool | str | int # PYI016: Duplicate union member `int`
|
||||
|
|
||||
= help: Remove duplicate union member `int`
|
||||
|
||||
ℹ Fix
|
||||
17 17 |
|
||||
18 18 | # Should emit in longer unions, even if not directly adjacent.
|
||||
19 19 | field3: str | str | int # PYI016: Duplicate union member `str`
|
||||
20 |-field4: int | int | str # PYI016: Duplicate union member `int`
|
||||
20 |+field4: int | str # PYI016: Duplicate union member `int`
|
||||
21 21 | field5: str | int | str # PYI016: Duplicate union member `str`
|
||||
22 22 | field6: int | bool | str | int # PYI016: Duplicate union member `int`
|
||||
23 23 |
|
||||
|
||||
PYI016.py:21:21: PYI016 [*] Duplicate union member `str`
|
||||
|
|
||||
19 | field3: str | str | int # PYI016: Duplicate union member `str`
|
||||
20 | field4: int | int | str # PYI016: Duplicate union member `int`
|
||||
21 | field5: str | int | str # PYI016: Duplicate union member `str`
|
||||
| ^^^ PYI016
|
||||
22 | field6: int | bool | str | int # PYI016: Duplicate union member `int`
|
||||
|
|
||||
= help: Remove duplicate union member `str`
|
||||
|
||||
ℹ Fix
|
||||
18 18 | # Should emit in longer unions, even if not directly adjacent.
|
||||
19 19 | field3: str | str | int # PYI016: Duplicate union member `str`
|
||||
20 20 | field4: int | int | str # PYI016: Duplicate union member `int`
|
||||
21 |-field5: str | int | str # PYI016: Duplicate union member `str`
|
||||
21 |+field5: str | int # PYI016: Duplicate union member `str`
|
||||
22 22 | field6: int | bool | str | int # PYI016: Duplicate union member `int`
|
||||
23 23 |
|
||||
24 24 | # Shouldn't emit for non-type unions.
|
||||
|
||||
PYI016.py:22:28: PYI016 [*] Duplicate union member `int`
|
||||
|
|
||||
20 | field4: int | int | str # PYI016: Duplicate union member `int`
|
||||
21 | field5: str | int | str # PYI016: Duplicate union member `str`
|
||||
22 | field6: int | bool | str | int # PYI016: Duplicate union member `int`
|
||||
| ^^^ PYI016
|
||||
23 |
|
||||
24 | # Shouldn't emit for non-type unions.
|
||||
|
|
||||
= help: Remove duplicate union member `int`
|
||||
|
||||
ℹ Fix
|
||||
19 19 | field3: str | str | int # PYI016: Duplicate union member `str`
|
||||
20 20 | field4: int | int | str # PYI016: Duplicate union member `int`
|
||||
21 21 | field5: str | int | str # PYI016: Duplicate union member `str`
|
||||
22 |-field6: int | bool | str | int # PYI016: Duplicate union member `int`
|
||||
22 |+field6: int | bool | str # PYI016: Duplicate union member `int`
|
||||
23 23 |
|
||||
24 24 | # Shouldn't emit for non-type unions.
|
||||
25 25 | field7 = str | str
|
||||
|
||||
PYI016.py:28:22: PYI016 [*] Duplicate union member `int`
|
||||
|
|
||||
27 | # Should emit for strangely-bracketed unions.
|
||||
28 | field8: int | (str | int) # PYI016: Duplicate union member `int`
|
||||
| ^^^ PYI016
|
||||
29 |
|
||||
30 | # Should handle user brackets when fixing.
|
||||
|
|
||||
= help: Remove duplicate union member `int`
|
||||
|
||||
ℹ Fix
|
||||
25 25 | field7 = str | str
|
||||
26 26 |
|
||||
27 27 | # Should emit for strangely-bracketed unions.
|
||||
28 |-field8: int | (str | int) # PYI016: Duplicate union member `int`
|
||||
28 |+field8: int | (str) # PYI016: Duplicate union member `int`
|
||||
29 29 |
|
||||
30 30 | # Should handle user brackets when fixing.
|
||||
31 31 | field9: int | (int | str) # PYI016: Duplicate union member `int`
|
||||
|
||||
PYI016.py:31:16: PYI016 [*] Duplicate union member `int`
|
||||
|
|
||||
30 | # Should handle user brackets when fixing.
|
||||
31 | field9: int | (int | str) # PYI016: Duplicate union member `int`
|
||||
| ^^^ PYI016
|
||||
32 | field10: (str | int) | str # PYI016: Duplicate union member `str`
|
||||
|
|
||||
= help: Remove duplicate union member `int`
|
||||
|
||||
ℹ Fix
|
||||
28 28 | field8: int | (str | int) # PYI016: Duplicate union member `int`
|
||||
29 29 |
|
||||
30 30 | # Should handle user brackets when fixing.
|
||||
31 |-field9: int | (int | str) # PYI016: Duplicate union member `int`
|
||||
31 |+field9: int | (str) # PYI016: Duplicate union member `int`
|
||||
32 32 | field10: (str | int) | str # PYI016: Duplicate union member `str`
|
||||
33 33 |
|
||||
34 34 | # Should emit for nested unions.
|
||||
|
||||
PYI016.py:32:24: PYI016 [*] Duplicate union member `str`
|
||||
|
|
||||
30 | # Should handle user brackets when fixing.
|
||||
31 | field9: int | (int | str) # PYI016: Duplicate union member `int`
|
||||
32 | field10: (str | int) | str # PYI016: Duplicate union member `str`
|
||||
| ^^^ PYI016
|
||||
33 |
|
||||
34 | # Should emit for nested unions.
|
||||
|
|
||||
= help: Remove duplicate union member `str`
|
||||
|
||||
ℹ Fix
|
||||
29 29 |
|
||||
30 30 | # Should handle user brackets when fixing.
|
||||
31 31 | field9: int | (int | str) # PYI016: Duplicate union member `int`
|
||||
32 |-field10: (str | int) | str # PYI016: Duplicate union member `str`
|
||||
32 |+field10: str | int # PYI016: Duplicate union member `str`
|
||||
33 33 |
|
||||
34 34 | # Should emit for nested unions.
|
||||
35 35 | field11: dict[int | int, str]
|
||||
|
||||
PYI016.py:35:21: PYI016 [*] Duplicate union member `int`
|
||||
|
|
||||
34 | # Should emit for nested unions.
|
||||
35 | field11: dict[int | int, str]
|
||||
| ^^^ PYI016
|
||||
|
|
||||
= help: Remove duplicate union member `int`
|
||||
|
||||
ℹ Fix
|
||||
32 32 | field10: (str | int) | str # PYI016: Duplicate union member `str`
|
||||
33 33 |
|
||||
34 34 | # Should emit for nested unions.
|
||||
35 |-field11: dict[int | int, str]
|
||||
35 |+field11: dict[int, str]
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI018.py:4:1: PYI018 Private TypeVar `_T` is never used
|
||||
|
|
||||
2 | from typing import TypeVar
|
||||
3 |
|
||||
4 | _T = typing.TypeVar("_T")
|
||||
| ^^ PYI018
|
||||
5 | _P = TypeVar("_P")
|
||||
|
|
||||
|
||||
PYI018.py:5:1: PYI018 Private TypeVar `_P` is never used
|
||||
|
|
||||
4 | _T = typing.TypeVar("_T")
|
||||
5 | _P = TypeVar("_P")
|
||||
| ^^ PYI018
|
||||
6 |
|
||||
7 | # OK
|
||||
|
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,38 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI019.py:7:62: PYI019 Methods like `__new__` should return `typing.Self` instead of a custom `TypeVar`
|
||||
|
|
||||
6 | class BadClass:
|
||||
7 | def __new__(cls: type[_S], *args: str, **kwargs: int) -> _S: ... # PYI019
|
||||
| ^^ PYI019
|
||||
|
|
||||
|
||||
PYI019.py:10:54: PYI019 Methods like `bad_instance_method` should return `typing.Self` instead of a custom `TypeVar`
|
||||
|
|
||||
10 | def bad_instance_method(self: _S, arg: bytes) -> _S: ... # PYI019
|
||||
| ^^ PYI019
|
||||
|
|
||||
|
||||
PYI019.py:14:54: PYI019 Methods like `bad_class_method` should return `typing.Self` instead of a custom `TypeVar`
|
||||
|
|
||||
13 | @classmethod
|
||||
14 | def bad_class_method(cls: type[_S], arg: int) -> _S: ... # PYI019
|
||||
| ^^ PYI019
|
||||
|
|
||||
|
||||
PYI019.py:35:63: PYI019 Methods like `__new__` should return `typing.Self` instead of a custom `TypeVar`
|
||||
|
|
||||
33 | # Python > 3.12
|
||||
34 | class PEP695BadDunderNew[T]:
|
||||
35 | def __new__[S](cls: type[S], *args: Any, ** kwargs: Any) -> S: ... # PYI019
|
||||
| ^ PYI019
|
||||
|
|
||||
|
||||
PYI019.py:38:46: PYI019 Methods like `generic_instance_method` should return `typing.Self` instead of a custom `TypeVar`
|
||||
|
|
||||
38 | def generic_instance_method[S](self: S) -> S: ... # PYI019
|
||||
| ^ PYI019
|
||||
|
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,37 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI024.py:3:9: PYI024 Use `typing.NamedTuple` instead of `collections.namedtuple`
|
||||
|
|
||||
1 | import collections
|
||||
2 |
|
||||
3 | person: collections.namedtuple # Y024 Use "typing.NamedTuple" instead of "collections.namedtuple"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ PYI024
|
||||
4 |
|
||||
5 | from collections import namedtuple
|
||||
|
|
||||
= help: Replace with `typing.NamedTuple`
|
||||
|
||||
PYI024.py:7:9: PYI024 Use `typing.NamedTuple` instead of `collections.namedtuple`
|
||||
|
|
||||
5 | from collections import namedtuple
|
||||
6 |
|
||||
7 | person: namedtuple # Y024 Use "typing.NamedTuple" instead of "collections.namedtuple"
|
||||
| ^^^^^^^^^^ PYI024
|
||||
8 |
|
||||
9 | person = namedtuple(
|
||||
|
|
||||
= help: Replace with `typing.NamedTuple`
|
||||
|
||||
PYI024.py:9:10: PYI024 Use `typing.NamedTuple` instead of `collections.namedtuple`
|
||||
|
|
||||
7 | person: namedtuple # Y024 Use "typing.NamedTuple" instead of "collections.namedtuple"
|
||||
8 |
|
||||
9 | person = namedtuple(
|
||||
| ^^^^^^^^^^ PYI024
|
||||
10 | "Person", ["name", "age"]
|
||||
11 | ) # Y024 Use "typing.NamedTuple" instead of "collections.namedtuple"
|
||||
|
|
||||
= help: Replace with `typing.NamedTuple`
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,46 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI025.py:10:33: PYI025 [*] Use `from collections.abc import Set as AbstractSet` to avoid confusion with the `set` builtin
|
||||
|
|
||||
9 | def f():
|
||||
10 | from collections.abc import Set # PYI025
|
||||
| ^^^ PYI025
|
||||
|
|
||||
= help: Alias `Set` to `AbstractSet`
|
||||
|
||||
ℹ Suggested fix
|
||||
7 7 |
|
||||
8 8 |
|
||||
9 9 | def f():
|
||||
10 |- from collections.abc import Set # PYI025
|
||||
10 |+ from collections.abc import Set as AbstractSet # PYI025
|
||||
11 11 |
|
||||
12 12 |
|
||||
13 13 | def f():
|
||||
|
||||
PYI025.py:14:51: PYI025 [*] Use `from collections.abc import Set as AbstractSet` to avoid confusion with the `set` builtin
|
||||
|
|
||||
13 | def f():
|
||||
14 | from collections.abc import Container, Sized, Set, ValuesView # PYI025
|
||||
| ^^^ PYI025
|
||||
15 |
|
||||
16 | GLOBAL: Set[int] = set()
|
||||
|
|
||||
= help: Alias `Set` to `AbstractSet`
|
||||
|
||||
ℹ Suggested fix
|
||||
11 11 |
|
||||
12 12 |
|
||||
13 13 | def f():
|
||||
14 |- from collections.abc import Container, Sized, Set, ValuesView # PYI025
|
||||
14 |+ from collections.abc import Container, Sized, Set as AbstractSet, ValuesView # PYI025
|
||||
15 15 |
|
||||
16 |- GLOBAL: Set[int] = set()
|
||||
16 |+ GLOBAL: AbstractSet[int] = set()
|
||||
17 17 |
|
||||
18 18 | class Class:
|
||||
19 |- member: Set[int]
|
||||
19 |+ member: AbstractSet[int]
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,110 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI030.py:9:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
8 | # Should emit for duplicate field types.
|
||||
9 | field2: Literal[1] | Literal[2] # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
10 |
|
||||
11 | # Should emit for union types in arguments.
|
||||
|
|
||||
|
||||
PYI030.py:12:17: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
11 | # Should emit for union types in arguments.
|
||||
12 | def func1(arg1: Literal[1] | Literal[2]): # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
13 | print(arg1)
|
||||
|
|
||||
|
||||
PYI030.py:17:16: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
16 | # Should emit for unions in return types.
|
||||
17 | def func2() -> Literal[1] | Literal[2]: # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
18 | return "my Literal[1]ing"
|
||||
|
|
||||
|
||||
PYI030.py:22:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
21 | # Should emit in longer unions, even if not directly adjacent.
|
||||
22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
|
|
||||
|
||||
PYI030.py:23:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
21 | # Should emit in longer unions, even if not directly adjacent.
|
||||
22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
|
|
||||
|
||||
PYI030.py:24:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
|
|
||||
|
||||
PYI030.py:25:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
26 |
|
||||
27 | # Should emit for non-type unions.
|
||||
|
|
||||
|
||||
PYI030.py:28:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
27 | # Should emit for non-type unions.
|
||||
28 | field7 = Literal[1] | Literal[2] # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
29 |
|
||||
30 | # Should emit for parenthesized unions.
|
||||
|
|
||||
|
||||
PYI030.py:31:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
30 | # Should emit for parenthesized unions.
|
||||
31 | field8: Literal[1] | (Literal[2] | str) # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
32 |
|
||||
33 | # Should handle user parentheses when fixing.
|
||||
|
|
||||
|
||||
PYI030.py:34:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
33 | # Should handle user parentheses when fixing.
|
||||
34 | field9: Literal[1] | (Literal[2] | str) # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
35 | field10: (Literal[1] | str) | Literal[2] # Error
|
||||
|
|
||||
|
||||
PYI030.py:35:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
33 | # Should handle user parentheses when fixing.
|
||||
34 | field9: Literal[1] | (Literal[2] | str) # Error
|
||||
35 | field10: (Literal[1] | str) | Literal[2] # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
36 |
|
||||
37 | # Should emit for union in generic parent type.
|
||||
|
|
||||
|
||||
PYI030.py:38:15: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
37 | # Should emit for union in generic parent type.
|
||||
38 | field11: dict[Literal[1] | Literal[2], str] # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
|
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,42 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI032.py:6:29: PYI032 [*] Prefer `object` to `Any` for the second parameter to `__eq__`
|
||||
|
|
||||
5 | class Bad:
|
||||
6 | def __eq__(self, other: Any) -> bool: ... # Y032
|
||||
| ^^^ PYI032
|
||||
7 | def __ne__(self, other: typing.Any) -> typing.Any: ... # Y032
|
||||
|
|
||||
= help: Replace with `object`
|
||||
|
||||
ℹ Fix
|
||||
3 3 |
|
||||
4 4 |
|
||||
5 5 | class Bad:
|
||||
6 |- def __eq__(self, other: Any) -> bool: ... # Y032
|
||||
6 |+ def __eq__(self, other: object) -> bool: ... # Y032
|
||||
7 7 | def __ne__(self, other: typing.Any) -> typing.Any: ... # Y032
|
||||
8 8 |
|
||||
9 9 |
|
||||
|
||||
PYI032.py:7:29: PYI032 [*] Prefer `object` to `Any` for the second parameter to `__ne__`
|
||||
|
|
||||
5 | class Bad:
|
||||
6 | def __eq__(self, other: Any) -> bool: ... # Y032
|
||||
7 | def __ne__(self, other: typing.Any) -> typing.Any: ... # Y032
|
||||
| ^^^^^^^^^^ PYI032
|
||||
|
|
||||
= help: Replace with `object`
|
||||
|
||||
ℹ Fix
|
||||
4 4 |
|
||||
5 5 | class Bad:
|
||||
6 6 | def __eq__(self, other: Any) -> bool: ... # Y032
|
||||
7 |- def __ne__(self, other: typing.Any) -> typing.Any: ... # Y032
|
||||
7 |+ def __ne__(self, other: object) -> typing.Any: ... # Y032
|
||||
8 8 |
|
||||
9 9 |
|
||||
10 10 | class Good:
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,92 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI034.py:19:9: PYI034 `__new__` methods in classes like `Bad` usually return `self` at runtime
|
||||
|
|
||||
17 | object
|
||||
18 | ): # Y040 Do not inherit from "object" explicitly, as it is redundant in Python 3
|
||||
19 | def __new__(cls, *args: Any, **kwargs: Any) -> Bad:
|
||||
| ^^^^^^^ 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: ..."
|
||||
|
|
||||
= 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
|
||||
|
|
||||
32 | ... # Y032 Prefer "object" to "Any" for the second parameter in "__ne__" methods
|
||||
33 |
|
||||
34 | def __enter__(self) -> Bad:
|
||||
| ^^^^^^^^^ 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: ..."
|
||||
|
|
||||
= 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
|
||||
|
|
||||
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: ..."
|
||||
36 |
|
||||
37 | async def __aenter__(self) -> Bad:
|
||||
| ^^^^^^^^^^ 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: ..."
|
||||
|
|
||||
= 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
|
||||
|
|
||||
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: ..."
|
||||
39 |
|
||||
40 | def __iadd__(self, other: Bad) -> Bad:
|
||||
| ^^^^^^^^ 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: ..."
|
||||
|
|
||||
= 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
|
||||
|
|
||||
162 | class BadIterator1(Iterator[int]):
|
||||
163 | def __iter__(self) -> Iterator[int]:
|
||||
| ^^^^^^^^ 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: ..."
|
||||
|
|
||||
= 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
|
||||
|
|
||||
168 | typing.Iterator[int]
|
||||
169 | ): # Y022 Use "collections.abc.Iterator[T]" instead of "typing.Iterator[T]" (PEP 585 syntax)
|
||||
170 | def __iter__(self) -> Iterator[int]:
|
||||
| ^^^^^^^^ 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: ..."
|
||||
|
|
||||
= 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
|
||||
|
|
||||
175 | typing.Iterator[int]
|
||||
176 | ): # Y022 Use "collections.abc.Iterator[T]" instead of "typing.Iterator[T]" (PEP 585 syntax)
|
||||
177 | def __iter__(self) -> collections.abc.Iterator[int]:
|
||||
| ^^^^^^^^ 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: ..."
|
||||
|
|
||||
= 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
|
||||
|
|
||||
181 | class BadIterator4(Iterator[int]):
|
||||
182 | # Note: *Iterable*, not *Iterator*, returned!
|
||||
183 | def __iter__(self) -> Iterable[int]:
|
||||
| ^^^^^^^^ 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: ..."
|
||||
|
|
||||
= 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
|
||||
|
|
||||
192 | class BadAsyncIterator(collections.abc.AsyncIterator[str]):
|
||||
193 | def __aiter__(self) -> typing.AsyncIterator[str]:
|
||||
| ^^^^^^^^^ 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)
|
||||
|
|
||||
= help: Consider using `typing_extensions.Self` as return type
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,161 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI036.py:54:31: PYI036 [*] Star-args in `__exit__` should be annotated with `object`
|
||||
|
|
||||
53 | class BadOne:
|
||||
54 | def __exit__(self, *args: Any) -> None: ... # PYI036: Bad star-args annotation
|
||||
| ^^^ PYI036
|
||||
55 | async def __aexit__(self) -> None: ... # PYI036: Missing args
|
||||
|
|
||||
= help: Annotate star-args with `object`
|
||||
|
||||
ℹ Fix
|
||||
51 51 |
|
||||
52 52 |
|
||||
53 53 | class BadOne:
|
||||
54 |- def __exit__(self, *args: Any) -> None: ... # PYI036: Bad star-args annotation
|
||||
54 |+ def __exit__(self, *args: object) -> None: ... # PYI036: Bad star-args annotation
|
||||
55 55 | async def __aexit__(self) -> None: ... # PYI036: Missing args
|
||||
56 56 |
|
||||
57 57 | class BadTwo:
|
||||
|
||||
PYI036.py:55:24: PYI036 If there are no star-args, `__aexit__` should have at least 3 non-keyword-only args (excluding `self`)
|
||||
|
|
||||
53 | class BadOne:
|
||||
54 | def __exit__(self, *args: Any) -> None: ... # PYI036: Bad star-args annotation
|
||||
55 | async def __aexit__(self) -> None: ... # PYI036: Missing args
|
||||
| ^^^^^^ PYI036
|
||||
56 |
|
||||
57 | class BadTwo:
|
||||
|
|
||||
|
||||
PYI036.py:58:38: PYI036 All arguments after the first four in `__exit__` must have a default value
|
||||
|
|
||||
57 | class BadTwo:
|
||||
58 | def __exit__(self, typ, exc, tb, weird_extra_arg) -> None: ... # PYI036: Extra arg must have default
|
||||
| ^^^^^^^^^^^^^^^ PYI036
|
||||
59 | async def __aexit__(self, typ, exc, tb, *, weird_extra_arg) -> None: ...# PYI036: Extra arg must have default
|
||||
|
|
||||
|
||||
PYI036.py:59:48: PYI036 All keyword-only arguments in `__aexit__` must have a default value
|
||||
|
|
||||
57 | class BadTwo:
|
||||
58 | def __exit__(self, typ, exc, tb, weird_extra_arg) -> None: ... # PYI036: Extra arg must have default
|
||||
59 | async def __aexit__(self, typ, exc, tb, *, weird_extra_arg) -> None: ...# PYI036: Extra arg must have default
|
||||
| ^^^^^^^^^^^^^^^ PYI036
|
||||
60 |
|
||||
61 | class BadThree:
|
||||
|
|
||||
|
||||
PYI036.py:62:29: PYI036 The first argument in `__exit__` should be annotated with `object` or `type[BaseException] | None`
|
||||
|
|
||||
61 | class BadThree:
|
||||
62 | def __exit__(self, typ: type[BaseException], exc: BaseException | None, tb: TracebackType | None) -> None: ... # PYI036: First arg has bad annotation
|
||||
| ^^^^^^^^^^^^^^^^^^^ PYI036
|
||||
63 | async def __aexit__(self, __typ: type[BaseException] | None, __exc: BaseException, __tb: TracebackType) -> bool | None: ... # PYI036: Second arg has bad annotation
|
||||
|
|
||||
|
||||
PYI036.py:63:73: PYI036 The second argument in `__aexit__` should be annotated with `object` or `BaseException | None`
|
||||
|
|
||||
61 | class BadThree:
|
||||
62 | def __exit__(self, typ: type[BaseException], exc: BaseException | None, tb: TracebackType | None) -> None: ... # PYI036: First arg has bad annotation
|
||||
63 | async def __aexit__(self, __typ: type[BaseException] | None, __exc: BaseException, __tb: TracebackType) -> bool | None: ... # PYI036: Second arg has bad annotation
|
||||
| ^^^^^^^^^^^^^ PYI036
|
||||
64 |
|
||||
65 | class BadFour:
|
||||
|
|
||||
|
||||
PYI036.py:63:94: PYI036 The third argument in `__aexit__` should be annotated with `object` or `types.TracebackType | None`
|
||||
|
|
||||
61 | class BadThree:
|
||||
62 | def __exit__(self, typ: type[BaseException], exc: BaseException | None, tb: TracebackType | None) -> None: ... # PYI036: First arg has bad annotation
|
||||
63 | async def __aexit__(self, __typ: type[BaseException] | None, __exc: BaseException, __tb: TracebackType) -> bool | None: ... # PYI036: Second arg has bad annotation
|
||||
| ^^^^^^^^^^^^^ PYI036
|
||||
64 |
|
||||
65 | class BadFour:
|
||||
|
|
||||
|
||||
PYI036.py:66:111: PYI036 The third argument in `__exit__` should be annotated with `object` or `types.TracebackType | None`
|
||||
|
|
||||
65 | class BadFour:
|
||||
66 | def __exit__(self, typ: typing.Optional[type[BaseException]], exc: typing.Union[BaseException, None], tb: TracebackType) -> None: ... # PYI036: Third arg has bad annotation
|
||||
| ^^^^^^^^^^^^^ PYI036
|
||||
67 | async def __aexit__(self, __typ: type[BaseException] | None, __exc: BaseException | None, __tb: typing.Union[TracebackType, None, int]) -> bool | None: ... # PYI036: Third arg has bad annotation
|
||||
|
|
||||
|
||||
PYI036.py:67:101: PYI036 The third argument in `__aexit__` should be annotated with `object` or `types.TracebackType | None`
|
||||
|
|
||||
65 | class BadFour:
|
||||
66 | def __exit__(self, typ: typing.Optional[type[BaseException]], exc: typing.Union[BaseException, None], tb: TracebackType) -> None: ... # PYI036: Third arg has bad annotation
|
||||
67 | async def __aexit__(self, __typ: type[BaseException] | None, __exc: BaseException | None, __tb: typing.Union[TracebackType, None, int]) -> bool | None: ... # PYI036: Third arg has bad annotation
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI036
|
||||
68 |
|
||||
69 | class BadFive:
|
||||
|
|
||||
|
||||
PYI036.py:70:29: PYI036 The first argument in `__exit__` should be annotated with `object` or `type[BaseException] | None`
|
||||
|
|
||||
69 | class BadFive:
|
||||
70 | def __exit__(self, typ: BaseException | None, *args: list[str]) -> bool: ... # PYI036: Bad star-args annotation
|
||||
| ^^^^^^^^^^^^^^^^^^^^ PYI036
|
||||
71 | async def __aexit__(self, /, typ: type[BaseException] | None, *args: Any) -> Awaitable[None]: ... # PYI036: Bad star-args annotation
|
||||
|
|
||||
|
||||
PYI036.py:70:58: PYI036 [*] Star-args in `__exit__` should be annotated with `object`
|
||||
|
|
||||
69 | class BadFive:
|
||||
70 | def __exit__(self, typ: BaseException | None, *args: list[str]) -> bool: ... # PYI036: Bad star-args annotation
|
||||
| ^^^^^^^^^ PYI036
|
||||
71 | async def __aexit__(self, /, typ: type[BaseException] | None, *args: Any) -> Awaitable[None]: ... # PYI036: Bad star-args annotation
|
||||
|
|
||||
= help: Annotate star-args with `object`
|
||||
|
||||
ℹ Fix
|
||||
67 67 | async def __aexit__(self, __typ: type[BaseException] | None, __exc: BaseException | None, __tb: typing.Union[TracebackType, None, int]) -> bool | None: ... # PYI036: Third arg has bad annotation
|
||||
68 68 |
|
||||
69 69 | class BadFive:
|
||||
70 |- def __exit__(self, typ: BaseException | None, *args: list[str]) -> bool: ... # PYI036: Bad star-args annotation
|
||||
70 |+ def __exit__(self, typ: BaseException | None, *args: object) -> bool: ... # PYI036: Bad star-args annotation
|
||||
71 71 | async def __aexit__(self, /, typ: type[BaseException] | None, *args: Any) -> Awaitable[None]: ... # PYI036: Bad star-args annotation
|
||||
72 72 |
|
||||
73 73 | class BadSix:
|
||||
|
||||
PYI036.py:71:74: PYI036 [*] Star-args in `__aexit__` should be annotated with `object`
|
||||
|
|
||||
69 | class BadFive:
|
||||
70 | def __exit__(self, typ: BaseException | None, *args: list[str]) -> bool: ... # PYI036: Bad star-args annotation
|
||||
71 | async def __aexit__(self, /, typ: type[BaseException] | None, *args: Any) -> Awaitable[None]: ... # PYI036: Bad star-args annotation
|
||||
| ^^^ PYI036
|
||||
72 |
|
||||
73 | class BadSix:
|
||||
|
|
||||
= help: Annotate star-args with `object`
|
||||
|
||||
ℹ Fix
|
||||
68 68 |
|
||||
69 69 | class BadFive:
|
||||
70 70 | def __exit__(self, typ: BaseException | None, *args: list[str]) -> bool: ... # PYI036: Bad star-args annotation
|
||||
71 |- async def __aexit__(self, /, typ: type[BaseException] | None, *args: Any) -> Awaitable[None]: ... # PYI036: Bad star-args annotation
|
||||
71 |+ async def __aexit__(self, /, typ: type[BaseException] | None, *args: object) -> Awaitable[None]: ... # PYI036: Bad star-args annotation
|
||||
72 72 |
|
||||
73 73 | class BadSix:
|
||||
74 74 | def __exit__(self, typ, exc, tb, weird_extra_arg, extra_arg2 = None) -> None: ... # PYI036: Extra arg must have default
|
||||
|
||||
PYI036.py:74:38: PYI036 All arguments after the first four in `__exit__` must have a default value
|
||||
|
|
||||
73 | class BadSix:
|
||||
74 | def __exit__(self, typ, exc, tb, weird_extra_arg, extra_arg2 = None) -> None: ... # PYI036: Extra arg must have default
|
||||
| ^^^^^^^^^^^^^^^ PYI036
|
||||
75 | async def __aexit__(self, typ, exc, tb, *, weird_extra_arg) -> None: ... # PYI036: kwargs must have default
|
||||
|
|
||||
|
||||
PYI036.py:75:48: PYI036 All keyword-only arguments in `__aexit__` must have a default value
|
||||
|
|
||||
73 | class BadSix:
|
||||
74 | def __exit__(self, typ, exc, tb, weird_extra_arg, extra_arg2 = None) -> None: ... # PYI036: Extra arg must have default
|
||||
75 | async def __aexit__(self, typ, exc, tb, *, weird_extra_arg) -> None: ... # PYI036: kwargs must have default
|
||||
| ^^^^^^^^^^^^^^^ PYI036
|
||||
|
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,50 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI041.py:22:14: PYI041 Use `float` instead of `int | float`
|
||||
|
|
||||
22 | def f0(arg1: float | int) -> None:
|
||||
| ^^^^^^^^^^^ PYI041
|
||||
23 | ...
|
||||
|
|
||||
|
||||
PYI041.py:26:30: PYI041 Use `complex` instead of `float | complex`
|
||||
|
|
||||
26 | def f1(arg1: float, *, arg2: float | list[str] | type[bool] | complex) -> None:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI041
|
||||
27 | ...
|
||||
|
|
||||
|
||||
PYI041.py:30:28: PYI041 Use `float` instead of `int | float`
|
||||
|
|
||||
30 | def f2(arg1: int, /, arg2: int | int | float) -> None:
|
||||
| ^^^^^^^^^^^^^^^^^ PYI041
|
||||
31 | ...
|
||||
|
|
||||
|
||||
PYI041.py:38:24: PYI041 Use `float` instead of `int | float`
|
||||
|
|
||||
38 | async def f4(**kwargs: int | int | float) -> None:
|
||||
| ^^^^^^^^^^^^^^^^^ PYI041
|
||||
39 | ...
|
||||
|
|
||||
|
||||
PYI041.py:46:24: PYI041 Use `complex` instead of `float | complex`
|
||||
|
|
||||
44 | ...
|
||||
45 |
|
||||
46 | def bad(self, arg: int | float | complex) -> None:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ PYI041
|
||||
47 | ...
|
||||
|
|
||||
|
||||
PYI041.py:46:24: PYI041 Use `complex` instead of `int | complex`
|
||||
|
|
||||
44 | ...
|
||||
45 |
|
||||
46 | def bad(self, arg: int | float | complex) -> None:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ PYI041
|
||||
47 | ...
|
||||
|
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,32 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI042.py:10:1: PYI042 Type alias `just_literals_pipe_union` should be CamelCase
|
||||
|
|
||||
8 | )
|
||||
9 |
|
||||
10 | just_literals_pipe_union: TypeAlias = (
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ PYI042
|
||||
11 | Literal[True] | Literal["idk"]
|
||||
12 | ) # PYI042, since not camel case
|
||||
|
|
||||
|
||||
PYI042.py:19:1: PYI042 Type alias `snake_case_alias1` should be CamelCase
|
||||
|
|
||||
17 | _PrivateAliasS2: TypeAlias = Annotated[str, "also okay"]
|
||||
18 |
|
||||
19 | snake_case_alias1: TypeAlias = str | int # PYI042, since not camel case
|
||||
| ^^^^^^^^^^^^^^^^^ PYI042
|
||||
20 | _snake_case_alias2: TypeAlias = Literal["whatever"] # PYI042, since not camel case
|
||||
21 | Snake_case_alias: TypeAlias = int | float # PYI042, since not camel case
|
||||
|
|
||||
|
||||
PYI042.py:20:1: PYI042 Type alias `_snake_case_alias2` should be CamelCase
|
||||
|
|
||||
19 | snake_case_alias1: TypeAlias = str | int # PYI042, since not camel case
|
||||
20 | _snake_case_alias2: TypeAlias = Literal["whatever"] # PYI042, since not camel case
|
||||
| ^^^^^^^^^^^^^^^^^^ PYI042
|
||||
21 | Snake_case_alias: TypeAlias = int | float # PYI042, since not camel case
|
||||
|
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,33 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI043.py:10:1: PYI043 Private type alias `_PrivateAliasT` should not be suffixed with `T` (the `T` suffix implies that an object is a `TypeVar`)
|
||||
|
|
||||
8 | )
|
||||
9 |
|
||||
10 | _PrivateAliasT: TypeAlias = str | int # PYI043, since this ends in a T
|
||||
| ^^^^^^^^^^^^^^ PYI043
|
||||
11 | _PrivateAliasT2: TypeAlias = typing.Any # PYI043, since this ends in a T
|
||||
12 | _PrivateAliasT3: TypeAlias = Literal[
|
||||
|
|
||||
|
||||
PYI043.py:11:1: PYI043 Private type alias `_PrivateAliasT2` should not be suffixed with `T` (the `T` suffix implies that an object is a `TypeVar`)
|
||||
|
|
||||
10 | _PrivateAliasT: TypeAlias = str | int # PYI043, since this ends in a T
|
||||
11 | _PrivateAliasT2: TypeAlias = typing.Any # PYI043, since this ends in a T
|
||||
| ^^^^^^^^^^^^^^^ PYI043
|
||||
12 | _PrivateAliasT3: TypeAlias = Literal[
|
||||
13 | "not", "a", "chance"
|
||||
|
|
||||
|
||||
PYI043.py:12:1: PYI043 Private type alias `_PrivateAliasT3` should not be suffixed with `T` (the `T` suffix implies that an object is a `TypeVar`)
|
||||
|
|
||||
10 | _PrivateAliasT: TypeAlias = str | int # PYI043, since this ends in a T
|
||||
11 | _PrivateAliasT2: TypeAlias = typing.Any # PYI043, since this ends in a T
|
||||
12 | _PrivateAliasT3: TypeAlias = Literal[
|
||||
| ^^^^^^^^^^^^^^^ PYI043
|
||||
13 | "not", "a", "chance"
|
||||
14 | ] # PYI043, since this ends in a T
|
||||
|
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,60 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI045.py:12:27: PYI045 `__iter__` methods should return an `Iterator`, not an `Iterable`
|
||||
|
|
||||
11 | class TypingIterableTReturn:
|
||||
12 | def __iter__(self) -> typing.Iterable[int]:
|
||||
| ^^^^^^^^^^^^^^^^^^^^ PYI045
|
||||
13 | ...
|
||||
|
|
||||
|
||||
PYI045.py:20:27: PYI045 `__iter__` methods should return an `Iterator`, not an `Iterable`
|
||||
|
|
||||
19 | class TypingIterableReturn:
|
||||
20 | def __iter__(self) -> typing.Iterable:
|
||||
| ^^^^^^^^^^^^^^^ PYI045
|
||||
21 | ...
|
||||
|
|
||||
|
||||
PYI045.py:28:27: PYI045 `__iter__` methods should return an `Iterator`, not an `Iterable`
|
||||
|
|
||||
27 | class CollectionsIterableTReturn:
|
||||
28 | def __iter__(self) -> collections.abc.Iterable[int]:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI045
|
||||
29 | ...
|
||||
|
|
||||
|
||||
PYI045.py:36:27: PYI045 `__iter__` methods should return an `Iterator`, not an `Iterable`
|
||||
|
|
||||
35 | class CollectionsIterableReturn:
|
||||
36 | def __iter__(self) -> collections.abc.Iterable:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ PYI045
|
||||
37 | ...
|
||||
|
|
||||
|
||||
PYI045.py:44:27: PYI045 `__iter__` methods should return an `Iterator`, not an `Iterable`
|
||||
|
|
||||
43 | class IterableReturn:
|
||||
44 | def __iter__(self) -> Iterable:
|
||||
| ^^^^^^^^ PYI045
|
||||
45 | ...
|
||||
|
|
||||
|
||||
PYI045.py:79:28: PYI045 `__aiter__` methods should return an `AsyncIterator`, not an `AsyncIterable`
|
||||
|
|
||||
78 | class TypingAsyncIterableTReturn:
|
||||
79 | def __aiter__(self) -> typing.AsyncIterable[int]:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ PYI045
|
||||
80 | ...
|
||||
|
|
||||
|
||||
PYI045.py:84:28: PYI045 `__aiter__` methods should return an `AsyncIterator`, not an `AsyncIterable`
|
||||
|
|
||||
83 | class TypingAsyncIterableReturn:
|
||||
84 | def __aiter__(self) -> typing.AsyncIterable:
|
||||
| ^^^^^^^^^^^^^^^^^^^^ PYI045
|
||||
85 | ...
|
||||
|
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI046.py:5:7: PYI046 Private protocol `_Foo` is never used
|
||||
|
|
||||
5 | class _Foo(Protocol):
|
||||
| ^^^^ PYI046
|
||||
6 | bar: int
|
||||
|
|
||||
|
||||
PYI046.py:9:7: PYI046 Private protocol `_Bar` is never used
|
||||
|
|
||||
9 | class _Bar(typing.Protocol):
|
||||
| ^^^^ PYI046
|
||||
10 | bar: int
|
||||
|
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,20 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI047.py:6:1: PYI047 Private TypeAlias `_UnusedPrivateTypeAlias` is never used
|
||||
|
|
||||
6 | _UnusedPrivateTypeAlias: TypeAlias = int | None
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI047
|
||||
7 | _T: typing.TypeAlias = str
|
||||
|
|
||||
|
||||
PYI047.py:7:1: PYI047 Private TypeAlias `_T` is never used
|
||||
|
|
||||
6 | _UnusedPrivateTypeAlias: TypeAlias = int | None
|
||||
7 | _T: typing.TypeAlias = str
|
||||
| ^^ PYI047
|
||||
8 |
|
||||
9 | # OK
|
||||
|
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI049.py:5:7: PYI049 Private TypedDict `_UnusedTypedDict` is never used
|
||||
|
|
||||
5 | class _UnusedTypedDict(TypedDict):
|
||||
| ^^^^^^^^^^^^^^^^ PYI049
|
||||
6 | foo: str
|
||||
|
|
||||
|
||||
PYI049.py:9:7: PYI049 Private TypedDict `_UnusedTypedDict2` is never used
|
||||
|
|
||||
9 | class _UnusedTypedDict2(typing.TypedDict):
|
||||
| ^^^^^^^^^^^^^^^^^ PYI049
|
||||
10 | bar: int
|
||||
|
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,24 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI051.py:4:18: PYI051 `Literal["foo"]` is redundant in a union with `str`
|
||||
|
|
||||
2 | from typing import Literal, TypeAlias, Union
|
||||
3 |
|
||||
4 | A: str | Literal["foo"]
|
||||
| ^^^^^ PYI051
|
||||
5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str]
|
||||
6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]]
|
||||
|
|
||||
|
||||
PYI051.py:9:31: PYI051 `Literal[1J]` is redundant in a union with `complex`
|
||||
|
|
||||
7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int]
|
||||
8 |
|
||||
9 | def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ...
|
||||
| ^^ PYI051
|
||||
10 |
|
||||
11 | # OK
|
||||
|
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,32 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI056.py:4:1: PYI056 Calling `.append()` on `__all__` may not be supported by all type checkers (use `+=` instead)
|
||||
|
|
||||
3 | # Errors
|
||||
4 | __all__.append("D")
|
||||
| ^^^^^^^^^^^^^^ PYI056
|
||||
5 | __all__.extend(["E", "Foo"])
|
||||
6 | __all__.remove("A")
|
||||
|
|
||||
|
||||
PYI056.py:5:1: PYI056 Calling `.extend()` on `__all__` may not be supported by all type checkers (use `+=` instead)
|
||||
|
|
||||
3 | # Errors
|
||||
4 | __all__.append("D")
|
||||
5 | __all__.extend(["E", "Foo"])
|
||||
| ^^^^^^^^^^^^^^ PYI056
|
||||
6 | __all__.remove("A")
|
||||
|
|
||||
|
||||
PYI056.py:6:1: PYI056 Calling `.remove()` on `__all__` may not be supported by all type checkers (use `+=` instead)
|
||||
|
|
||||
4 | __all__.append("D")
|
||||
5 | __all__.extend(["E", "Foo"])
|
||||
6 | __all__.remove("A")
|
||||
| ^^^^^^^^^^^^^^ PYI056
|
||||
7 |
|
||||
8 | # OK
|
||||
|
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user