[pyupgrade] Fix UP043 to apply to collections.abc.Generator and 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]
```
This commit is contained in:
cake-monotone 2024-10-03 21:06:15 +09:00 committed by GitHub
parent 7e3894f5b3
commit 3728d5b3a2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 64 additions and 7 deletions

View file

@ -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"

View file

@ -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<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

View file

@ -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"