-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Multiple binary | operation in a single statement failed with "E1131: unsupported operand type(s) for | (unsupported-binary-operation)" #7381
Comments
Same issue when using Django's "Q objects" https://docs.djangoproject.com/en/3.1/topics/db/queries/#complex-lookups-with-q 2 Q objects |
Thanks for the report. I can't reproduce this one myself: (venv310) Marks-MacBook-Air-2:programming markbyrne$ pip freeze |grep pylint
pylint==2.15.0
pylint-quotes==0.2.3 (venv310) Marks-MacBook-Air-2:programming markbyrne$ pylint --version
pylint 2.15.0
astroid 2.12.5
Python 3.10.4 (v3.10.4:9d38120e33, Mar 23 2022, 17:29:05) [Clang 13.0.0 (clang-1300.0.29.30)] (venv310) Marks-MacBook-Air-2:programming markbyrne$ cat example.py
'''test'''
from enum import Flag
class MosaicFlags(Flag):
"""test"""
NONE = 0
SUPPLY_MUTABLE = 1
TRANSFERABLE = 2
RESTRICTABLE = 4
REVOKABLE = 8
value = MosaicFlags.SUPPLY_MUTABLE | MosaicFlags.RESTRICTABLE | MosaicFlags.REVOKABLE
print(value)
(venv310) Marks-MacBook-Air-2:programming markbyrne$ pylint example.py --load-plugins pylint_quotes
************* Module programming.p
p.py:1:0: C4003: Invalid docstring quote ''', should be """ (invalid-docstring-quote)
------------------------------------------------------------------
Your code has been rated at 8.89/10 (previous run: 8.89/10, +0.00) |
…h bitwise operators. Refs pylint-dev#7381
Hi @mbyrnepr2, Thanks for taking a look. Sorry, I didnt actually try the sample code. pylint example.py --load-plugins pylint_quotes from enum import Flag
class Module:
"""module"""
class TestFlags(Flag):
"""test flags"""
TEST_NONE = 0
TEST_SUPPLY_MUTABLE = 1
TEST_TRANSFERABLE = 2
TEST_RESTRICTABLE = 4
TEST_REVOKABLE = 8
class TestClass():
"""test class"""
@staticmethod
def _assert_flags_parser(value, expected):
"""assert"""
pass
def test_flags_parser_can_handle_multiple_string_flags(self):
"""test flags"""
self._assert_flags_parser(
'supply_mutable restrictable revokable',
Module.TestFlags.TEST_SUPPLY_MUTABLE | Module.TestFlags.TEST_RESTRICTABLE | Module.TestFlags.TEST_REVOKABLE)
@staticmethod
def test_flags_parser_passes_non_parsed_values_as_is():
"""test parser"""
value = Module.TestFlags.TEST_SUPPLY_MUTABLE | Module.TestFlags.TEST_RESTRICTABLE | Module.TestFlags.TEST_REVOKABLE
print(value) |
if you want a shorter example without enum dependency you can reproduce this false positive bug with this: class BinaryOperator:
""" only make useless binary operations
"""
def __or__(self, whatever):
return 42
operators = [ BinaryOperator(), BinaryOperator() ]
def _fn(idx: int=0):
print(operators[0] | operators[1]) # NO unsupported-binary-operation issue
print(operators[idx] | operators[1]) # OUPS unsupported-binary-operation issue
_fn(0) |
Thanks for the examples. @Wayonb you're right - something between 2.14.1 & 2.15.0 has led to this false positive. Note it happens only for Python versions below 3.10 because of this logic: https://github.com/PyCQA/pylint/blob/main/pylint/checkers/typecheck.py#L1879-L1880 |
Is there any chance for part or all of the new type checker code to be reverted until the issue is fixed? Thanks |
@RemiCardona Without looking too much into it, the cost of fixing the issue is probably going to be smaller than the cost to partially revert (but the main problem is that we don't have contributions for either right now). |
@Pierre-Sassoulas I have been waiting on working on |
It could be worth taking a look at this change. If I revert that one locally, I can't reproduce using the following example, provided in the comment above example from the commentfrom enum import Flag
class Module:
"""module"""
class TestFlags(Flag):
"""test flags"""
TEST_NONE = 0
TEST_SUPPLY_MUTABLE = 1
TEST_TRANSFERABLE = 2
TEST_RESTRICTABLE = 4
TEST_REVOKABLE = 8
class TestClass():
"""test class"""
@staticmethod
def _assert_flags_parser(value, expected):
"""assert"""
pass
def test_flags_parser_can_handle_multiple_string_flags(self):
"""test flags"""
self._assert_flags_parser(
'supply_mutable restrictable revokable',
Module.TestFlags.TEST_SUPPLY_MUTABLE | Module.TestFlags.TEST_RESTRICTABLE | Module.TestFlags.TEST_REVOKABLE)
@staticmethod
def test_flags_parser_passes_non_parsed_values_as_is():
"""test parser"""
value = Module.TestFlags.TEST_SUPPLY_MUTABLE | Module.TestFlags.TEST_RESTRICTABLE | Module.TestFlags.TEST_REVOKABLE
print(value) |
Here is my repro. Having the expression in the tuple seems to be necessary. class MyFlag(enum.Flag):
FOO = 1
BAR = 2
BAZ = 4
XX = (MyFlag.FOO | MyFlag.BAR | MyFlag.BAZ, 'hello') |
Here's another repro. Completing @belm0's one. It seems placing the expression in a tuple, a list or passing it as a parameter of a function raises checker E1131. This was tested on the latest version released this morning (pylint 2.15.8/Python 3.9.10) Reprofrom enum import Flag
class MyFlag(Flag):
FOO = 1
BAR = 2
BAZ = 3
def spam(eggs):
...
# No errors
spam(MyFlag.FOO | MyFlag.BAR) # two operands
eggs = (MyFlag.FOO | MyFlag.BAR, "hello") # two operands
eggs = MyFlag.FOO | MyFlag.BAR | MyFlag.BAZ # expression *not* in a tuple, list nor function
# E1131: unsupported operand type(s) for | (unsupported-binary-operation)
spam(MyFlag.FOO | MyFlag.BAR | MyFlag.BAZ) # 3 operands as a parameter of a function
eggs = (MyFlag.FOO | MyFlag.BAR | MyFlag.BAZ, "hello") # 3 operands in a tuple
eggs = [MyFlag.FOO | MyFlag.BAR | MyFlag.BAZ, "hello"] # 3 operands in a list Env> pylint --version
pylint 2.15.8
astroid 2.12.13
Python 3.9.10 (main, Jun 9 2022, 15:45:30)
[GCC 9.3.1 20200408 (Red Hat 9.3.1-2)] Expected results
|
Here's a django example from #7953 thanks to @masiak2: from django.db import models
from django.db.models import Q
class Author(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField()
# this is fine
qs = Author.objects.filter(Q(name="x") | Q(name="y"))
# this throws an unsupported-binary-operation error
qs2 = Author.objects.filter(Q(name="x") | Q(name="y") | Q(name="z")) |
Another short example with Enum's Flag:
|
Another example: "https://github.com/PyCQA/pylint/issues/8297"
from dataclasses import dataclass
@dataclass
class C:
"class doc"
a: str
b: int = 10
c: float | int | None = None |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Another example:
under py3.8 & 3.9. However it's not showing issue with py3.11 |
This is needed to make pylint pass: ``` ************* Module band.models band/models.py:162:16: E1131: unsupported operand type(s) for | (unsupported-binary-operation) ************* Module gig.models gig/models.py:47:45: E1131: unsupported operand type(s) for | (unsupported-binary-operation) ``` Reference: pylint-dev/pylint#7381 (comment)
Bug description
If I am trying to OR more than two flags, pylint 2.15.0 fails with "E1131: unsupported operand type(s) for | (unsupported-binary-operation)". This worked with pylint 2.14.1
Configuration
No response
Command used
Pylint output
Expected behavior
Expected no errors
Pylint version
OS / Environment
Ubuntu 20.04
Additional dependencies
isort==5.10.1
pycodestyle==2.9.1
pylint==2.15.0
pylint-quotes==0.2.3
The text was updated successfully, but these errors were encountered: