Skip to content

Commit

Permalink
[pyupgrade] Fix UP043 to apply to collections.abc.Generator and `…
Browse files Browse the repository at this point in the history
…collections.abc.AsyncGenerator` (#13611)

## Summary

fix #13602 

Currently, `UP043` only applies to typing.Generator, but it should also
support collections.abc.Generator.

This update ensures `UP043` correctly handles both
`collections.abc.Generator` and `collections.abc.AsyncGenerator`

### UP043
> `UP043`
> Python 3.13 introduced the ability for type parameters to specify
default values. As such, the default type arguments for some types in
the standard library (e.g., Generator, AsyncGenerator) are now optional.
> Omitting type parameters that match the default values can make the
code more concise and easier to read.

```py
Generator[int, None, None] -> Generator[int]
```
  • Loading branch information
cake-monotone authored Oct 3, 2024
1 parent 7e3894f commit 3728d5b
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 7 deletions.
13 changes: 12 additions & 1 deletion crates/ruff_linter/resources/test/fixtures/pyupgrade/UP043.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Generator, AsyncGenerator
from collections.abc import Generator, AsyncGenerator


def func() -> Generator[int, None, None]:
Expand Down Expand Up @@ -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"
Original file line number Diff line number Diff line change
Expand Up @@ -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]:
Expand All @@ -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]:
Expand All @@ -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]
Expand Down Expand Up @@ -140,9 +141,20 @@ impl DefaultedTypeAnnotation {
/// includes default type arguments.
fn from_expr(expr: &Expr, semantic: &ruff_python_semantic::SemanticModel) -> Option<Self> {
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]:
Expand Down Expand Up @@ -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"

0 comments on commit 3728d5b

Please sign in to comment.