Skip to content

Consistency between is/is not and ==/!= when comparing types for unidiomatic-typecheck #10170

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

Merged
merged 11 commits into from
May 4, 2025

Conversation

nedelcu-ioan
Copy link
Contributor

Type of Changes

Type
🐛 Bug fix

Description

Closes #10161

Copy link

codecov bot commented Jan 7, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 95.83%. Comparing base (6456374) to head (226c110).
Report is 10 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #10170      +/-   ##
==========================================
- Coverage   95.83%   95.83%   -0.01%     
==========================================
  Files         174      174              
  Lines       18995    18993       -2     
==========================================
- Hits        18204    18202       -2     
  Misses        791      791              
Files with missing lines Coverage Δ
pylint/checkers/base/comparison_checker.py 100.00% <100.00%> (ø)

This comment has been minimized.

@Pierre-Sassoulas Pierre-Sassoulas added False Positive 🦟 A message is emitted but nothing is wrong with the code backport maintenance/3.3.x labels Jan 25, 2025
@Pierre-Sassoulas Pierre-Sassoulas modified the milestones: 3.3.4, 3.3.5 Jan 25, 2025
Comment on lines 349 to 353
right_arg = utils.safe_infer(right.args[0])
if not isinstance(right_arg, LITERAL_NODE_TYPES):
# not e.g. type(x) == type([])
return
return
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure I would change this.

Copy link
Contributor

@zenlyj zenlyj Feb 5, 2025

Choose a reason for hiding this comment

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

agree with jacob, shall we keep this guard block that checks for literal node types?

Copy link
Member

Choose a reason for hiding this comment

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

At this point we already know that the left arg is type(something), once we know the right argument is starting by type() we don't have to check what's inside anymore ? Or we want to remove the whole "type_of_literals_negatives" test block ?

Copy link
Contributor

Choose a reason for hiding this comment

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

i think it depends on whether we want to retain current behavior of raising a message for type(a) is type(LITERAL), where LITERAL: [] | {} | "" | .... These cases are covered by the type_of_literals_positives test block, introduced from #299.

Couldn't dig into the related PR as it was merged >10 years ago in a different repository, but the separation of deliberate_subclass_check_negatives and type_of_literals_positives test blocks seems to indicate that the author wanted to raise a message because type(a) is type([]) is equivalent to type(a) is list, which should be refactored to isinstance(a, list)?

Copy link
Member

Choose a reason for hiding this comment

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

I re-read the issue. Here's my context:

  • OP wanted no message for type(x) == type(y) on the theory that users know what they're doing (me: I'd probably wontfix that -- but I won't stand in the way right now)
  • then @zenlyj noticed we have a discrepancy between == and is we should fix. (me: I'm mostly interested in fixing that alone)
  • then in PR review we face the question of whether to remove the cases that check type(x) == type([]). This seems to pull even further in the wrong direction, linter should catch this.

Let's just fix the is/is not thing and keep these test cases and the open follow-up issues for:

  • suggesting type(x) is type(y) to be rewritten as isinstance(x, type(y)), going against OP
  • extending comparison-with-callable to cover == list

Copy link
Member

Choose a reason for hiding this comment

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

Opened #10364 and #10365

This comment has been minimized.

@Pierre-Sassoulas Pierre-Sassoulas modified the milestones: 3.3.5, 3.3.6 Mar 8, 2025
@Pierre-Sassoulas Pierre-Sassoulas modified the milestones: 3.3.6, 3.3.7 Mar 20, 2025
@DanielNoord DanielNoord added the Needs take over 🛎️ Orignal implementer went away but the code could be salvaged. label Mar 30, 2025
@Pierre-Sassoulas Pierre-Sassoulas removed the Needs take over 🛎️ Orignal implementer went away but the code could be salvaged. label May 2, 2025
@Pierre-Sassoulas Pierre-Sassoulas self-assigned this May 2, 2025

This comment has been minimized.

@Pierre-Sassoulas Pierre-Sassoulas changed the title Incorrect scenario of unidiomatic-typecheck #10161 Consistency between is/is not and ==/!= when comparing types for unidiomatic-typecheck May 2, 2025

This comment has been minimized.

This comment has been minimized.

Comment on lines 349 to 353
right_arg = utils.safe_infer(right.args[0])
if not isinstance(right_arg, LITERAL_NODE_TYPES):
# not e.g. type(x) == type([])
return
return
Copy link
Member

Choose a reason for hiding this comment

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

I re-read the issue. Here's my context:

  • OP wanted no message for type(x) == type(y) on the theory that users know what they're doing (me: I'd probably wontfix that -- but I won't stand in the way right now)
  • then @zenlyj noticed we have a discrepancy between == and is we should fix. (me: I'm mostly interested in fixing that alone)
  • then in PR review we face the question of whether to remove the cases that check type(x) == type([]). This seems to pull even further in the wrong direction, linter should catch this.

Let's just fix the is/is not thing and keep these test cases and the open follow-up issues for:

  • suggesting type(x) is type(y) to be rewritten as isinstance(x, type(y)), going against OP
  • extending comparison-with-callable to cover == list

This comment has been minimized.

DanielNoord
DanielNoord previously approved these changes May 4, 2025
Copy link
Collaborator

@DanielNoord DanielNoord left a comment

Choose a reason for hiding this comment

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

LGTM!

jacobtylerwalls
jacobtylerwalls previously approved these changes May 4, 2025
Copy link
Member

@jacobtylerwalls jacobtylerwalls left a comment

Choose a reason for hiding this comment

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

Thanks, all!

Copy link
Contributor

github-actions bot commented May 4, 2025

🤖 Effect of this PR on checked open source code: 🤖

Effect on pandas:
The following messages are no longer emitted:

  1. unidiomatic-typecheck:
    Use isinstance() rather than type() for a typecheck.
    https://github.com/pandas-dev/pandas/blob/e55d90783bac30b75e7288380b15a62ab6e43f78/pandas/core/arrays/masked.py#L1108
  2. unidiomatic-typecheck:
    Use isinstance() rather than type() for a typecheck.
    https://github.com/pandas-dev/pandas/blob/e55d90783bac30b75e7288380b15a62ab6e43f78/pandas/core/arrays/interval.py#L337
  3. unidiomatic-typecheck:
    Use isinstance() rather than type() for a typecheck.
    https://github.com/pandas-dev/pandas/blob/e55d90783bac30b75e7288380b15a62ab6e43f78/pandas/core/arrays/interval.py#L992
  4. unidiomatic-typecheck:
    Use isinstance() rather than type() for a typecheck.
    https://github.com/pandas-dev/pandas/blob/e55d90783bac30b75e7288380b15a62ab6e43f78/pandas/core/arrays/base.py#L1510
  5. unidiomatic-typecheck:
    Use isinstance() rather than type() for a typecheck.
    https://github.com/pandas-dev/pandas/blob/e55d90783bac30b75e7288380b15a62ab6e43f78/pandas/core/arrays/arrow/extension_types.py#L43
  6. unidiomatic-typecheck:
    Use isinstance() rather than type() for a typecheck.
    https://github.com/pandas-dev/pandas/blob/e55d90783bac30b75e7288380b15a62ab6e43f78/pandas/core/arrays/arrow/extension_types.py#L97
  7. unidiomatic-typecheck:
    Use isinstance() rather than type() for a typecheck.
    https://github.com/pandas-dev/pandas/blob/e55d90783bac30b75e7288380b15a62ab6e43f78/pandas/core/indexes/base.py#L5545

This comment was generated for commit 74c2fa7

@Pierre-Sassoulas Pierre-Sassoulas requested a review from zenlyj May 4, 2025 13:13
@zenlyj
Copy link
Contributor

zenlyj commented May 4, 2025

LGTM 👌, thanks!

@jacobtylerwalls jacobtylerwalls merged commit d396616 into pylint-dev:main May 4, 2025
38 of 39 checks passed
Copy link
Contributor

github-actions bot commented May 4, 2025

The backport to maintenance/3.3.x failed:

The process '/usr/bin/git' failed with exit code 1

To backport manually, run these commands in your terminal:

# Fetch latest updates from GitHub
git fetch
# Create a new working tree
git worktree add .worktrees/backport-maintenance/3.3.x maintenance/3.3.x
# Navigate to the new working tree
cd .worktrees/backport-maintenance/3.3.x
# Create a new branch
git switch --create backport-10170-to-maintenance/3.3.x
# Cherry-pick the merged commit of this pull request and resolve the conflicts
git cherry-pick -x --mainline 1 d396616db59977540ab32496e324c7aaca352ab2
# Push it to GitHub
git push --set-upstream origin backport-10170-to-maintenance/3.3.x
# Go back to the original working tree
cd ../..
# Delete the working tree
git worktree remove .worktrees/backport-maintenance/3.3.x

Then, create a pull request where the base branch is maintenance/3.3.x and the compare/head branch is backport-10170-to-maintenance/3.3.x.

jacobtylerwalls pushed a commit to jacobtylerwalls/pylint that referenced this pull request May 4, 2025
…g types for ``unidiomatic-typecheck`` (pylint-dev#10170)

(cherry picked from commit d396616)
Pierre-Sassoulas added a commit to Pierre-Sassoulas/pylint that referenced this pull request May 4, 2025
…g types for ``unidiomatic-typecheck`` (pylint-dev#10170)

Co-authored-by: Pierre Sassoulas <[email protected]>
Pierre-Sassoulas added a commit that referenced this pull request May 4, 2025
…g types for ``unidiomatic-typecheck`` (#10170) (#10366)

(cherry picked from commit d396616)

Co-authored-by: Nedelcu Ioan-Andrei <[email protected]>
Co-authored-by: Pierre Sassoulas <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport maintenance/3.3.x False Positive 🦟 A message is emitted but nothing is wrong with the code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Inconsistency between is/is not and ==/!= when comparing types for unidiomatic-typecheck
6 participants