Skip to content
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

Negation and None #5085

Open
socketpair opened this issue Sep 28, 2021 · 6 comments
Open

Negation and None #5085

socketpair opened this issue Sep 28, 2021 · 6 comments
Labels
Control flow Requires control flow understanding False Positive 🦟 A message is emitted but nothing is wrong with the code Needs PR This issue is accepted, sufficiently specified and now needs an implementation

Comments

@socketpair
Copy link

socketpair commented Sep 28, 2021

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 socketpair added Bug 🪲 Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling labels Sep 28, 2021
@Pierre-Sassoulas Pierre-Sassoulas added Control flow Requires control flow understanding and removed Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling labels Oct 17, 2021
@saroad2
Copy link

saroad2 commented Apr 19, 2022

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)

@Pierre-Sassoulas Pierre-Sassoulas added False Positive 🦟 A message is emitted but nothing is wrong with the code Needs PR This issue is accepted, sufficiently specified and now needs an implementation and removed Bug 🪲 labels Jul 14, 2022
@sam-s
Copy link

sam-s commented Sep 7, 2023

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

@socketpair
Copy link
Author

socketpair commented Mar 21, 2024

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
Copy link
Author

@Pierre-Sassoulas @sam-s @saroad2

Do you have any ideas ?

@Pierre-Sassoulas
Copy link
Member

The is None case was introduced in astroid 2.13 pylint-dev/astroid#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 .

@socketpair
Copy link
Author

socketpair commented May 6, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Control flow Requires control flow understanding False Positive 🦟 A message is emitted but nothing is wrong with the code Needs PR This issue is accepted, sufficiently specified and now needs an implementation
Projects
None yet
Development

No branches or pull requests

4 participants