astral-sh / ruff

An extremely fast Python linter and code formatter, written in Rust.
https://docs.astral.sh/ruff
MIT License
32.29k stars 1.08k forks source link

PyUpgrade rule UP007 does not work on forward reference string types #12945

Open goodspark opened 2 months ago

goodspark commented 2 months ago

Keywords: forward reference, pyupgrade, UP007

Python 3.12, also 3.10 Ruff 0.6.1, also 0.5.7 Command: ruff check .

Code:

Python file

x: Optional['Something']  # expect UP007 to trigger here -> x: 'Something | None'
y: Union[int, 'Something']  # expect UP007 to trigger here -> y: 'Something | int'
x2: Optional[Something]  # correctly caught by UP007
y2: Union[int, Something]  # correctly caught by UP007
class Something:
  pass

pyproject.toml

[project]
# As long as this is >=3.10 or any subset, like ==3.10, this bug will occur.
requires-python = ">=3.12"

[tool.ruff.lint]
extend-select = ["UP"]
extend-safe-fixes = ["UP007"]
charliermarsh commented 2 months ago

I believe that's because 'Something' | None is not a valid type annotation -- it will error at runtime.

charliermarsh commented 2 months ago

If you add from __future__ import annotations, we do correctly flag all four, since the type annotations are then deferred.

charliermarsh commented 2 months ago

So I think this is working as intended, AFAICT.

goodspark commented 2 months ago

I guess another fix I was envisioning was "Something | None" (note both Something and None are in strings).