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

Move various tests from TestTypeChecker to functional tests #5455

Merged
merged 4 commits into from Dec 2, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
173 changes: 0 additions & 173 deletions tests/checkers/unittest_typecheck.py
Expand Up @@ -200,179 +200,6 @@ def test_nomember_on_c_extension_info_msg(self) -> None:
with self.assertAddsMessages(message):
self.checker.visit_attribute(node)

@set_config(
contextmanager_decorators=(
"contextlib.contextmanager",
".custom_contextmanager",
)
)
def test_custom_context_manager(self):
"""Test that @custom_contextmanager is recognized as configured."""
node = astroid.extract_node(
"""
from contextlib import contextmanager
def custom_contextmanager(f):
return contextmanager(f)
@custom_contextmanager
def dec():
yield
with dec():
pass
"""
)
with self.assertNoMessages():
self.checker.visit_with(node)

def test_invalid_metaclass(self) -> None:
module = astroid.parse(
"""
class InvalidAsMetaclass(object):
pass

class FirstInvalid(object, metaclass=int):
pass

class SecondInvalid(object, metaclass=InvalidAsMetaclass):
pass

class ThirdInvalid(object, metaclass=2):
pass

class FourthInvalid(object, metaclass=InvalidAsMetaclass()):
pass
"""
)
for class_obj, metaclass_name in (
("FourthInvalid", "Instance of .InvalidAsMetaclass"),
("ThirdInvalid", "2"),
("SecondInvalid", "InvalidAsMetaclass"),
("FirstInvalid", "int"),
):
classdef = module[class_obj]
message = MessageTest(
"invalid-metaclass", node=classdef, args=(metaclass_name,)
)
with self.assertAddsMessages(message):
self.checker.visit_classdef(classdef)

def test_invalid_metaclass_function_metaclasses(self) -> None:
module = astroid.parse(
"""
def invalid_metaclass_1(name, bases, attrs):
return int
def invalid_metaclass_2(name, bases, attrs):
return 1
class Invalid(metaclass=invalid_metaclass_1):
pass
class InvalidSecond(metaclass=invalid_metaclass_2):
pass
"""
)
for class_obj, metaclass_name in (("Invalid", "int"), ("InvalidSecond", "1")):
classdef = module[class_obj]
message = MessageTest(
"invalid-metaclass", node=classdef, args=(metaclass_name,)
)
with self.assertAddsMessages(message):
self.checker.visit_classdef(classdef)

def test_typing_namedtuple_not_callable_issue1295(self) -> None:
module = astroid.parse(
"""
import typing
Named = typing.NamedTuple('Named', [('foo', int), ('bar', int)])
named = Named(1, 2)
"""
)
call = module.body[-1].value
callables = call.func.inferred()
assert len(callables) == 1
assert callables[0].callable()
with self.assertNoMessages():
self.checker.visit_call(call)

def test_typing_namedtuple_unsubscriptable_object_issue1295(self) -> None:
module = astroid.parse(
"""
import typing
MyType = typing.Tuple[str, str]
"""
)
subscript = module.body[-1].value
with self.assertNoMessages():
self.checker.visit_subscript(subscript)

def test_staticmethod_multiprocessing_call(self) -> None:
"""Make sure not-callable isn't raised for descriptors

astroid can't process descriptors correctly so
pylint needs to ignore not-callable for them
right now

Test for https://github.com/PyCQA/pylint/issues/1699
"""
call = astroid.extract_node(
"""
import multiprocessing
multiprocessing.current_process() #@
"""
)
with self.assertNoMessages():
self.checker.visit_call(call)

def test_not_callable_uninferable_property(self) -> None:
"""Make sure not-callable isn't raised for uninferable
properties
"""
call = astroid.extract_node(
"""
class A:
@property
def call(self):
return undefined

a = A()
a.call() #@
"""
)
with self.assertNoMessages():
self.checker.visit_call(call)

def test_descriptor_call(self) -> None:
call = astroid.extract_node(
"""
def func():
pass

class ADescriptor:
def __get__(self, instance, owner):
return func

class AggregateCls:
a = ADescriptor()

AggregateCls().a() #@
"""
)
with self.assertNoMessages():
self.checker.visit_call(call)

def test_unknown_parent(self) -> None:
"""Make sure the callable check does not crash when a node's parent
cannot be determined.
"""
call = astroid.extract_node(
"""
def get_num(n):
return 2 * n
get_num(10)()
"""
)
with self.assertAddsMessages(
MessageTest("not-callable", node=call, args="get_num(10)")
):
self.checker.visit_call(call)


class TestTypeCheckerOnDecorators(CheckerTestCase):
"Tests for pylint.checkers.typecheck on decorated functions."
Expand Down
32 changes: 32 additions & 0 deletions tests/functional/i/invalid/m/invalid_metaclass.py
Expand Up @@ -32,3 +32,35 @@ class ThirdGood(object):
@six.add_metaclass(ValidAsMetaclass)
class FourthGood(object):
pass


class FirstInvalid(object, metaclass=int): # [invalid-metaclass]
pass


class SecondInvalid(object, metaclass=InvalidAsMetaclass): # [invalid-metaclass]
pass


class ThirdInvalid(object, metaclass=2): # [invalid-metaclass]
pass


class FourthInvalid(object, metaclass=InvalidAsMetaclass()): # [invalid-metaclass]
pass


def invalid_metaclass_1(name, bases, attrs):
return int


def invalid_metaclass_2(name, bases, attrs):
return 1


class Invalid(metaclass=invalid_metaclass_1): # [invalid-metaclass]
pass


class InvalidSecond(metaclass=invalid_metaclass_2): # [invalid-metaclass]
pass
6 changes: 6 additions & 0 deletions tests/functional/i/invalid/m/invalid_metaclass.txt
@@ -0,0 +1,6 @@
invalid-metaclass:37:0:38:8:FirstInvalid:Invalid metaclass 'int' used:UNDEFINED
invalid-metaclass:41:0:42:8:SecondInvalid:Invalid metaclass 'InvalidAsMetaclass' used:UNDEFINED
invalid-metaclass:45:0:46:8:ThirdInvalid:Invalid metaclass '2' used:UNDEFINED
invalid-metaclass:49:0:50:8:FourthInvalid:Invalid metaclass 'Instance of invalid_metaclass.InvalidAsMetaclass' used:UNDEFINED
invalid-metaclass:61:0:62:8:Invalid:Invalid metaclass 'int' used:UNDEFINED
invalid-metaclass:65:0:66:8:InvalidSecond:Invalid metaclass '1' used:UNDEFINED
57 changes: 56 additions & 1 deletion tests/functional/n/not_callable.py
@@ -1,4 +1,5 @@
# pylint: disable=missing-docstring,no-self-use,too-few-public-methods,wrong-import-position,useless-object-inheritance,use-dict-literal
# pylint: disable=wrong-import-order, undefined-variable

REVISION = None

Expand Down Expand Up @@ -117,7 +118,8 @@ def does_not_make_sense(self):
PROP1.does_not_make_sense()


import missing # pylint: disable=import-error
import missing # pylint: disable=import-error


class UnknownBaseCallable(missing.Blah):
pass
Expand All @@ -133,3 +135,56 @@ def value(self):
return 42

CLASS_WITH_PROP = ClassWithProperty().value() # [not-callable]

# Test typing.Namedtuple not callable
# See: https://github.com/PyCQA/pylint/issues/1295
import typing

Named = typing.NamedTuple("Named", [("foo", int), ("bar", int)])
named = Named(1, 2)

# Test descriptor call
def func():
pass


class ADescriptor:
def __get__(self, instance, owner):
return func


class AggregateCls:
a = ADescriptor()


AggregateCls().a()


# Make sure not-callable isn't raised for descriptors

# astroid can't process descriptors correctly so
# pylint needs to ignore not-callable for them
# right now

# Test for https://github.com/PyCQA/pylint/issues/1699

import multiprocessing

multiprocessing.current_process()

# Make sure not-callable isn't raised for uninferable properties
class MyClass:
@property
def call(self):
return undefined


a = A()
a.call()

# Make sure the callable check does not crash when a node's parent cannot be determined.
def get_number(arg):
return 2 * arg


get_number(10)() # [not-callable]
19 changes: 10 additions & 9 deletions tests/functional/n/not_callable.txt
@@ -1,9 +1,10 @@
not-callable:5:0:5:10::REVISION is not callable:UNDEFINED
not-callable:23:12:23:22::INSTANCE is not callable:UNDEFINED
not-callable:25:12:25:18::LIST is not callable:UNDEFINED
not-callable:27:12:27:18::DICT is not callable:UNDEFINED
not-callable:29:12:29:19::TUPLE is not callable:UNDEFINED
not-callable:31:12:31:17::INT is not callable:UNDEFINED
not-callable:66:0:66:13::PROP.test is not callable:UNDEFINED
not-callable:67:0:67:13::PROP.custom is not callable:UNDEFINED
not-callable:135:18:135:45::ClassWithProperty().value is not callable:UNDEFINED
not-callable:6:0:6:10::REVISION is not callable:UNDEFINED
not-callable:24:12:24:22::INSTANCE is not callable:UNDEFINED
not-callable:26:12:26:18::LIST is not callable:UNDEFINED
not-callable:28:12:28:18::DICT is not callable:UNDEFINED
not-callable:30:12:30:19::TUPLE is not callable:UNDEFINED
not-callable:32:12:32:17::INT is not callable:UNDEFINED
not-callable:67:0:67:13::PROP.test is not callable:UNDEFINED
not-callable:68:0:68:13::PROP.custom is not callable:UNDEFINED
not-callable:137:18:137:45::ClassWithProperty().value is not callable:UNDEFINED
not-callable:190:0:190:16::get_number(10) is not callable:UNDEFINED
7 changes: 7 additions & 0 deletions tests/functional/u/unsubscriptable_object.py
@@ -0,0 +1,7 @@
"""Tests for unscubscriptable-object"""

# Test for typing.NamedTuple
# See: https://github.com/PyCQA/pylint/issues/1295
import typing

MyType = typing.Tuple[str, str]