[pyupgrade] Fix false positive for TypeVar with default on Python <3.13 (UP046,UP047)#21045
[pyupgrade] Fix false positive for TypeVar with default on Python <3.13 (UP046,UP047)#21045ntBre merged 1 commit intoastral-sh:mainfrom
pyupgrade] Fix false positive for TypeVar with default on Python <3.13 (UP046,UP047)#21045Conversation
|
ntBre
left a comment
There was a problem hiding this comment.
Thank you! The code change and new comments look great, but would you mind converting your manual tests into regression tests in the repo?
If you already have separate Python files, they would fit nicely as new test cases alongside files like UP046_1.py and test_case entries here:
ruff/crates/ruff_linter/src/rules/pyupgrade/mod.rs
Lines 114 to 126 in 83a3bc4
Although you may need a separate test function so that you can set the version like we do here:
|
Thanks for the review! As an update - I got busy with festivals around; I plan to complete this in the next 2-3 days. |
….13 (`UP046`,`UP047`) Type default for Type parameter was added in Python 3.13 (PEP 696). `typing_extensions.TypeVar` backports the default argument to earlier versions. `UP046` & `UP047` were getting triggered when typing_extensions.TypeVar with `default` argument was used on python version < 3.13 It shouldn't be triggered for python version < 3.13 This commit fixes the bug by adding a python version check before triggering them. Fixes astral-sh#20929. Signed-off-by: Prakhar Pratyush <[email protected]>
056c130 to
a559cb8
Compare
|
@ntBre I've added tests. Ready to review. |
pyupgrade] Fix false positive for TypeVar with default on Python<3.13 (UP046,UP047)pyupgrade] Fix false positive for TypeVar with default on Python <3.13 (UP046,UP047)
* origin/main: (21 commits) [ty] Update "constraint implication" relation to work on constraints between two typevars (#21068) [`flake8-type-checking`] Fix `TC003` false positive with `future-annotations` (#21125) [ty] Fix lookup of `__new__` on instances (#21147) Fix syntax error false positive on nested alternative patterns (#21104) [`pyupgrade`] Fix false positive for `TypeVar` with default on Python <3.13 (`UP046`,`UP047`) (#21045) [ty] Reachability and narrowing for enum methods (#21130) [ty] Use `range` instead of custom `IntIterable` (#21138) [`ruff`] Add support for additional eager conversion patterns (`RUF065`) (#20657) [`ruff-ecosystem`] Fix CLI crash on Python 3.14 (#21092) [ty] Infer type of `self` for decorated methods and properties (#21123) [`flake8-bandit`] Fix correct example for `S308` (#21128) [ty] Dont provide goto definition for definitions which are not reexported in builtins (#21127) [`airflow`] warning `airflow....DAG.create_dagrun` has been removed (`AIR301`) (#21093) [ty] follow the breaking API changes made in salsa-rs/salsa#1015 (#21117) [ty] Rename `Type::into_nominal_instance` (#21124) [ty] Filter out "unimported" from the current module [ty] Add evaluation test for auto-import including symbols in current module [ty] Refactor `ty_ide` completion tests [ty] Render `import <...>` in completions when "label details" isn't supported [`refurb`] Preserve digit separators in `Decimal` constructor (`FURB157`) (#20588) ...
Summary
Type default for Type parameter was added in Python 3.13 (PEP 696).
typing_extensions.TypeVarbackports the default argument to earlier versions.UP046&UP047were getting triggered whentyping_extensions.TypeVarwithdefaultargument was used on python version < 3.13It shouldn't be triggered for python version < 3.13
This commit fixes the bug by adding a python version check before triggering them.
Fixes #20929.
Test Plan
Manual testing 1
As the issue author pointed out in #20929 (comment), ran the following on
mainbranch:Output
Compiling ruff_linter v0.14.1 (/Users/prakhar/ruff/crates/ruff_linter) Compiling ruff v0.14.1 (/Users/prakhar/ruff/crates/ruff) Compiling ruff_graph v0.1.0 (/Users/prakhar/ruff/crates/ruff_graph) Compiling ruff_workspace v0.0.0 (/Users/prakhar/ruff/crates/ruff_workspace) Compiling ruff_server v0.2.2 (/Users/prakhar/ruff/crates/ruff_server) Finished `dev` profile [unoptimized + debuginfo] target(s) in 6.72s Running `target/debug/ruff check ../efax/ --target-version py312 --no-cache` UP046 Generic class `ExpectationParametrization` uses `Generic` subclass instead of type parameters --> /Users/prakhar/efax/efax/_src/expectation_parametrization.py:17:48 | 17 | class ExpectationParametrization(Distribution, Generic[NP]): | ^^^^^^^^^^^ 18 | """The expectation parametrization of an exponential family distribution. | help: Use type parameters UP046 Generic class `ExpToNat` uses `Generic` subclass instead of type parameters --> /Users/prakhar/efax/efax/_src/mixins/exp_to_nat/exp_to_nat.py:27:68 | 26 | @dataclass 27 | class ExpToNat(ExpectationParametrization[NP], SimpleDistribution, Generic[NP]): | ^^^^^^^^^^^ 28 | """This mixin implements the conversion from expectation to natural parameters. | help: Use type parameters UP046 Generic class `HasEntropyEP` uses `Generic` subclass instead of type parameters --> /Users/prakhar/efax/efax/_src/mixins/has_entropy.py:25:20 | 23 | HasEntropy, 24 | JaxAbstractClass, 25 | Generic[NP]): | ^^^^^^^^^^^ 26 | @abstract_jit 27 | @abstractmethod | help: Use type parameters UP046 Generic class `HasEntropyNP` uses `Generic` subclass instead of type parameters --> /Users/prakhar/efax/efax/_src/mixins/has_entropy.py:64:20 | 62 | class HasEntropyNP(NaturalParametrization[EP], 63 | HasEntropy, 64 | Generic[EP]): | ^^^^^^^^^^^ 65 | @jit 66 | @final | help: Use type parameters UP046 Generic class `NaturalParametrization` uses `Generic` subclass instead of type parameters --> /Users/prakhar/efax/efax/_src/natural_parametrization.py:43:30 | 41 | class NaturalParametrization(Distribution, 42 | JaxAbstractClass, 43 | Generic[EP, Domain]): | ^^^^^^^^^^^^^^^^^^^ 44 | """The natural parametrization of an exponential family distribution. | help: Use type parameters UP046 Generic class `Structure` uses `Generic` subclass instead of type parameters --> /Users/prakhar/efax/efax/_src/structure/structure.py:31:17 | 30 | @dataclass 31 | class Structure(Generic[P]): | ^^^^^^^^^^ 32 | """This class generalizes the notion of type for Distribution objects. | help: Use type parameters UP046 Generic class `DistributionInfo` uses `Generic` subclass instead of type parameters --> /Users/prakhar/efax/tests/distribution_info.py:20:24 | 20 | class DistributionInfo(Generic[NP, EP, Domain]): | ^^^^^^^^^^^^^^^^^^^^^^^ 21 | def __init__(self, dimensions: int = 1, safety: float = 0.0) -> None: 22 | super().__init__() | help: Use type parameters Found 7 errors. No fixes available (7 hidden fixes can be enabled with the `--unsafe-fixes` option).Running it after the changes:
ruff % cargo run -p ruff -- check ../efax/ --target-version py312 --no-cache Compiling ruff_linter v0.14.1 (/Users/prakhar/ruff/crates/ruff_linter) Compiling ruff v0.14.1 (/Users/prakhar/ruff/crates/ruff) Compiling ruff_graph v0.1.0 (/Users/prakhar/ruff/crates/ruff_graph) Compiling ruff_workspace v0.0.0 (/Users/prakhar/ruff/crates/ruff_workspace) Compiling ruff_server v0.2.2 (/Users/prakhar/ruff/crates/ruff_server) Finished `dev` profile [unoptimized + debuginfo] target(s) in 7.86s Running `target/debug/ruff check ../efax/ --target-version py312 --no-cache` All checks passed!Manual testing 2
Ran the check on the following script (mainly to verify
UP047):On
mainbranch:Output
Compiling ruff_linter v0.14.1 (/Users/prakhar/ruff/crates/ruff_linter) Compiling ruff v0.14.1 (/Users/prakhar/ruff/crates/ruff) Compiling ruff_graph v0.1.0 (/Users/prakhar/ruff/crates/ruff_graph) Compiling ruff_workspace v0.0.0 (/Users/prakhar/ruff/crates/ruff_workspace) Compiling ruff_server v0.2.2 (/Users/prakhar/ruff/crates/ruff_server) Finished `dev` profile [unoptimized + debuginfo] target(s) in 7.43s Running `target/debug/ruff check /Users/prakhar/up046.py --target-version py312 --preview --no-cache` UP047 Generic function `generic_function` should use type parameters --> /Users/prakhar/up046.py:10:5 | 10 | def generic_function(var: T) -> T: | ^^^^^^^^^^^^^^^^^^^^^^^^ 11 | return var | help: Use type parameters UP046 Generic class `GenericClass` uses `Generic` subclass instead of type parameters --> /Users/prakhar/up046.py:17:20 | 17 | class GenericClass(Generic[Q]): | ^^^^^^^^^^ 18 | var: Q | help: Use type parameters Found 2 errors. No fixes available (2 hidden fixes can be enabled with the `--unsafe-fixes` option).After the fix (this branch):