Pylint: False positive try-except-raise

Created on 29 Aug 2019  路  7Comments  路  Source: PyCQA/pylint

Steps to reproduce

When you need to catch an exception in the for loop iterator, you write something like this:

def wrapper(gen):
  while True:
    try:
      yield next(gen)
    except StopIteration:
      raise
    except Exception as e:
      print(e) # or whatever kind of logging you want
 ```
In this case, the immediate `raise` after `except` is _correct_ because there is another `except` after that.

### Current behavior

foo.py:109: warning (W0706, try-except-raise, cursor_wrapper) The except handler raises immediately


### Expected behavior

No diagnostics

### pylint --version output

pylint 2.3.1
astroid 2.2.5
Python 3.7.4 (default, Jul 9 2019, 18:13:23)
[Clang 10.0.1 (clang-1001.0.46.4)]
```

bug checkers

All 7 comments

Thanks for creating the issue, this makes sense and it's definitely a bug.

Gave this another go and cannot reproduce it. We also have code around these except handlers being followed by generic ones, so not sure how this issue was triggered for you. Do let me know if you had a different example for which you can reproduce the issue consistently using the latest pylint.

here you go

"https://github.com/PyCQA/pylint/issues/3083"

import sys

import bson

class Pull():
    "Pull data from MongoDB"
    def __init__(self):
        self.cursor_bson_errors = []

    def bson_cursor_wrapper(self, cursor):
        """Catch bson errors and report them in details.
        https://stackoverflow.com/q/13653783/850781
        https://stackoverflow.com/q/46933995/850781"""
        while True:
            try:
                yield next(cursor)
            except StopIteration:
                raise
            except bson.errors.InvalidBSON as exn:
                _exc_type, exc_value, exc_traceback = sys.exc_info()
                assert exn == exc_value
                last_tb = exc_traceback
                while last_tb.tb_next:
                    last_tb = last_tb.tb_next
                # File "/.../bson/__init__.py", line 1098, in _decode_all_selective
                self.cursor_bson_errors.append(len(last_tb.tb_frame.f_locals["data"]))

here is what I see:

epylint .../python/pylint-3083.py
************* Module pylint-3083
.../python/pylint-3083.py:19: warning (W0706, try-except-raise, Pull.bson_cursor_wrapper) The except handler raises immediately

Still cannot reproduce with 3.7.2, pylint 2.3.1 and astroid 2.2.5.

looks like a regression - I have

pylint 2.4.2
astroid 2.3.1
Python 3.7.4 (default, Sep  7 2019, 18:27:02) 
[Clang 10.0.1 (clang-1001.0.46.4)]

similar issue with this use case:

        try:
            raise Exception(42)
        except Exception:
            raise
        finally:
            print(42)

with

pylint 2.4.3
astroid 2.3.2
Python 3.5.3 (default, Sep 27 2018, 17:25:39) 
[GCC 6.3.0 20170516]

Same for me:

import asyncio

try:
    _ = 1
except asyncio.CancelledError:
    raise
except Exception as err:
    raise ValueError

Interesting that if asyncio.CancelledError is changed to e.g. TypeError, pylint shows no warning.

pylint 2.4.4
astroid 2.3.3
Python 3.8.1 (default, Dec 21 2019, 20:57:38)
[GCC 9.2.0]

UPD:
It happens if exception is directly inherited from BaseException, not Exception, so minimal example is following

class MyVeryBasicError(BaseException):
    pass

try:
    pass
except MyVeryBasicError:
    raise
except Exception as err:
    raise ValueError

So it's not a bug, because asyncio.CancelledError is inherited from BaseException and will not be caught by except Exception: branch. In case of StopIteration pylint gives no warning to me.

Was this page helpful?
0 / 5 - 0 ratings