Skip to content

Commit

Permalink
ignored-modules can skip submodules. Close #3135
Browse files Browse the repository at this point in the history
  • Loading branch information
PCManticore committed Sep 26, 2019
1 parent 5f8084c commit 4d0fbec
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 10 deletions.
9 changes: 9 additions & 0 deletions ChangeLog
Expand Up @@ -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?
===========================

Expand Down
36 changes: 27 additions & 9 deletions pylint/checkers/typecheck.py
Expand Up @@ -43,6 +43,7 @@
import shlex
import sys
import types
from collections import deque
from collections.abc import Sequence
from functools import singledispatch

Expand Down Expand Up @@ -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*
Expand All @@ -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
Expand Down
14 changes: 13 additions & 1 deletion tests/unittest_checker_typecheck.py
Expand Up @@ -75,7 +75,7 @@ def test_no_member_in_getattr_ignored(self):
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(
"""
Expand All @@ -89,6 +89,18 @@ def test_ignored_modules_invalid_pattern(self):
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(
Expand Down

0 comments on commit 4d0fbec

Please sign in to comment.