% cat example.py
if type(obj) == int:
pass
% pycodestyle example.py
example.py:1:4: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()`
Great!
Strange behavior
Change type(obj) == int to int == type(obj) (swap the left and right sides).
Expected
Raise E721.
This code is still comparing the return value of type.
Actual
Do NOT raise E721.
% cat example.py
if int == type(obj):
pass
% pycodestyle example.py
% echo $?
0
Investigation
>>> from pycodestyle import comparison_type
>>> list(comparison_type("if type(obj) == int:", noqa=False))
[(3, 'E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()`')]
>>> list(comparison_type("if int == type(obj):", noqa=False))
[]
>>> from pycodestyle import COMPARE_TYPE_REGEX
>>> from pycodestyle import SINGLETONS
>>> match = COMPARE_TYPE_REGEX.search("if type(obj) == int:")
>>> match
<re.Match object; span=(3, 15), match='type(obj) =='>
>>> match.group(1) # None; Go yield (L1466)
>>> match.group(2)
'obj'
>>> match = COMPARE_TYPE_REGEX.search("if int == type(obj):")
>>> match
<re.Match object; span=(7, 19), match='== type(obj)'>
>>> match.group(1)
'obj'
>>> match.group(2)
>>> inst = match.group(1)
>>> inst and inst.isidentifier() and inst not in SINGLETONS # Go return (L1465) not yield
True
If you need to use captured substrings, you might need to do something like inst = match.group(1) or match.group(2).
However, in that case, inst and inst.isidentifier() and inst not in SINGLETONS would return True, and E721 would no longer be raised.
Therefore, I believe that removing the return statement here would resolve the reported issue.
One concern I have is that it seems inst = match.group(1) has not been changed along with the last pull request.
https://github.com/PyCQA/pycodestyle/pull/1086/files
Depending on the reason for not changing this, we might need to consider a different solution.
Environment
Normal behavior
Great!
Strange behavior
Change
type(obj) == int
toint == type(obj)
(swap the left and right sides).Expected
Raise E721. This code is still comparing the return value of type.
Actual
Do NOT raise E721.
Investigation
In v2.11.0 (21abd9b6dcbfa38635bc85a2c2327ec11ad91ffc),
COMPARE_TYPE_REGEX
has 2 captures. https://github.com/PyCQA/pycodestyle/blob/21abd9b6dcbfa38635bc85a2c2327ec11ad91ffc/pycodestyle.py#L128-L131In
comparison_type
, the first captured substring is only referred (inst = match.group(1)
). https://github.com/PyCQA/pycodestyle/blob/21abd9b6dcbfa38635bc85a2c2327ec11ad91ffc/pycodestyle.py#L1451-L1452 https://github.com/PyCQA/pycodestyle/blob/21abd9b6dcbfa38635bc85a2c2327ec11ad91ffc/pycodestyle.py#L1461-L1470If you need to use captured substrings, you might need to do something like
inst = match.group(1) or match.group(2)
. However, in that case,inst and inst.isidentifier() and inst not in SINGLETONS
would return True, and E721 would no longer be raised. Therefore, I believe that removing the return statement here would resolve the reported issue.One concern I have is that it seems
inst = match.group(1)
has not been changed along with the last pull request. https://github.com/PyCQA/pycodestyle/pull/1086/files Depending on the reason for not changing this, we might need to consider a different solution.