-
-
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
Fix invalid type false positive #8206
Fix invalid type false positive #8206
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #8206 +/- ##
=======================================
Coverage 95.46% 95.46%
=======================================
Files 177 177
Lines 18698 18704 +6
=======================================
+ Hits 17850 17856 +6
Misses 848 848
|
This comment has been minimized.
This comment has been minimized.
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.
This will need a changelog entry
pylint/checkers/typecheck.py
Outdated
@@ -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 == "|": |
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.
Can't we use the new UnionType
here?
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.
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?
pylint/checkers/typecheck.py
Outdated
@@ -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 == "|": |
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 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
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
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.
Agreed, I'll add that once the rest is figured out. And maybe a shorter name would be nice π
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.
maybe _alt_union_syntax_enabled
?
You can also rename it in pylint/extensions/typing.py
[testoptions] | ||
min_pyver=3.10 |
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.
maybe you could allow the test to run also for earlier versions like was done in redundant-typehint-argument
:
[testoptions] | |
min_pyver=3.10 | |
[testoptions] | |
min_pyver=3.7 | |
[TYPING] | |
runtime-typing=no |
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.
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?
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.
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.
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.
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+.
I included test cases for false negatives from #8213. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
[testoptions] | ||
min_pyver=3.10 |
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.
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): |
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.
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.
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.
No, Union[int, str]
is an instance of ClassDef
and not UnionType
. I'm not sure what exactly UnionType
corresponds to.
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.
π
This comment has been minimized.
This comment has been minimized.
@DanielNoord Anything else for this one? |
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 you add INFERENCE
as confidence to the message?>
π€ According to the primer, this change has no effect on the checked open source code. π€π This comment was generated for commit 66d21ac |
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.
Thanks for this! π
The backport to
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 |
(cherry picked from commit e64f043)
Type of Changes
Description
Fixes false positive for
isinstance-second-argument-not-valid-type
with union types.Closes #8205