diff --git a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP043.py b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP043.py index c4ebf662a67cd..3968a16a54a83 100644 --- a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP043.py +++ b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP043.py @@ -1,4 +1,4 @@ -from typing import Generator, AsyncGenerator +from collections.abc import Generator, AsyncGenerator def func() -> Generator[int, None, None]: @@ -39,3 +39,14 @@ async def func() -> AsyncGenerator[int]: async def func() -> AsyncGenerator[int, int]: foo = yield 42 return foo + + +from typing import Generator, AsyncGenerator + + +def func() -> Generator[str, None, None]: + yield "hello" + + +async def func() -> AsyncGenerator[str, None]: + yield "hello" diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_default_type_args.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_default_type_args.rs index 8349eae78fce0..4ef77fbc30f71 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_default_type_args.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_default_type_args.rs @@ -19,7 +19,7 @@ use crate::checkers::ast::Checker; /// ## Examples /// /// ```python -/// from typing import Generator, AsyncGenerator +/// from collections.abc import Generator, AsyncGenerator /// /// /// def sync_gen() -> Generator[int, None, None]: @@ -33,7 +33,7 @@ use crate::checkers::ast::Checker; /// Use instead: /// /// ```python -/// from typing import Generator, AsyncGenerator +/// from collections.abc import Generator, AsyncGenerator /// /// /// def sync_gen() -> Generator[int]: @@ -47,6 +47,7 @@ use crate::checkers::ast::Checker; /// ## References /// /// - [PEP 696 – Type Defaults for Type Parameters](https://peps.python.org/pep-0696/) +/// - [Annotating generators and coroutines](https://docs.python.org/3.13/library/typing.html#annotating-generators-and-coroutines) /// - [typing.Generator](https://docs.python.org/3.13/library/typing.html#typing.Generator) /// - [typing.AsyncGenerator](https://docs.python.org/3.13/library/typing.html#typing.AsyncGenerator) #[violation] @@ -140,9 +141,20 @@ impl DefaultedTypeAnnotation { /// includes default type arguments. fn from_expr(expr: &Expr, semantic: &ruff_python_semantic::SemanticModel) -> Option { let qualified_name = semantic.resolve_qualified_name(expr)?; - if semantic.match_typing_qualified_name(&qualified_name, "Generator") { + + if semantic.match_typing_qualified_name(&qualified_name, "Generator") + || matches!( + qualified_name.segments(), + ["collections", "abc", "Generator"] + ) + { Some(Self::Generator) - } else if semantic.match_typing_qualified_name(&qualified_name, "AsyncGenerator") { + } else if semantic.match_typing_qualified_name(&qualified_name, "AsyncGenerator") + || matches!( + qualified_name.segments(), + ["collections", "abc", "AsyncGenerator"] + ) + { Some(Self::AsyncGenerator) } else { None diff --git a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP043.py.snap b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP043.py.snap index 4198822ad3363..65243085cce44 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP043.py.snap +++ b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP043.py.snap @@ -10,7 +10,7 @@ UP043.py:4:15: UP043 [*] Unnecessary default type arguments = help: Remove default type arguments ℹ Safe fix -1 1 | from typing import Generator, AsyncGenerator +1 1 | from collections.abc import Generator, AsyncGenerator 2 2 | 3 3 | 4 |-def func() -> Generator[int, None, None]: @@ -72,4 +72,38 @@ UP043.py:31:21: UP043 [*] Unnecessary default type arguments 31 |+async def func() -> AsyncGenerator[int]: 32 32 | yield 42 33 33 | -34 34 | +34 34 | + +UP043.py:47:15: UP043 [*] Unnecessary default type arguments + | +47 | def func() -> Generator[str, None, None]: + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ UP043 +48 | yield "hello" + | + = help: Remove default type arguments + +ℹ Safe fix +44 44 | from typing import Generator, AsyncGenerator +45 45 | +46 46 | +47 |-def func() -> Generator[str, None, None]: + 47 |+def func() -> Generator[str]: +48 48 | yield "hello" +49 49 | +50 50 | + +UP043.py:51:21: UP043 [*] Unnecessary default type arguments + | +51 | async def func() -> AsyncGenerator[str, None]: + | ^^^^^^^^^^^^^^^^^^^^^^^^^ UP043 +52 | yield "hello" + | + = help: Remove default type arguments + +ℹ Safe fix +48 48 | yield "hello" +49 49 | +50 50 | +51 |-async def func() -> AsyncGenerator[str, None]: + 51 |+async def func() -> AsyncGenerator[str]: +52 52 | yield "hello"