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)]
```
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.