diff options
Diffstat (limited to 'tests/checkers/unittest_utils.py')
-rw-r--r-- | tests/checkers/unittest_utils.py | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/tests/checkers/unittest_utils.py b/tests/checkers/unittest_utils.py new file mode 100644 index 000000000..9774b2d58 --- /dev/null +++ b/tests/checkers/unittest_utils.py @@ -0,0 +1,406 @@ +# Copyright (c) 2010 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> +# Copyright (c) 2013-2020 Claudiu Popa <pcmanticore@gmail.com> +# Copyright (c) 2013-2014 Google, Inc. +# Copyright (c) 2014 Arun Persaud <arun@nubati.net> +# Copyright (c) 2015 Ionel Cristian Maries <contact@ionelmc.ro> +# Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com> +# Copyright (c) 2018 Alan Chan <achan961117@gmail.com> +# Copyright (c) 2018 Caio Carrara <ccarrara@redhat.com> +# Copyright (c) 2019-2021 Pierre Sassoulas <pierre.sassoulas@gmail.com> +# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> +# Copyright (c) 2019 Nathan Marrow <nmarrow@google.com> +# Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> +# Copyright (c) 2020 Anthony Sottile <asottile@umich.edu> +# Copyright (c) 2021 Daniƫl van Noord <13665637+DanielNoord@users.noreply.github.com> +# Copyright (c) 2021 Marc Mueller <30130371+cdce8p@users.noreply.github.com> + +# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE + +"""Tests for the pylint.checkers.utils module.""" + +from typing import Dict, Union + +import astroid +import pytest + +from pylint.checkers import utils + + +@pytest.mark.parametrize( + "name,expected", + [ + ("min", True), + ("__builtins__", True), + ("__path__", False), + ("__file__", False), + ("whatever", False), + ("mybuiltin", False), + ], +) +def testIsBuiltin(name, expected): + assert utils.is_builtin(name) == expected + + +@pytest.mark.parametrize( + "fn,kw", + [("foo(3)", {"keyword": "bar"}), ("foo(one=a, two=b, three=c)", {"position": 1})], +) +def testGetArgumentFromCallError( + fn: str, kw: Union[Dict[str, int], Dict[str, str]] +) -> None: + with pytest.raises(utils.NoSuchArgumentError): + node = astroid.extract_node(fn) + utils.get_argument_from_call(node, **kw) + + +@pytest.mark.parametrize( + "fn,kw", [("foo(bar=3)", {"keyword": "bar"}), ("foo(a, b, c)", {"position": 1})] +) +def testGetArgumentFromCallExists( + fn: str, kw: Union[Dict[str, int], Dict[str, str]] +) -> None: + node = astroid.extract_node(fn) + assert utils.get_argument_from_call(node, **kw) is not None + + +def testGetArgumentFromCall() -> None: + node = astroid.extract_node("foo(a, not_this_one=1, this_one=2)") + arg = utils.get_argument_from_call(node, position=2, keyword="this_one") + assert arg.value == 2 + + node = astroid.extract_node("foo(a)") + with pytest.raises(utils.NoSuchArgumentError): + utils.get_argument_from_call(node, position=1) + with pytest.raises(ValueError): + utils.get_argument_from_call(node, None, None) + name = utils.get_argument_from_call(node, position=0) + assert name.name == "a" + + +def test_error_of_type() -> None: + nodes = astroid.extract_node( + """ + try: pass + except AttributeError: #@ + pass + try: pass + except Exception: #@ + pass + except: #@ + pass + """ + ) + assert utils.error_of_type(nodes[0], AttributeError) + assert utils.error_of_type(nodes[0], (AttributeError,)) + assert not utils.error_of_type(nodes[0], Exception) + assert utils.error_of_type(nodes[1], Exception) + + +def test_node_ignores_exception() -> None: + nodes = astroid.extract_node( + """ + try: + 1/0 #@ + except ZeroDivisionError: + pass + try: + 1/0 #@ + except Exception: + pass + try: + 2/0 #@ + except: + pass + try: + 1/0 #@ + except ValueError: + pass + """ + ) + assert utils.node_ignores_exception(nodes[0], ZeroDivisionError) + assert not utils.node_ignores_exception(nodes[1], ZeroDivisionError) + assert not utils.node_ignores_exception(nodes[2], ZeroDivisionError) + assert not utils.node_ignores_exception(nodes[3], ZeroDivisionError) + + +def test_is_subclass_of_node_b_derived_from_node_a() -> None: + nodes = astroid.extract_node( + """ + class Superclass: #@ + pass + + class Subclass(Superclass): #@ + pass + """ + ) + assert utils.is_subclass_of(nodes[1], nodes[0]) + + +def test_is_subclass_of_node_b_not_derived_from_node_a() -> None: + nodes = astroid.extract_node( + """ + class OneClass: #@ + pass + + class AnotherClass: #@ + pass + """ + ) + assert not utils.is_subclass_of(nodes[1], nodes[0]) + + +def test_is_subclass_of_not_classdefs() -> None: + node = astroid.extract_node( + """ + class OneClass: #@ + pass + """ + ) + assert not utils.is_subclass_of(None, node) + assert not utils.is_subclass_of(node, None) + assert not utils.is_subclass_of(None, None) + + +def test_parse_format_method_string() -> None: + samples = [ + ("{}", 1), + ("{}:{}", 2), + ("{field}", 1), + ("{:5}", 1), + ("{:10}", 1), + ("{field:10}", 1), + ("{field:10}{{}}", 1), + ("{:5}{!r:10}", 2), + ("{:5}{}{{}}{}", 3), + ("{0}{1}{0}", 2), + ("Coordinates: {latitude}, {longitude}", 2), + ("X: {0[0]}; Y: {0[1]}", 1), + ("{:*^30}", 1), + ("{!r:}", 1), + ] + for fmt, count in samples: + keys, num_args, pos_args = utils.parse_format_method_string(fmt) + keyword_args = len({k for k, l in keys if not isinstance(k, int)}) + assert keyword_args + num_args + pos_args == count + + +def test_inherit_from_std_ex_recursive_definition() -> None: + node = astroid.extract_node( + """ + import datetime + class First(datetime.datetime): + pass + class Second(datetime.datetime): #@ + pass + datetime.datetime = First + datetime.datetime = Second + """ + ) + assert not utils.inherit_from_std_ex(node) + + +def test_get_node_last_lineno_simple() -> None: + node = astroid.extract_node( + """ + pass + """ + ) + assert utils.get_node_last_lineno(node) == 2 + + +def test_get_node_last_lineno_if_simple() -> None: + node = astroid.extract_node( + """ + if True: + print(1) + pass + """ + ) + assert utils.get_node_last_lineno(node) == 4 + + +def test_get_node_last_lineno_if_elseif_else() -> None: + node = astroid.extract_node( + """ + if True: + print(1) + elif False: + print(2) + else: + print(3) + """ + ) + assert utils.get_node_last_lineno(node) == 7 + + +def test_get_node_last_lineno_while() -> None: + node = astroid.extract_node( + """ + while True: + print(1) + """ + ) + assert utils.get_node_last_lineno(node) == 3 + + +def test_get_node_last_lineno_while_else() -> None: + node = astroid.extract_node( + """ + while True: + print(1) + else: + print(2) + """ + ) + assert utils.get_node_last_lineno(node) == 5 + + +def test_get_node_last_lineno_for() -> None: + node = astroid.extract_node( + """ + for x in range(0, 5): + print(1) + """ + ) + assert utils.get_node_last_lineno(node) == 3 + + +def test_get_node_last_lineno_for_else() -> None: + node = astroid.extract_node( + """ + for x in range(0, 5): + print(1) + else: + print(2) + """ + ) + assert utils.get_node_last_lineno(node) == 5 + + +def test_get_node_last_lineno_try() -> None: + node = astroid.extract_node( + """ + try: + print(1) + except ValueError: + print(2) + except Exception: + print(3) + """ + ) + assert utils.get_node_last_lineno(node) == 7 + + +def test_get_node_last_lineno_try_except_else() -> None: + node = astroid.extract_node( + """ + try: + print(1) + except Exception: + print(2) + print(3) + else: + print(4) + """ + ) + assert utils.get_node_last_lineno(node) == 8 + + +def test_get_node_last_lineno_try_except_finally() -> None: + node = astroid.extract_node( + """ + try: + print(1) + except Exception: + print(2) + finally: + print(4) + """ + ) + assert utils.get_node_last_lineno(node) == 7 + + +def test_get_node_last_lineno_try_except_else_finally() -> None: + node = astroid.extract_node( + """ + try: + print(1) + except Exception: + print(2) + else: + print(3) + finally: + print(4) + """ + ) + assert utils.get_node_last_lineno(node) == 9 + + +def test_get_node_last_lineno_with() -> None: + node = astroid.extract_node( + """ + with x as y: + print(1) + pass + """ + ) + assert utils.get_node_last_lineno(node) == 4 + + +def test_get_node_last_lineno_method() -> None: + node = astroid.extract_node( + """ + def x(a, b): + print(a, b) + pass + """ + ) + assert utils.get_node_last_lineno(node) == 4 + + +def test_get_node_last_lineno_decorator() -> None: + node = astroid.extract_node( + """ + @decor() + def x(a, b): + print(a, b) + pass + """ + ) + assert utils.get_node_last_lineno(node) == 5 + + +def test_get_node_last_lineno_class() -> None: + node = astroid.extract_node( + """ + class C(object): + CONST = True + + def x(self, b): + print(b) + + def y(self): + pass + pass + """ + ) + assert utils.get_node_last_lineno(node) == 10 + + +def test_get_node_last_lineno_combined() -> None: + node = astroid.extract_node( + """ + class C(object): + CONST = True + + def y(self): + try: + pass + except: + pass + finally: + pass + """ + ) + assert utils.get_node_last_lineno(node) == 11 |