-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flake8-type-checking
] Apply TC008
more eagerly in TYPE_CHECKING
blocks and disapply it in stubs
#15180
Merged
AlexWaygood
merged 10 commits into
astral-sh:main
from
Daverball:feat/tc008-typing-execution-context
Jan 8, 2025
Merged
[flake8-type-checking
] Apply TC008
more eagerly in TYPE_CHECKING
blocks and disapply it in stubs
#15180
Changes from 5 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
a775f51
[`flake8-type-checking`] Apply `TC008` more eagerly in typing context
Daverball 348fd86
Execution context doesn't work, since it's already set to typing inside
Daverball f119f26
Merge branch 'main' into feat/tc008-typing-execution-context
Daverball a9f2d80
Avoids false positives for true forward references
Daverball 39f4e10
Adds some use-before-define test cases
Daverball 44dccdc
Disable `TC008` in stubs. Clean up stuff that's no longer needed.
Daverball 5947f64
Update crates/ruff_linter/src/checkers/ast/mod.rs
Daverball 5db1af5
Applies suggested change
Daverball ea541a6
Adds note and link to `PYI020`
Daverball 9e8642f
more docs
AlexWaygood File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
25 changes: 25 additions & 0 deletions
25
crates/ruff_linter/resources/test/fixtures/flake8_type_checking/TC008.pyi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
from __future__ import annotations | ||
|
||
from typing import TypeAlias, TYPE_CHECKING | ||
|
||
from foo import Foo | ||
|
||
a: TypeAlias = 'int' # TC008 | ||
b: TypeAlias = 'Foo' # TC008 | ||
c: TypeAlias = 'Foo[str]' # TC008 | ||
d: TypeAlias = 'Foo.bar' # TC008 | ||
e: TypeAlias = 'Baz' # OK | ||
|
||
type B = 'Foo' # TC008 | ||
type C = 'Foo[str]' # TC008 | ||
type D = 'Foo.bar' # TC008 | ||
type E = 'Baz' # TC008 | ||
|
||
|
||
class Baz: | ||
a: TypeAlias = 'Baz' # False negative in stubs | ||
type A = 'Baz' # TC008 | ||
|
||
class Nested: | ||
a: TypeAlias = 'Baz' # False negative in stubs | ||
type A = 'Baz' # TC008 |
31 changes: 31 additions & 0 deletions
31
...uff_linter/resources/test/fixtures/flake8_type_checking/TC008_typing_execution_context.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
from __future__ import annotations | ||
|
||
from typing import TypeAlias, TYPE_CHECKING | ||
|
||
from foo import Foo | ||
|
||
if TYPE_CHECKING: | ||
from typing import Dict | ||
|
||
OptStr: TypeAlias = str | None | ||
Bar: TypeAlias = Foo[int] | ||
|
||
a: TypeAlias = 'int' # TC008 | ||
b: TypeAlias = 'Dict' # TC008 | ||
c: TypeAlias = 'Foo' # TC008 | ||
d: TypeAlias = 'Foo[str]' # TC008 | ||
e: TypeAlias = 'Foo.bar' # TC008 | ||
f: TypeAlias = 'Foo | None' # TC008 | ||
g: TypeAlias = 'OptStr' # TC008 | ||
h: TypeAlias = 'Bar' # TC008 | ||
i: TypeAlias = Foo['str'] # TC008 | ||
j: TypeAlias = 'Baz' # OK (this would be treated as use before define) | ||
k: TypeAlias = 'k | None' # False negative in type checking block | ||
l: TypeAlias = 'int' | None # TC008 (because TC010 is not enabled) | ||
m: TypeAlias = ('int' # TC008 | ||
| None) | ||
n: TypeAlias = ('int' # TC008 (fix removes comment currently) | ||
' | None') | ||
|
||
|
||
class Baz: ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
201 changes: 201 additions & 0 deletions
201
...apshots/ruff_linter__rules__flake8_type_checking__tests__quoted-type-alias_TC008.pyi.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
--- | ||
source: crates/ruff_linter/src/rules/flake8_type_checking/mod.rs | ||
--- | ||
TC008.pyi:7:16: TC008 [*] Remove quotes from type alias | ||
| | ||
5 | from foo import Foo | ||
6 | | ||
7 | a: TypeAlias = 'int' # TC008 | ||
| ^^^^^ TC008 | ||
8 | b: TypeAlias = 'Foo' # TC008 | ||
9 | c: TypeAlias = 'Foo[str]' # TC008 | ||
| | ||
= help: Remove quotes | ||
|
||
ℹ Safe fix | ||
4 4 | | ||
5 5 | from foo import Foo | ||
6 6 | | ||
7 |-a: TypeAlias = 'int' # TC008 | ||
7 |+a: TypeAlias = int # TC008 | ||
8 8 | b: TypeAlias = 'Foo' # TC008 | ||
9 9 | c: TypeAlias = 'Foo[str]' # TC008 | ||
10 10 | d: TypeAlias = 'Foo.bar' # TC008 | ||
|
||
TC008.pyi:8:16: TC008 [*] Remove quotes from type alias | ||
| | ||
7 | a: TypeAlias = 'int' # TC008 | ||
8 | b: TypeAlias = 'Foo' # TC008 | ||
| ^^^^^ TC008 | ||
9 | c: TypeAlias = 'Foo[str]' # TC008 | ||
10 | d: TypeAlias = 'Foo.bar' # TC008 | ||
| | ||
= help: Remove quotes | ||
|
||
ℹ Safe fix | ||
5 5 | from foo import Foo | ||
6 6 | | ||
7 7 | a: TypeAlias = 'int' # TC008 | ||
8 |-b: TypeAlias = 'Foo' # TC008 | ||
8 |+b: TypeAlias = Foo # TC008 | ||
9 9 | c: TypeAlias = 'Foo[str]' # TC008 | ||
10 10 | d: TypeAlias = 'Foo.bar' # TC008 | ||
11 11 | e: TypeAlias = 'Baz' # OK | ||
|
||
TC008.pyi:9:16: TC008 [*] Remove quotes from type alias | ||
| | ||
7 | a: TypeAlias = 'int' # TC008 | ||
8 | b: TypeAlias = 'Foo' # TC008 | ||
9 | c: TypeAlias = 'Foo[str]' # TC008 | ||
| ^^^^^^^^^^ TC008 | ||
10 | d: TypeAlias = 'Foo.bar' # TC008 | ||
11 | e: TypeAlias = 'Baz' # OK | ||
| | ||
= help: Remove quotes | ||
|
||
ℹ Safe fix | ||
6 6 | | ||
7 7 | a: TypeAlias = 'int' # TC008 | ||
8 8 | b: TypeAlias = 'Foo' # TC008 | ||
9 |-c: TypeAlias = 'Foo[str]' # TC008 | ||
9 |+c: TypeAlias = Foo[str] # TC008 | ||
10 10 | d: TypeAlias = 'Foo.bar' # TC008 | ||
11 11 | e: TypeAlias = 'Baz' # OK | ||
12 12 | | ||
|
||
TC008.pyi:10:16: TC008 [*] Remove quotes from type alias | ||
| | ||
8 | b: TypeAlias = 'Foo' # TC008 | ||
9 | c: TypeAlias = 'Foo[str]' # TC008 | ||
10 | d: TypeAlias = 'Foo.bar' # TC008 | ||
| ^^^^^^^^^ TC008 | ||
11 | e: TypeAlias = 'Baz' # OK | ||
| | ||
= help: Remove quotes | ||
|
||
ℹ Safe fix | ||
7 7 | a: TypeAlias = 'int' # TC008 | ||
8 8 | b: TypeAlias = 'Foo' # TC008 | ||
9 9 | c: TypeAlias = 'Foo[str]' # TC008 | ||
10 |-d: TypeAlias = 'Foo.bar' # TC008 | ||
10 |+d: TypeAlias = Foo.bar # TC008 | ||
11 11 | e: TypeAlias = 'Baz' # OK | ||
12 12 | | ||
13 13 | type B = 'Foo' # TC008 | ||
|
||
TC008.pyi:13:10: TC008 [*] Remove quotes from type alias | ||
| | ||
11 | e: TypeAlias = 'Baz' # OK | ||
12 | | ||
13 | type B = 'Foo' # TC008 | ||
| ^^^^^ TC008 | ||
14 | type C = 'Foo[str]' # TC008 | ||
15 | type D = 'Foo.bar' # TC008 | ||
| | ||
= help: Remove quotes | ||
|
||
ℹ Safe fix | ||
10 10 | d: TypeAlias = 'Foo.bar' # TC008 | ||
11 11 | e: TypeAlias = 'Baz' # OK | ||
12 12 | | ||
13 |-type B = 'Foo' # TC008 | ||
13 |+type B = Foo # TC008 | ||
14 14 | type C = 'Foo[str]' # TC008 | ||
15 15 | type D = 'Foo.bar' # TC008 | ||
16 16 | type E = 'Baz' # TC008 | ||
|
||
TC008.pyi:14:10: TC008 [*] Remove quotes from type alias | ||
| | ||
13 | type B = 'Foo' # TC008 | ||
14 | type C = 'Foo[str]' # TC008 | ||
| ^^^^^^^^^^ TC008 | ||
15 | type D = 'Foo.bar' # TC008 | ||
16 | type E = 'Baz' # TC008 | ||
| | ||
= help: Remove quotes | ||
|
||
ℹ Safe fix | ||
11 11 | e: TypeAlias = 'Baz' # OK | ||
12 12 | | ||
13 13 | type B = 'Foo' # TC008 | ||
14 |-type C = 'Foo[str]' # TC008 | ||
14 |+type C = Foo[str] # TC008 | ||
15 15 | type D = 'Foo.bar' # TC008 | ||
16 16 | type E = 'Baz' # TC008 | ||
17 17 | | ||
|
||
TC008.pyi:15:10: TC008 [*] Remove quotes from type alias | ||
| | ||
13 | type B = 'Foo' # TC008 | ||
14 | type C = 'Foo[str]' # TC008 | ||
15 | type D = 'Foo.bar' # TC008 | ||
| ^^^^^^^^^ TC008 | ||
16 | type E = 'Baz' # TC008 | ||
| | ||
= help: Remove quotes | ||
|
||
ℹ Safe fix | ||
12 12 | | ||
13 13 | type B = 'Foo' # TC008 | ||
14 14 | type C = 'Foo[str]' # TC008 | ||
15 |-type D = 'Foo.bar' # TC008 | ||
15 |+type D = Foo.bar # TC008 | ||
16 16 | type E = 'Baz' # TC008 | ||
17 17 | | ||
18 18 | | ||
|
||
TC008.pyi:16:10: TC008 [*] Remove quotes from type alias | ||
| | ||
14 | type C = 'Foo[str]' # TC008 | ||
15 | type D = 'Foo.bar' # TC008 | ||
16 | type E = 'Baz' # TC008 | ||
| ^^^^^ TC008 | ||
| | ||
= help: Remove quotes | ||
|
||
ℹ Safe fix | ||
13 13 | type B = 'Foo' # TC008 | ||
14 14 | type C = 'Foo[str]' # TC008 | ||
15 15 | type D = 'Foo.bar' # TC008 | ||
16 |-type E = 'Baz' # TC008 | ||
16 |+type E = Baz # TC008 | ||
17 17 | | ||
18 18 | | ||
19 19 | class Baz: | ||
|
||
TC008.pyi:21:14: TC008 [*] Remove quotes from type alias | ||
| | ||
19 | class Baz: | ||
20 | a: TypeAlias = 'Baz' # False negative in stubs | ||
21 | type A = 'Baz' # TC008 | ||
| ^^^^^ TC008 | ||
22 | | ||
23 | class Nested: | ||
| | ||
= help: Remove quotes | ||
|
||
ℹ Safe fix | ||
18 18 | | ||
19 19 | class Baz: | ||
20 20 | a: TypeAlias = 'Baz' # False negative in stubs | ||
21 |- type A = 'Baz' # TC008 | ||
21 |+ type A = Baz # TC008 | ||
22 22 | | ||
23 23 | class Nested: | ||
24 24 | a: TypeAlias = 'Baz' # False negative in stubs | ||
|
||
TC008.pyi:25:18: TC008 [*] Remove quotes from type alias | ||
| | ||
23 | class Nested: | ||
24 | a: TypeAlias = 'Baz' # False negative in stubs | ||
25 | type A = 'Baz' # TC008 | ||
| ^^^^^ TC008 | ||
| | ||
= help: Remove quotes | ||
|
||
ℹ Safe fix | ||
22 22 | | ||
23 23 | class Nested: | ||
24 24 | a: TypeAlias = 'Baz' # False negative in stubs | ||
25 |- type A = 'Baz' # TC008 | ||
25 |+ type A = Baz # TC008 |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we also add a note to the docs for this rule pointing users to PYI020 for stub files? (And we could similarly add a note to the PYI020 docs pointing users to this rule for runtime files)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AlexWaygood Do you happen to know how to cross reference rules from another rule? I couldn't find any examples. Does linking to the corresponding enum variant work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm... no, I'm not sure what the best solution is there. @MichaReiser, do you have any guidance/insight?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I chatted to @MichaReiser this morning and we concluded that neither of us knows of a great way to do this :-) hardcoding a link to https://docs.astral.sh/ruff/rules/quoted-annotation-in-stub/ might be best for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just double checked and yes, there's no custom handling in
ruff/crates/ruff_dev/src/generate_docs.rs
Lines 118 to 187 in bb12fe9
It might be possible to use relative links as we do in the linter documentation
ruff/docs/linter.md
Lines 165 to 167 in 68eb0a2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could probably also link
/rules/quoted-annotation-in-stub.md
so it's only semi-hardlinked, I had to do something similar in a setting to link to a rule.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AlexWaygood I think a reference from TC008 to PYI020 is sufficient. A reference the other way doesn't make that much sense to me, since most PYI rules are so specific to stub files.