pylint icon indicating copy to clipboard operation
pylint copied to clipboard

Negation and None

Open socketpair opened this issue 4 years ago • 6 comments

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

socketpair avatar Sep 28 '21 08:09 socketpair

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)

saroad2 avatar Apr 19 '22 20:04 saroad2

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)]

sam-s avatar Sep 07 '23 21:09 sam-s

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)]

socketpair avatar Mar 21 '24 16:03 socketpair

@Pierre-Sassoulas @sam-s @saroad2

Do you have any ideas ?

socketpair avatar Mar 21 '24 16:03 socketpair

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 avatar May 06 '24 08:05 Pierre-Sassoulas

@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)

socketpair avatar May 06 '24 09:05 socketpair