| # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html |
| # For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE |
| # Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt |
| |
| import os |
| import re |
| import sys |
| from pathlib import Path |
| |
| import astroid |
| |
| from pylint.checkers import variables |
| from pylint.interfaces import HIGH |
| from pylint.testutils import CheckerTestCase, MessageTest, linter, set_config |
| from pylint.testutils.reporter_for_tests import GenericTestReporter |
| |
| REGR_DATA_DIR = str(Path(__file__).parent / ".." / "regrtest_data") |
| |
| |
| class TestVariablesChecker(CheckerTestCase): |
| CHECKER_CLASS = variables.VariablesChecker |
| |
| def test_all_elements_without_parent(self) -> None: |
| node = astroid.extract_node("__all__ = []") |
| node.value.elts.append(astroid.Const("test")) |
| root = node.root() |
| with self.assertNoMessages(): |
| self.checker.visit_module(root) |
| self.checker.leave_module(root) |
| |
| |
| class TestVariablesCheckerWithTearDown(CheckerTestCase): |
| CHECKER_CLASS = variables.VariablesChecker |
| |
| def setup_method(self) -> None: |
| super().setup_method() |
| self._to_consume_backup = self.checker._to_consume |
| self.checker._to_consume = [] |
| |
| def teardown_method(self) -> None: |
| self.checker._to_consume = self._to_consume_backup |
| |
| @set_config(callbacks=("callback_", "_callback")) |
| def test_custom_callback_string(self) -> None: |
| """Test the --callbacks option works.""" |
| node = astroid.extract_node( |
| """ |
| def callback_one(abc): |
| ''' should not emit unused-argument. ''' |
| """ |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_functiondef(node) |
| self.checker.leave_functiondef(node) |
| |
| node = astroid.extract_node( |
| """ |
| def two_callback(abc, defg): |
| ''' should not emit unused-argument. ''' |
| """ |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_functiondef(node) |
| self.checker.leave_functiondef(node) |
| |
| node = astroid.extract_node( |
| """ |
| def normal_func(abc): |
| ''' should emit unused-argument. ''' |
| """ |
| ) |
| with self.assertAddsMessages( |
| MessageTest( |
| "unused-argument", |
| node=node["abc"], |
| args="abc", |
| confidence=HIGH, |
| line=2, |
| col_offset=16, |
| end_line=2, |
| end_col_offset=19, |
| ) |
| ): |
| self.checker.visit_functiondef(node) |
| self.checker.leave_functiondef(node) |
| |
| node = astroid.extract_node( |
| """ |
| def cb_func(abc): |
| ''' Previous callbacks are overridden. ''' |
| """ |
| ) |
| with self.assertAddsMessages( |
| MessageTest( |
| "unused-argument", |
| node=node["abc"], |
| args="abc", |
| confidence=HIGH, |
| line=2, |
| col_offset=12, |
| end_line=2, |
| end_col_offset=15, |
| ) |
| ): |
| self.checker.visit_functiondef(node) |
| self.checker.leave_functiondef(node) |
| |
| @set_config(redefining_builtins_modules=("os",)) |
| def test_redefined_builtin_modname_not_ignored(self) -> None: |
| node = astroid.parse( |
| """ |
| from future.builtins import open |
| """ |
| ) |
| with self.assertAddsMessages( |
| MessageTest( |
| "redefined-builtin", |
| node=node.body[0], |
| args="open", |
| line=2, |
| col_offset=0, |
| end_line=2, |
| end_col_offset=32, |
| ) |
| ): |
| self.checker.visit_module(node) |
| |
| @set_config(redefining_builtins_modules=("os",)) |
| def test_redefined_builtin_in_function(self) -> None: |
| node = astroid.extract_node( |
| """ |
| def test(): |
| from os import open |
| """ |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_module(node.root()) |
| self.checker.visit_functiondef(node) |
| |
| def test_import_as_underscore(self) -> None: |
| node = astroid.parse( |
| """ |
| import math as _ |
| """ |
| ) |
| with self.assertNoMessages(): |
| self.walk(node) |
| |
| def test_lambda_in_classdef(self) -> None: |
| # Make sure lambda doesn't raises |
| # Undefined-method in class def |
| |
| # Issue 1824 |
| # https://github.com/pylint-dev/pylint/issues/1824 |
| node = astroid.parse( |
| """ |
| class MyObject(object): |
| method1 = lambda func: func() |
| method2 = lambda function: function() |
| """ |
| ) |
| with self.assertNoMessages(): |
| self.walk(node) |
| |
| def test_nested_lambda(self) -> None: |
| """Make sure variables from parent lambdas |
| aren't noted as undefined. |
| |
| https://github.com/pylint-dev/pylint/issues/760 |
| """ |
| node = astroid.parse( |
| """ |
| lambda x: lambda: x + 1 |
| """ |
| ) |
| with self.assertNoMessages(): |
| self.walk(node) |
| |
| @set_config(ignored_argument_names=re.compile("arg")) |
| def test_ignored_argument_names_no_message(self) -> None: |
| """Make sure is_ignored_argument_names properly ignores |
| function arguments. |
| """ |
| node = astroid.parse( |
| """ |
| def fooby(arg): |
| pass |
| """ |
| ) |
| with self.assertNoMessages(): |
| self.walk(node) |
| |
| @set_config(ignored_argument_names=re.compile("args|kwargs")) |
| def test_ignored_argument_names_starred_args(self) -> None: |
| node = astroid.parse( |
| """ |
| def fooby(*args, **kwargs): |
| pass |
| """ |
| ) |
| with self.assertNoMessages(): |
| self.walk(node) |
| |
| |
| class TestMissingSubmodule(CheckerTestCase): |
| CHECKER_CLASS = variables.VariablesChecker |
| |
| @staticmethod |
| def test_package_all() -> None: |
| sys.path.insert(0, REGR_DATA_DIR) |
| try: |
| linter.check([os.path.join(REGR_DATA_DIR, "package_all")]) |
| assert isinstance(linter.reporter, GenericTestReporter) |
| got = linter.reporter.finalize().strip() |
| assert got == "E: 3: Undefined variable name 'missing' in __all__" |
| finally: |
| sys.path.pop(0) |