pylint
pylint copied to clipboard
Negation and None
Bug description
Pylint incorrectly tracks types:
class Xxx:
def __init__(self):
self.__val = None
@property
def get_value(self) -> int:
if self.__val is None:
self.__val = 42
return self.__val
def method(self):
return 'qwe'[:-self.get_value]
Configuration
No response
Command used
pylint a.py
Pylint output
a.py:12:22: E1130: bad operand type for unary -: NoneType (invalid-unary-operand-type)
Expected behavior
no errors
Pylint version
pylint 2.9.6
astroid 2.6.6
Python 3.9.7 (default, Aug 30 2021, 00:00:00)
[GCC 11.2.1 20210728 (Red Hat 11.2.1-1)]
OS / Environment
Fedora 34
Additional dependencies
No response
I also encountered this bug with the following example:
from pathlib import Path
from typing import Optional, List
def clear(paths_list: List[Path], limit: Optional[int] = None):
if limit is not None and limit < len(paths_list):
paths_list = paths_list[-limit:]
for path in paths_list:
path.unlink()
When running Pylint over the code above it raises:
my\path.py:7:32: E1130: bad operand type for unary -: NoneType (invalid-unary-operand-type)
Here is an even smaller test case:
l = [1,2,3]
x = None
if isinstance(x, int):
l = l[-x:]
that gives
bad operand type for unary -: NoneType (invalid-unary-operand-type)
on
pylint 2.17.5
astroid 2.15.6
Python 3.11.5 (tags/v3.11.5:cce6ba9, Aug 24 2023, 14:38:34) [MSC v.1936 64 bit (AMD64)]
val: int | None = None
def get_value() -> int:
if val is None:
return 42
return val
print(get_value() + 1) # no errors here (as expected)
print(-get_value()) # BUMM! error! WHY ?
print(None + 1) # NO ERROR HERE ?! WUT ?
pylint 3.0.4
astroid 3.0.3
Python 3.12.2 (main, Feb 21 2024, 00:00:00) [GCC 13.2.1 20231205 (Red Hat 13.2.1-6)]
@Pierre-Sassoulas @sam-s @saroad2
Do you have any ideas ?
The is None case was introduced in astroid 2.13 https://github.com/pylint-dev/astroid/pull/1189, isinstance still needs works in astroid. I won't have enough time to dig into the specifics about how the inference works in your specific case @socketpair .
@Pierre-Sassoulas I have minified:
val = None
if val is None:
val = 42
print(-val)
E1130: bad operand type for unary -: NoneType (invalid-unary-operand-type)
Still requires digging ?
For original post, seems, whole system ignores typing for functions and re-calculates possibly types on its own way. Because the function is said to return int. But int the sensitive place, Pylint thinks it may return None (agree that's another bug)