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

Fix invalid type false positive #8206

Conversation

nickdrozd
Copy link
Collaborator

Type of Changes

Type
βœ“ πŸ› Bug fix

Description

Fixes false positive for isinstance-second-argument-not-valid-type with union types.

Closes #8205

@codecov
Copy link

codecov bot commented Feb 7, 2023

Codecov Report

Merging #8206 (66d21ac) into main (81ed650) will increase coverage by 0.00%.
The diff coverage is 100.00%.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #8206   +/-   ##
=======================================
  Coverage   95.46%   95.46%           
=======================================
  Files         177      177           
  Lines       18698    18704    +6     
=======================================
+ Hits        17850    17856    +6     
  Misses        848      848           
Impacted Files Coverage Ξ”
pylint/checkers/typecheck.py 96.35% <100.00%> (+0.01%) ⬆️
pylint/constants.py 100.00% <100.00%> (ΓΈ)

@github-actions

This comment has been minimized.

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.

This will need a changelog entry

tests/functional/i/isinstance_second_argument_py310.py Outdated Show resolved Hide resolved
@@ -806,6 +806,10 @@ def _is_invalid_isinstance_type(arg: nodes.NodeNG) -> bool:
return False
if isinstance(inferred, astroid.Instance) and inferred.qname() == BUILTIN_TUPLE:
return False
if isinstance(arg, nodes.BinOp) and arg.op == "|":
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can't we use the new UnionType here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Because of what I assume are inference failures, I couldn't cover all the test cases without checking both the inferred value and the superficial value. Is there a better way to do this?

@DanielNoord DanielNoord added typing False Positive 🦟 A message is emitted but nothing is wrong with the code labels Feb 7, 2023
@DanielNoord DanielNoord added this to the 2.16.2 milestone Feb 7, 2023
@@ -806,6 +806,10 @@ def _is_invalid_isinstance_type(arg: nodes.NodeNG) -> bool:
return False
if isinstance(inferred, astroid.Instance) and inferred.qname() == BUILTIN_TUPLE:
return False
if isinstance(arg, nodes.BinOp) and arg.op == "|":
Copy link
Contributor

Choose a reason for hiding this comment

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

I reckon this check should only be done for python version that support PEP604 and the | operand for type annotations. I think this condition should only be checked when supported, similar code in pylint/extensions/typing.py

Suggested change
if isinstance(arg, nodes.BinOp) and arg.op == "|":
if _should_check_alternative_union_syntax and isinstance(arg, nodes.BinOp) and arg.op == "|":

where:

        py_version = self.linter.config.py_version
        self._py37_plus = py_version >= (3, 7)
        self._py310_plus = py_version >= (3, 10)
        self._should_check_alternative_union_syntax = self._py310_plus or (
            self._py37_plus and self.linter.config.runtime_typing is False

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Agreed, I'll add that once the rest is figured out. And maybe a shorter name would be nice πŸ˜†

Copy link
Contributor

Choose a reason for hiding this comment

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

maybe _alt_union_syntax_enabled ?

You can also rename it in pylint/extensions/typing.py

Comment on lines +1 to +2
[testoptions]
min_pyver=3.10
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe you could allow the test to run also for earlier versions like was done in redundant-typehint-argument:

Suggested change
[testoptions]
min_pyver=3.10
[testoptions]
min_pyver=3.7
[TYPING]
runtime-typing=no

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

What does the runtime-typing option do? Also, is there a need to specify 3.7 as the min version, since that's already the min version being used?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Now that I think about it, this check is different because it doesn't deal with type annotations. In this case the types involved will actually be called, so I think this option won't apply.

Copy link
Contributor

Choose a reason for hiding this comment

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

you don't have to explicitly write min_pyver=3.7 but it would be just clearer for the test reader to understand why runtime-typing was used. There is some documentation runtime-typing at pylint/extensions/typing.py. It will identify type annotations if it can for python versions 3.7-3.9 with the | operation.

Now that I think about it, this check is different because it doesn't deal with type annotations. In this case the types involved will actually be called, so I think this option won't apply.

I think you are right. These are not annotations it the actual code. so if someone uses the | operation they can only do that in py3.10+.

@nickdrozd
Copy link
Collaborator Author

I included test cases for false negatives from #8213.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

pylint/checkers/typecheck.py Outdated Show resolved Hide resolved
Comment on lines +1 to +2
[testoptions]
min_pyver=3.10
Copy link
Contributor

Choose a reason for hiding this comment

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

you don't have to explicitly write min_pyver=3.7 but it would be just clearer for the test reader to understand why runtime-typing was used. There is some documentation runtime-typing at pylint/extensions/typing.py. It will identify type annotations if it can for python versions 3.7-3.9 with the | operation.

Now that I think about it, this check is different because it doesn't deal with type annotations. In this case the types involved will actually be called, so I think this option won't apply.

I think you are right. These are not annotations it the actual code. so if someone uses the | operation they can only do that in py3.10+.

@@ -806,6 +813,10 @@ def _is_invalid_isinstance_type(arg: nodes.NodeNG) -> bool:
return False
if isinstance(inferred, astroid.Instance) and inferred.qname() == BUILTIN_TUPLE:
return False
if PY310_PLUS and isinstance(inferred, bases.UnionType):
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if PY310_PLUS and isinstance(inferred, bases.UnionType):
if isinstance(inferred, bases.UnionType):

Is the bases.UnionType the legacy Union/Optional type? if so it is supported from 3.7+ I think.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, Union[int, str] is an instance of ClassDef and not UnionType. I'm not sure what exactly UnionType corresponds to.

Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

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

πŸ‘

@github-actions

This comment has been minimized.

@Pierre-Sassoulas Pierre-Sassoulas modified the milestones: 2.16.2, 2.16.3 Feb 13, 2023
@nickdrozd
Copy link
Collaborator Author

@DanielNoord Anything else for this one?

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.

Could you add INFERENCE as confidence to the message?>

@github-actions
Copy link
Contributor

πŸ€– According to the primer, this change has no effect on the checked open source code. πŸ€–πŸŽ‰

This comment was generated for commit 66d21ac

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.

Thanks for this! πŸ˜„

@Pierre-Sassoulas Pierre-Sassoulas merged commit e64f043 into pylint-dev:main Feb 14, 2023
@github-actions
Copy link
Contributor

The backport to maintenance/2.16.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/2.16.x maintenance/2.16.x
# Navigate to the new working tree
cd .worktrees/backport-maintenance/2.16.x
# Create a new branch
git switch --create backport-8206-to-maintenance/2.16.x
# Cherry-pick the merged commit of this pull request and resolve the conflicts
git cherry-pick -x --mainline 1 e64f0437388298c7f8514a6755c3c27a0d9a35f2
# Push it to GitHub
git push --set-upstream origin backport-8206-to-maintenance/2.16.x
# Go back to the original working tree
cd ../..
# Delete the working tree
git worktree remove .worktrees/backport-maintenance/2.16.x

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

cdce8p pushed a commit to cdce8p/pylint that referenced this pull request Mar 6, 2023
@cdce8p cdce8p modified the milestones: 2.16.3, 2.16.4 Mar 6, 2023
cdce8p added a commit that referenced this pull request Mar 6, 2023
(cherry picked from commit e64f043)

Co-authored-by: Nick Drozd <nicholasdrozd@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Backported False Positive 🦟 A message is emitted but nothing is wrong with the code typing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

W1116 (isinstance-second-argument-not-valid-type) false positive for union types
5 participants