Skip to content

Conversation

IDrokin117
Copy link
Contributor

Summary

Resolves #18165

Added pattern ["sys", "version_info", "major"] to the existing matches for sys.version_info to ensure consistent handling of both the base object and its major version attribute.

Test Plan

cargo nextest run and cargo insta test

added sys.version_info attribute .major support
added fixtures to UP036_5.py
updated snapshot

issue: astral-sh#18165
@ntBre ntBre added the rule Implementing or modifying a lint rule label Jun 11, 2025
Copy link
Contributor

github-actions bot commented Jun 11, 2025

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

Copy link
Contributor

@ntBre ntBre 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 working on this! I think this looks good, I just had one suggestion for making the check a bit stricter. What do you think?

Comment on lines 109 to 114
.resolve_qualified_name(map_subscript(left))
.is_some_and(|qualified_name| {
matches!(qualified_name.segments(), ["sys", "version_info"])
matches!(
qualified_name.segments(),
["sys", "version_info"] | ["sys", "version_info", "major"]
)
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems pretty minor, especially because the fix is always unsafe, but this also calls map_subscript on sys.version_info.major, which we might not really want to allow. In other words, I think this would fix code like

import sys

if sys.version_info.major[1] > 3:
    print(3)
else:
    print(2)

to avoid the TypeError that would otherwise occur:

>>> import sys
>>> sys.version_info.major[1]
Traceback (most recent call last):
  File "<python-input-1>", line 1, in <module>
    sys.version_info.major[1]
    ~~~~~~~~~~~~~~~~~~~~~~^^^
TypeError: 'int' object is not subscriptable

It's much more convenient to add the check here, but I might lean slightly toward a separate resolve_qualified_name call to avoid map_subscript on major.

Copy link
Contributor

Choose a reason for hiding this comment

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

This isn't related to your changes, but I guess this rule is pretty lenient with these comparisons anyway. For example, it still applies to comparisons like these that would also fail at runtime:

import sys

if sys.version_info < 3: ...
if sys.version_info[0] < (3, 0): ...

Copy link
Contributor Author

@IDrokin117 IDrokin117 Jun 12, 2025

Choose a reason for hiding this comment

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

@ntBre Thanks for the review. Point taken. I've added a dedicated resolve_qualified_name call for the .major case. Could you take a look at the revised approach?
I also want to implement the fix for your second remark. Should this go into the current PR or would you prefer a separate PR?

added separate fn is_valid_version_info
split and added separate .major check without map_subscript()
@IDrokin117 IDrokin117 requested a review from ntBre June 14, 2025 15:55
Copy link
Contributor

@ntBre ntBre left a comment

Choose a reason for hiding this comment

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

Nice, thanks!

I also want to implement the fix for your second remark. Should this go into the current PR or would you prefer a separate PR?

Let's go ahead and merge the changes from this PR and leave the rest for a follow-up. We should probably also open an issue for the invalid comparisons to see if anyone else has feedback on possible fixes. There's currently a related rule (unrecognized-version-info-check (PYI003), and really PYI003-PYI006) that I think only applies in .pyi files. So there are already at least two options for detecting these issues: adding them to UP036 or PYI003.

…utdated_version_block.rs

replace `checker` argument with `semantic` in the fn is_valid_version_info
@ntBre ntBre enabled auto-merge (squash) June 20, 2025 13:40
@IDrokin117
Copy link
Contributor Author

IDrokin117 commented Jun 23, 2025

@ntBre Seems one of the actions failed due to "curl: (22) The requested URL returned error: 403". Could you please rerun or skip it to merge?

@charliermarsh
Copy link
Member

I got it.

@ntBre
Copy link
Contributor

ntBre commented Jun 23, 2025

Oops, I guess I shouldn't have dismissed the notification until I saw it actually merge, sorry!

It looks like the workflow might still be using an old version of the ci.yaml file with an old version of install-action. This error should be resolved on main.

@ntBre ntBre disabled auto-merge June 23, 2025 19:56
@ntBre ntBre enabled auto-merge (squash) June 23, 2025 19:59
@ntBre ntBre merged commit da16e00 into astral-sh:main Jun 23, 2025
34 checks passed
dcreager added a commit that referenced this pull request Jun 24, 2025
* main:
  [ty] Fix false positives when subscripting an object inferred as having an `Intersection` type (#18920)
  [`flake8-use-pathlib`] Add autofix for `PTH202` (#18763)
  [ty] Add relative import completion tests
  [ty] Clarify what "cursor" means
  [ty] Add a cursor test builder
  [ty] Enforce sort order of completions (#18917)
  [formatter] Fix missing blank lines before decorated classes in .pyi files (#18888)
  Apply fix availability and applicability when adding to `DiagnosticGuard` and remove `NoqaCode::rule` (#18834)
  py-fuzzer: allow relative executable paths (#18915)
  [ty] Change `environment.root` to accept multiple paths (#18913)
  [ty] Rename `src.root` setting to `environment.root` (#18760)
  Use file path for detecting package root (#18914)
  Consider virtual path for various server actions (#18910)
  [ty] Introduce `UnionType::try_from_elements` and `UnionType::try_map` (#18911)
  [ty] Support narrowing on `isinstance()`/`issubclass()` if the second argument is a dynamic, intersection, union or typevar type (#18900)
  [ty] Add decorator check for implicit attribute assignments (#18587)
  [`ruff`] Trigger `RUF037` for empty string and byte strings (#18862)
  [ty] Avoid duplicate diagnostic in unpacking (#18897)
  [`pyupgrade`] Extend version detection to include `sys.version_info.major` (`UP036`) (#18633)
  [`ruff`] Frozen Dataclass default should be valid (`RUF009`) (#18735)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rule Implementing or modifying a lint rule
Projects
None yet
Development

Successfully merging this pull request may close these issues.

sys.version_info.major not flagged by UP036
3 participants