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

Add tests #9981

Merged
merged 1 commit into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion tests/functional/u/unnecessary/unnecessary_lambda.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# pylint: disable=undefined-variable, use-list-literal, unnecessary-lambda-assignment, use-dict-literal
# pylint: disable=undefined-variable, use-list-literal, unnecessary-lambda-assignment, use-dict-literal, disallowed-name
"""test suspicious lambda expressions
"""

Expand Down Expand Up @@ -65,3 +65,23 @@ def f(d):
_ = lambda x: x(x)
_ = lambda x, y: x(x, y)
_ = lambda x: z(lambda y: x + y)(x)


# https://github.com/pylint-dev/pylint/issues/8192

# foo does not yet exist, so replacing lambda x: foo.get(x) with
# foo.get will raise NameError
g = lambda x: foo.get(x) # [unnecessary-lambda] FALSE POSITIVE

# an object is created and given the name 'foo'
foo = {1: 2}
assert g(1) == 2

# a new object is created and given the name 'foo'; first object is lost
foo = {1: 3}
assert g(1) == 3

# the name 'foo' is deleted; second object is lost; there is no foo
del foo

assert g(1) == 3 # NameError: name 'foo' is not defined
1 change: 1 addition & 0 deletions tests/functional/u/unnecessary/unnecessary_lambda.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ unnecessary-lambda:23:4:23:53:<lambda>:Lambda may not be necessary:UNDEFINED
unnecessary-lambda:25:4:25:71:<lambda>:Lambda may not be necessary:UNDEFINED
unnecessary-lambda:29:4:29:31:<lambda>:Lambda may not be necessary:UNDEFINED
unnecessary-lambda:31:4:31:44:<lambda>:Lambda may not be necessary:UNDEFINED
unnecessary-lambda:74:4:74:24:<lambda>:Lambda may not be necessary:UNDEFINED
61 changes: 60 additions & 1 deletion tests/functional/u/used/used_before_assignment.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Miscellaneous used-before-assignment cases"""
# pylint: disable=consider-using-f-string, missing-function-docstring
# pylint: disable=consider-using-f-string, missing-function-docstring, bare-except
import datetime
import sys
from typing import NoReturn
Expand Down Expand Up @@ -222,3 +222,62 @@ def print_platform_specific_command(self):
self.skip("only runs on Linux/Windows")

print(cmd)


# https://github.com/pylint-dev/pylint/issues/9941
try:
x = 1 / 0
except ZeroDivisionError:
print(x) # [used-before-assignment]

try:
y = 1 / 0
print(y)
except ZeroDivisionError:
print(y) # FALSE NEGATIVE


# https://github.com/pylint-dev/pylint/issues/9642
def __():
for i in []:
if i:
fail1 = 42
print(fail1) # [possibly-used-before-assignment]

for i in []:
fail2 = 42
print(fail2) # FALSE NEGATIVE


# https://github.com/pylint-dev/pylint/issues/9689
def outer_():
a = 1

def inner_try():
try:
nonlocal a
print(a) # [used-before-assignment] FALSE POSITIVE
a = 2
print(a)
except:
pass

def inner_while():
i = 0
while i < 2:
i += 1
nonlocal a
print(a) # [used-before-assignment] FALSE POSITIVE
a = 2
print(a)

def inner_for():
for _ in range(2):
nonlocal a
print(a)
a = 2
print(a)

inner_try()
inner_while()
inner_for()
4 changes: 4 additions & 0 deletions tests/functional/u/used/used_before_assignment.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ possibly-used-before-assignment:121:6:121:11::Possibly using variable 'VAR12' be
used-before-assignment:152:10:152:14::Using variable 'SALE' before assignment:INFERENCE
used-before-assignment:184:10:184:18::Using variable 'ALL_DONE' before assignment:INFERENCE
used-before-assignment:195:6:195:24::Using variable 'NOT_ALWAYS_DEFINED' before assignment:INFERENCE
used-before-assignment:231:10:231:11::Using variable 'x' before assignment:CONTROL_FLOW
possibly-used-before-assignment:245:10:245:15:__:Possibly using variable 'fail1' before assignment:CONTROL_FLOW
used-before-assignment:259:18:259:19:outer_.inner_try:Using variable 'a' before assignment:HIGH
used-before-assignment:270:18:270:19:outer_.inner_while:Using variable 'a' before assignment:HIGH
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Tests for used-before-assignment when postponed evaluation of annotations is enabled"""
# pylint: disable=missing-function-docstring, invalid-name
# pylint: disable=missing-function-docstring, invalid-name, missing-class-docstring, too-few-public-methods
from __future__ import annotations
from typing import TYPE_CHECKING

Expand All @@ -11,3 +11,29 @@

def function_one(m: math): # no error for annotations
return m

# https://github.com/pylint-dev/pylint/issues/8893
if TYPE_CHECKING:
import datetime

def f():
return datetime.datetime.now() # [used-before-assignment]

def g() -> datetime.datetime:
return datetime.datetime.now() # FALSE NEGATIVE

if TYPE_CHECKING:
class X:
pass

def h():
return X() # FALSE NEGATIVE

def i() -> X:
return X() # FALSE NEGATIVE

if TYPE_CHECKING:
from mod import Y

def j():
return {Y() for _ in range(1)} # FALSE NEGATIVE
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
used-before-assignment:10:6:10:9::Using variable 'var' before assignment:INFERENCE
used-before-assignment:20:11:20:19:f:Using variable 'datetime' before assignment:INFERENCE
69 changes: 69 additions & 0 deletions tests/functional/u/used/used_before_assignment_py310.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,72 @@
print("x used to cause used-before-assignment!")
case _:
print("good thing it doesn't now!")


# pylint: disable = missing-function-docstring, redefined-outer-name, missing-class-docstring

# https://github.com/pylint-dev/pylint/issues/9668
from enum import Enum
from pylint.constants import PY311_PLUS
if PY311_PLUS:
from typing import assert_never # pylint: disable=no-name-in-module
else:
from typing_extensions import assert_never

class Example(Enum):
FOO = 1
BAR = 2

def check_value_if_then_match_return(example: Example, should_check: bool) -> str | None:
if should_check:
result = None
else:
match example:
case Example.FOO:
result = "foo"
case Example.BAR:
result = "bar"
case _:
return None

return result # [possibly-used-before-assignment] FALSE POSITIVE

def check_value_if_then_match_raise(example: Example, should_check: bool) -> str | None:
if should_check:
result = None
else:
match example:
case Example.FOO:
result = "foo"
case Example.BAR:
result = "bar"
case _:
raise ValueError("Not a valid enum")

return result # [possibly-used-before-assignment] FALSE POSITIVE

def check_value_if_then_match_assert_never(example: Example, should_check: bool) -> str | None:
if should_check:
result = None
else:
match example:
case Example.FOO:
result = "foo"
case Example.BAR:
result = "bar"
case _:
assert_never(example)

return result # [possibly-used-before-assignment] FALSE POSITIVE

def g(x):
if x is None:
y = 0
else:
match x:
case int():
y = x
case _:
raise TypeError(type(x))

return y # [possibly-used-before-assignment] FALSE POSITIVE
4 changes: 4 additions & 0 deletions tests/functional/u/used/used_before_assignment_py310.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
possibly-used-before-assignment:36:11:36:17:check_value_if_then_match_return:Possibly using variable 'result' before assignment:CONTROL_FLOW
possibly-used-before-assignment:50:11:50:17:check_value_if_then_match_raise:Possibly using variable 'result' before assignment:CONTROL_FLOW
possibly-used-before-assignment:64:11:64:17:check_value_if_then_match_assert_never:Possibly using variable 'result' before assignment:CONTROL_FLOW
possibly-used-before-assignment:76:11:76:12:g:Possibly using variable 'y' before assignment:CONTROL_FLOW
8 changes: 8 additions & 0 deletions tests/functional/u/used/used_before_assignment_py312.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@
type Point[T] = tuple[T, ...]
type Alias[*Ts] = tuple[*Ts]
type Alias[**P] = Callable[P]

# pylint: disable = invalid-name, missing-class-docstring, too-few-public-methods

# https://github.com/pylint-dev/pylint/issues/9815
type IntOrX = int | X # [used-before-assignment] FALSE POSITIVE

class X:
pass
1 change: 1 addition & 0 deletions tests/functional/u/used/used_before_assignment_py312.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
used-before-assignment:11:20:11:21::Using variable 'X' before assignment:HIGH
Loading