Problem
When an exception is raised from the user python code during copy(), the traceback looks like this:
Traceback (most recent call last):
<snipped>
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "venv/lib/python3.11/site-packages/psycopg/cursor.py", line 900, in copy
yield copy
File "myfile.py", line 86, in myfunc
raise MyException() from e
MyException
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "myotherfile.py", line 1251, in myotherfunc
with cursor.copy(sql.SQL('''
File "/usr/lib/python3.11/contextlib.py", line 155, in __exit__
self.gen.throw(typ, value, traceback)
File "venv/lib/python3.11/site-packages/psycopg/cursor.py", line 902, in copy
raise ex.with_traceback(None)
psycopg.errors.QueryCanceled: COPY from stdin failed: error from Python: MyException -
If I want to inspect the underlying exception, I currently need to check __context__. But __context__ should be reserved for unintended bugs in error handling code. This makes it hard to distinguish real underlying errors from exceptions unintentionally raised in psycopg's exception handling code.
Suggested solution
Change to explicit chaining, that is raise QueryCanceled() from underlying_exc instead of raise without from in the exception handling context.
This will change the traceback message to say "The above exception was the direct cause of the following exception". Also will change __context__ to None and make __cause__ have the exception instead.
There are linters that can help with detecting this more holistically, for example flake8-bugbear B904, though I didn't check if it will detect this case.
Problem
When an exception is raised from the user python code during
copy(), the traceback looks like this:If I want to inspect the underlying exception, I currently need to check
__context__. But__context__should be reserved for unintended bugs in error handling code. This makes it hard to distinguish real underlying errors from exceptions unintentionally raised in psycopg's exception handling code.Suggested solution
Change to explicit chaining, that is
raise QueryCanceled() from underlying_excinstead ofraisewithoutfromin the exception handling context.This will change the traceback message to say "The above exception was the direct cause of the following exception". Also will change
__context__to None and make__cause__have the exception instead.There are linters that can help with detecting this more holistically, for example flake8-bugbear B904, though I didn't check if it will detect this case.