diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2019-09-26 08:20:36 +0200 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2019-09-26 08:22:05 +0200 |
commit | 4d0fbec72d5c55591a9c35fa7a1bfdaa03be0e61 (patch) | |
tree | c6e724d554a4224851e3f5d0cc33def2a7922563 | |
parent | 5f8084cfa046b937c6039a1194f935cae82438fb (diff) | |
download | pylint-git-4d0fbec72d5c55591a9c35fa7a1bfdaa03be0e61.tar.gz |
``ignored-modules`` can skip submodules. Close #3135
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | pylint/checkers/typecheck.py | 36 | ||||
-rw-r--r-- | tests/unittest_checker_typecheck.py | 14 |
3 files changed, 49 insertions, 10 deletions
@@ -2,6 +2,15 @@ Pylint's ChangeLog ------------------ +What's New in Pylint 2.4.2? +=========================== + +Release date: TBA + + +* ``ignored-modules`` can skip submodules. Close #3135 + + What's New in Pylint 2.4.1? =========================== diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py index e11902208..53014bc54 100644 --- a/pylint/checkers/typecheck.py +++ b/pylint/checkers/typecheck.py @@ -43,6 +43,7 @@ import re import shlex import sys import types +from collections import deque from collections.abc import Sequence from functools import singledispatch @@ -99,7 +100,7 @@ def _flatten_container(iterable): yield item -def _is_owner_ignored(owner, name, ignored_classes, ignored_modules): +def _is_owner_ignored(owner, attrname, ignored_classes, ignored_modules): """Check if the given owner should be ignored This will verify if the owner's module is in *ignored_modules* @@ -114,20 +115,37 @@ def _is_owner_ignored(owner, name, ignored_classes, ignored_modules): ignored_modules = set(ignored_modules) module_name = owner.root().name module_qname = owner.root().qname() - if any( - module_name in ignored_modules - or module_qname in ignored_modules - or fnmatch.fnmatch(module_qname, ignore) - for ignore in ignored_modules - ): - return True + for ignore in ignored_modules: + # Try to match the module name / fully qualified name directly + if module_qname in ignored_modules or module_name in ignored_modules: + return True + + # Try to see if the ignores pattern match against the module name. + if fnmatch.fnmatch(module_qname, ignore): + return True + + # Otherwise we might have a root module name being ignored, + # and the qualified owner has more levels of depth. + parts = deque(module_name.split(".")) + current_module = "" + + while parts: + part = parts.popleft() + if not current_module: + current_module = part + else: + current_module += ".{}".format(part) + if current_module in ignored_modules: + return True + + # Match against ignored classes. ignored_classes = set(ignored_classes) if hasattr(owner, "qname"): qname = owner.qname() else: qname = "" - return any(ignore in (name, qname) for ignore in ignored_classes) + return any(ignore in (attrname, qname) for ignore in ignored_classes) @singledispatch diff --git a/tests/unittest_checker_typecheck.py b/tests/unittest_checker_typecheck.py index 5c55c6710..f63680cdd 100644 --- a/tests/unittest_checker_typecheck.py +++ b/tests/unittest_checker_typecheck.py @@ -75,7 +75,7 @@ class TestTypeChecker(CheckerTestCase): with self.assertNoMessages(): self.checker.visit_attribute(node) - @set_config(ignored_classes=("xml.etree.",)) + @set_config(ignored_modules=("xml.etree.",)) def test_ignored_modules_invalid_pattern(self): node = astroid.extract_node( """ @@ -89,6 +89,18 @@ class TestTypeChecker(CheckerTestCase): with self.assertAddsMessages(message): self.checker.visit_attribute(node) + @set_config(ignored_modules=("xml",)) + def test_ignored_modules_root_one_applies_as_well(self): + # Check that when a root module is completely ignored, submodules are skipped. + node = astroid.extract_node( + """ + import xml + xml.etree.Lala + """ + ) + with self.assertNoMessages(): + self.checker.visit_attribute(node) + @set_config(ignored_modules=("xml.etree*",)) def test_ignored_modules_patterns(self): node = astroid.extract_node( |