diff options
author | cpopa <devnull@localhost> | 2014-01-01 19:54:06 +0200 |
---|---|---|
committer | cpopa <devnull@localhost> | 2014-01-01 19:54:06 +0200 |
commit | 737dc750f6756e5f87294143bc9fe309feeeb495 (patch) | |
tree | 88c7cf1084496d2682adbf90a72573a46ea1be3a | |
parent | 3927b761d923c9d8d32290c5a694acda9083480b (diff) | |
download | pylint-737dc750f6756e5f87294143bc9fe309feeeb495.tar.gz |
Fix false positive for catching-non-exception, for C based exceptions.
-rw-r--r-- | checkers/exceptions.py | 30 | ||||
-rw-r--r-- | test/input/func_catching_non_exception.py | 15 | ||||
-rw-r--r-- | test/messages/func_catching_non_exception.txt | 6 |
3 files changed, 45 insertions, 6 deletions
diff --git a/checkers/exceptions.py b/checkers/exceptions.py index 9843001..175c77b 100644 --- a/checkers/exceptions.py +++ b/checkers/exceptions.py @@ -25,6 +25,23 @@ from pylint.checkers import BaseChecker from pylint.checkers.utils import is_empty, is_raising, check_messages from pylint.interfaces import IAstroidChecker +def infer_bases(klass): + """ Fully infer the bases of the klass node. + + This doesn't use .ancestors(), because we need + the non-inferable nodes (YES nodes), + which can't be retrieved from .ancestors() + """ + for base in klass.bases: + try: + inferit = base.infer().next() + except astroid.InferenceError: + continue + if inferit is YES: + yield inferit + else: + for base in infer_bases(inferit): + yield base OVERGENERAL_EXCEPTIONS = ('Exception',) @@ -214,9 +231,16 @@ class ExceptionsChecker(BaseChecker): if (not inherit_from_std_ex(exc) and exc.root().name != BUILTINS_NAME): - self.add_message('catching-non-exception', - node=handler.type, - args=(exc.name, )) + # try to see if the exception is based on a C based + # exception, by infering all the base classes and + # looking for inference errors + bases = infer_bases(exc) + fully_infered = not any(inferit is YES + for inferit in bases) + if fully_infered: + self.add_message('catching-non-exception', + node=handler.type, + args=(exc.name, )) exceptions_classes += excs diff --git a/test/input/func_catching_non_exception.py b/test/input/func_catching_non_exception.py index e6bfc57..d8e0e2d 100644 --- a/test/input/func_catching_non_exception.py +++ b/test/input/func_catching_non_exception.py @@ -1,5 +1,6 @@ """test non-exceptions catched """ +import socket __revision__ = 1 @@ -19,6 +20,16 @@ class MySecondGoodException(MyGoodException): """ custom 'exception' """ pass +class SkipException(socket.error): + """ This gave false positives for Python 2, + but not for Python 3, due to exception + hierarchy rewrite. + """ + +class SecondSkipException(SkipException): + """ This too shouldn't give false + positives. """ + try: 1 + 1 except MyException: @@ -39,3 +50,7 @@ try: except (MyGoodException, MySecondGoodException): print "should work" +try: + 1 + 3 +except (SkipException, SecondSkipException): + print "should work" diff --git a/test/messages/func_catching_non_exception.txt b/test/messages/func_catching_non_exception.txt index 9dc23eb..19f22ab 100644 --- a/test/messages/func_catching_non_exception.txt +++ b/test/messages/func_catching_non_exception.txt @@ -1,3 +1,3 @@ -E: 24: Catching an exception which doesn't inherit from BaseException: MyException -E: 29: Catching an exception which doesn't inherit from BaseException: MyException -E: 29: Catching an exception which doesn't inherit from BaseException: MySecondException
\ No newline at end of file +E: 35: Catching an exception which doesn't inherit from BaseException: MyException +E: 40: Catching an exception which doesn't inherit from BaseException: MyException +E: 40: Catching an exception which doesn't inherit from BaseException: MySecondException
\ No newline at end of file |