Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[pyupgrade] - add PEP646 Unpack conversion to * with fix (UP044) #13988

Merged
merged 5 commits into from
Oct 31, 2024

Conversation

diceroll123
Copy link
Contributor

@diceroll123 diceroll123 commented Oct 30, 2024

Summary

Adds Unpack[...] -> *... for Py311+

Closes #13891

Test Plan

cargo test

@charliermarsh charliermarsh added the rule Implementing or modifying a lint rule label Oct 30, 2024
@charliermarsh
Copy link
Member

Nice, thanks.

Copy link
Contributor

github-actions bot commented Oct 30, 2024

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

ℹ️ ecosystem check detected linter changes. (+18 -0 violations, +0 -0 fixes in 1 projects; 53 projects unchanged)

rotki/rotki (+18 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --output-format concise --preview

+ rotkehlchen/db/cache.py:73:36: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/cache.py:77:36: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/cache.py:81:36: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/cache.py:85:36: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/dbhandler.py:699:23: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/dbhandler.py:708:23: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/dbhandler.py:717:23: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/dbhandler.py:726:23: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/dbhandler.py:735:23: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/dbhandler.py:744:23: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/dbhandler.py:753:23: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/dbhandler.py:776:23: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/dbhandler.py:786:23: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/dbhandler.py:796:23: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/dbhandler.py:806:23: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/dbhandler.py:816:23: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/dbhandler.py:826:23: UP044 [*] Use `*` for unpacking
+ rotkehlchen/db/dbhandler.py:836:23: UP044 [*] Use `*` for unpacking

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
UP044 18 18 0 0 0

Copy link
Member

@MichaReiser MichaReiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great. Thank you!

Could you add one more test case for an unpacking where the target is a binary expression? This is is semantically invalid but it isn't a syntax error and we should at least avoid introducing a syntax error (I don't think we do, but we should make sure of it).


if checker.settings.preview.is_enabled() {
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
format!("*{inner}"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unpacking anything other than a Tuple or TypeVarTuple is semantically incorrect but it isn't a syntax error. For example:

def foo(*args: Unpack[int | str]) -> None:

Could we add a test asserting that the suggested fix doesn't suggest invalid syntax?


let inner = checker.locator().slice(slice.as_ref());

if checker.settings.preview.is_enabled() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this condition required when the rule itself is in preview?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silly me!

@dhruvmanila dhruvmanila added the preview Related to preview mode features label Oct 30, 2024
Comment on lines 72 to 75
if slice.is_bin_op_expr() {
// fixing this would introduce a syntax error
return;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applying the fix seems "safe enough":

def foo(*args: *int | str) -> None: pass  # not supported

Isn't invalid syntax

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, true, it gives a TypeError actually.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went ahead and converted it to an allowlist. I don't think any expressions other than name, subscript, and attribute are valid in this position.

@MichaReiser MichaReiser enabled auto-merge (squash) October 31, 2024 06:54
@MichaReiser MichaReiser merged commit 2d917d7 into astral-sh:main Oct 31, 2024
16 checks passed
@sibarras
Copy link

sibarras commented Nov 1, 2024

It's giving SyntaxError when changing this:

from typing import TypedDict, Unpack


class KWs(TypedDict):
    """kws."""

    foo: str


def func(**kwargs: Unpack[KWs]) -> None:  # <-- original
    """Func."""
    _ = kwargs

to this:

from typing import TypedDict, Unpack


class KWs(TypedDict):
    """kws."""

    foo: str


def func(**kwargs: *KWs) -> None:  # <-- modified
    """Func."""
    _ = kwargs

@MichaReiser
Copy link
Member

@sibarras see #14047

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
preview Related to preview mode features rule Implementing or modifying a lint rule
Projects
None yet
Development

Successfully merging this pull request may close these issues.

pyupgrade rule for Unpack
5 participants