Skip to content
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] Avoid false positives for | in TC008 #15201

Merged

Conversation

Daverball
Copy link
Contributor

This is a follow-up to #15180

Summary

| is not a valid runtime operation between types pre Python 3.10, so we should avoid unquoting the type expression.

Additionally most type checkers don't care about the execution context, so while they will allow | between types in stub files for convenience, they will still disallow it in type checking blocks, since those are treated as regular runtime code.

Test Plan

cargo nextest run

@Daverball

This comment was marked as outdated.

Copy link
Contributor

github-actions bot commented Dec 30, 2024

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

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

apache/airflow (+0 -2 violations, +0 -0 fixes)

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

- airflow/decorators/condition.py:32:35: TC008 [*] Remove quotes from type alias
- airflow/decorators/condition.py:33:35: TC008 [*] Remove quotes from type alias

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
TC008 2 0 2 0 0

@Daverball

This comment was marked as resolved.

@MichaReiser
Copy link
Member

Reviewing this PR is a bit challenging right now because it's based on #15180 and I can't change the base because your an external contributor. I suggest we wait with reviewing until the base PR is merged. Please ping us if we happen to forget to review the PR after #15180 is merged.

@Daverball Daverball force-pushed the bugfix/tc008-union-syntax-pre-py310 branch from c5ad656 to 89d35c2 Compare January 8, 2025 12:40
@Daverball
Copy link
Contributor Author

@MichaReiser @AlexWaygood You should be able to review this now

@dhruvmanila dhruvmanila added rule Implementing or modifying a lint rule preview Related to preview mode features labels Jan 8, 2025
@Daverball
Copy link
Contributor Author

Daverball commented Jan 8, 2025

The ecosystem results make sense to me now. Since airflow targets Python 3.9+ mypy would flag those type aliases if they were unquoted. So a TC008 shouldn't trigger, despite there being no runtime effects.

@dangotbanned
Copy link

@Daverball

I've got some false positives that seem to be this, in combination with being in a TYPE_CHECKING block:

Should I open an issue for this?

@Daverball
Copy link
Contributor Author

@dangotbanned Yes, that's this bug, it can also be hit in different contexts, it just previously wasn't as likely to be hit in TYPE_CHECKING blocks, because those also weren't handled properly yet.

Feel free to open an issue, if you think it makes it easier for others to discover that this issue is known and will be fixed.

@dangotbanned
Copy link

All good, thanks for clarifying @Daverball 🙂

@Daverball
Copy link
Contributor Author

@MichaReiser @AlexWaygood Bumping this again, now that the 0.9 rush is over.

@MichaReiser
Copy link
Member

Thanks for the ping. We decided that Alex should spend more time on Red Knot which leaves me as the main reviewer. I'll try to take a look but I'm not sure when I'll get to it because it also requires familiarizing myself with the type checking rules. Sorry for the long wait.

@Daverball
Copy link
Contributor Author

@MichaReiser Alright, no worries. This PR should be fairly easy to review, even with surface knowledge, the only thing you need to know is that the union syntax | is only allowed to be used at runtime starting with Python 3.10, prior to that it will raise a TypeError, since type did not provide a __or__ method that returns UnionType.

However type checkers still allow you to use the new syntax in older Python versions in non-runtime contexts like implicit/explicit forward references. But type checkers generally don't consider statements in TYPE_CHECKING blocks to be non-runtime. It is treated like any other code block, the only thing they do, is statically evaluate TYPE_CHECKING to True (and entirely skip analysis of code that isn't reachable this way).

There is a tiny bit of extra complexity for avoiding false negatives for typing.Annotated. This part should probably have been changed in #15180 in hindsight. All you need to know here is, that only the first argument to typing.Annotated is a type expression, so the rest of the arguments shouldn't influence our decision whether or not we can unquote.

TLDR: Annotated type alias value expressions always need to be considered in runtime context, unless they're explicitly wrapped in quotes. As a consequence, if a forward reference in the value expression uses |, we're not allowed to remove the quotes if the target python version is 3.9 or below.

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.

Thanks for the detailed explanation! It helped me to build the necessary context quickly to review the PR. I really appreciate it.

Looks good and thanks again for taking the time to explain the changes in detail to me.

@MichaReiser MichaReiser merged commit 73488e7 into astral-sh:main Jan 15, 2025
21 checks passed
@Daverball Daverball deleted the bugfix/tc008-union-syntax-pre-py310 branch January 15, 2025 13:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in 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.

4 participants