-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Fix unsupported-binary-operation
on classes that overload or
#6664
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
Conversation
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.
Thank you for opening the merge request, this look promising :)
I'm a bit confused about the functional tests. It looks like with my changes in place, we stop reporting this warning when run under Python 3.10 (because the If we're running on Python 3.10 but the Is that correct? |
Yes. I almost commented on this but did not because I thought the |
It feels like the right way to solve this is for Astroid not to report the existence of an Does this mean we need to have logic to deal with this in the Pylint checker? If so, I think it means that we can't benefit from implementing a |
I think adding a |
I have what I think is a fix for this. It's not elegant, but I can see that making Astroid infer all the cases correctly based on the configured version is not going to be easy. |
This comment has been minimized.
This comment has been minimized.
Pull Request Test Coverage Report for Build 2545186714
π - Coveralls |
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.
There's a small changelog issue (sorry about that, we're trying to get rid of the duplication in the next versions), but other than that LGTM. I'll wait for a review from someone else.
doc/whatsnew/2/2.14/summary.rst
Outdated
* Don't report ``unsupported-binary-operation`` on Python <= 3.9 when using the ``|`` operator | ||
with types, if one has a metaclass that overloads ``__or__`` or ``__ror__`` as appropriate. | ||
|
||
Closes #4951 | ||
|
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.
Unfortunately we need to still add the changelog in full.rst too until we release 2.14.0.
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 I've missed the 2.14 cut-off I guess I have to move this. I've put the note in index.rst
in the 2.15 section because that's where all the section headings are, but I don't know if this is going to get moved into separate files later?
Moving to 2.15 as we try to release asap :) |
Co-authored-by: Jacob Walls <[email protected]>
for more information, see https://pre-commit.ci
This comment has been minimized.
This comment has been minimized.
I don't fully understand, but on Python 3.10 Astroid will infer two values for the attribute built-in on |
This comment has been minimized.
This comment has been minimized.
I'm not very fluent in metaclasses. Should this inheritance pattern lead to different results? Currently I get a test failure: diff --git a/tests/functional/a/alternative/alternative_union_syntax_error.py b/tests/functional/a/alternative/alternative_union_syntax_error.py
index 3922e3c0d..4cb293d5c 100644
--- a/tests/functional/a/alternative/alternative_union_syntax_error.py
+++ b/tests/functional/a/alternative/alternative_union_syntax_error.py
@@ -98,10 +98,13 @@ class ReverseMetaclass(type):
def __ror__(cls, other):
return True
+class SecondLevelParent(ReverseMetaclass):
+ pass
+
class WithForward(metaclass=ForwardMetaclass):
pass
-class WithReverse(metaclass=ReverseMetaclass):
+class WithReverse(metaclass=SecondLevelParent):
pass
class DefaultMetaclass: |
I think you're right in your expectation that it should not report a warning with the second-level metaclass. I was assuming Astroid |
I think it might just be the assumption of direct parentage. Any time I see |
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 we solve this at the Astroid level, Pylint doesn't need any special rules and Astroid will be reporting slightly more correct data. But based on a quick search of the repo, it looks like Astroid doesn't support anything like a py-version setting.
I think adding a
py-version
in astroid is very high effort because we'd have to know every specificity of each interpreter instead of just relying on the ast module for the interpreter (basically emulate a 3.8 parsing on a 3.10 interpreter). By contrast in pylint for a specific case we have to know what is the specificity of versions older than 3.x for this specific use case. What do you think @cdce8p ?
It would be quite difficult to implement py-version
in astroid unfortunately. True, we could do the AST parsing with a different version but that doesn't really change much. For instance, I believe the __or__
and __ror__
methods on the type
metaclass are read directly from the interpreter. Thus we would need to manually update each and every change from Python at which point we're basically rebuilding CPython itself.
py-version
was more designed for things which can easily be inferred by pylint, like recommendations for the use of new features (f-strings
, ...).
The way you solved the issue here is quite clever! I left a few notes but after that I think it's ready.
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
This comment has been minimized.
This comment has been minimized.
class SecondLevelMetaclass(ForwardMetaclass): | ||
pass | ||
|
||
class WithSecondLevel(metaclass=SecondLevelMetaclass): | ||
pass | ||
|
||
class_list_with_second_level = [WithSecondLevel | DefaultMetaclass] |
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 doesn't seem to work at the moment. I only spend a few minutes investigating it, but couldn't a quick fix. Maybe it's better to remove that test case here and open a followup issue for it to be addressed later. At least that way this PR could be merged.
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 was hoping to get to the bottom of it, because I didn't want to commit a half-working fix. But thinking about it, this failure case isn't a new false positive so I guess this fix will be an improvement overall. I'll pull this out and open another PR for it.
This will be dealt with as a separate merge
Throughout this module we're using ``astroid.NotFoundError`` as an alias for ``astroid.exceptions.NotFoundError``, it seems best to be consistent.
π€ According to the primer, this change has no effect on the checked open source code. π€π This comment was generated for commit 8ec0215 |
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.
Looks good! Thanks @timmartin π¬
@jacobtylerwalls Small ping. Saw you left a review a while ago. Has it been resolved?
Yep, thanks for checking! I was the one that asked for that test case we haven't solved, but I agree we can postpone. I think it's just a matter of doing a recursive search on ancestors instead of relying on direct |
Type of Changes
Description
We have a specific checker looking for people using
|
with two types, apparently on the assumption that anyone doing that is mistakenly trying to use union syntax where it's not supported. This seems to overlook the fact that it is possible for class definitions to use a metaclass that implements__or__
or__ror__
as appropriate, which is the case in the permission classes for Django REST Framework, for example.Closes #4951