From 1ae9fcc6b1f83bad403da4f6cc3e69ddb94d49d4 Mon Sep 17 00:00:00 2001 From: Claudiu Popa Date: Tue, 19 Feb 2019 09:13:07 +0100 Subject: Protect against `NonDeducibleTypeHierarchy` when calling semi-private `is_subtype` `astroid.helpers.is_subtype` raises `NonDeducibleTypeHierarchy` when it cannot infer the base classes of the given types, but that makes sense in its context given that the method is mostly used to inform the inference process about the hierarchy of classes. Doesn't make that much sense for ``pylint`` itself, which is why we're handling the exception here, rather than in ``astroid`` Close PyCQA/astroid#644 --- ChangeLog | 10 +++++++++ pylint/checkers/utils.py | 8 ++++++-- pylint/test/functional/try_except_raise_crash.py | 25 +++++++++++++++++++++++ pylint/test/functional/try_except_raise_crash.txt | 1 + 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 pylint/test/functional/try_except_raise_crash.py create mode 100644 pylint/test/functional/try_except_raise_crash.txt diff --git a/ChangeLog b/ChangeLog index 4e7fc9874..dad70c637 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,16 @@ What's New in Pylint 2.3.0? Release date: TBA +* Protect against `NonDeducibleTypeHierarchy` when calling semi-private `is_subtype` + + `astroid.helpers.is_subtype` raises `NonDeducibleTypeHierarchy` when it cannot infer + the base classes of the given types, but that makes sense in its context given that + the method is mostly used to inform the inference process about the hierarchy of classes. + Doesn't make that much sense for ``pylint`` itself, which is why we're handling the + exception here, rather than in ``astroid`` + + Close PyCQA/astroid#644 + * Added a new command line option ``list-groups`` for listing all the check groups ``pylint`` knows about. * Allow ``BaseException`` for emitting ``broad-except``, just like ``Exception``. diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py index 3cc292115..b4129389f 100644 --- a/pylint/checkers/utils.py +++ b/pylint/checkers/utils.py @@ -40,6 +40,7 @@ from typing import Optional, Iterable, Tuple, Callable, Set, Union, Match, Dict, import _string # pylint: disable=wrong-import-position, wrong-import-order import astroid +from astroid.exceptions import _NonDeducibleTypeHierarchy from astroid import bases as _bases from astroid import scoped_nodes @@ -1202,6 +1203,9 @@ def is_subclass_of(child: astroid.ClassDef, parent: astroid.ClassDef) -> bool: return False for ancestor in child.ancestors(): - if astroid.helpers.is_subtype(ancestor, parent): - return True + try: + if astroid.helpers.is_subtype(ancestor, parent): + return True + except _NonDeducibleTypeHierarchy: + continue return False diff --git a/pylint/test/functional/try_except_raise_crash.py b/pylint/test/functional/try_except_raise_crash.py new file mode 100644 index 000000000..7a1f8d972 --- /dev/null +++ b/pylint/test/functional/try_except_raise_crash.py @@ -0,0 +1,25 @@ +# pylint: disable=missing-docstring,too-many-ancestors, broad-except +import collections.abc +from typing import TYPE_CHECKING, Any, MutableMapping + +if TYPE_CHECKING: + BaseClass = MutableMapping[str, Any] +else: + BaseClass = collections.abc.MutableMapping + + +class TestBaseException(BaseClass): + pass + + +class TestException(TestBaseException): + pass + + +def test(): + try: + 1 / 0 + except TestException: # [try-except-raise] + raise + except Exception: + pass diff --git a/pylint/test/functional/try_except_raise_crash.txt b/pylint/test/functional/try_except_raise_crash.txt new file mode 100644 index 000000000..a99476ab9 --- /dev/null +++ b/pylint/test/functional/try_except_raise_crash.txt @@ -0,0 +1 @@ +try-except-raise:22:test:The except handler raises immediately -- cgit v1.2.1