#25761 closed Bug (fixed)
Re-raised exceptions with __cause__ should also set __traceback__ on the exception
Reported by: | Raphaël Hertzog | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.8 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
In bug https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=802677 we have a report that testtools is broken when handling database exceptions raised by Django. This has been brought to the upstream developers of testtools who were quick to point out that Django is at fault:
https://github.com/testing-cabal/testtools/issues/162#issuecomment-156891988
Django is setting the __cause__
attribute thus mimicking Python's 3 behaviour, but not ensuring that the associated exception has a usable __traceback__
attribute. The traceback2 module (backport of Python 3's traceback) relies on this... thus Django should also make sure that the exception has the expected attribute when it sets __cause__
.
This needs to be fixed at least in django/db/utils.py (DatabaseErrorWrapper.__exit__()
). But there are other cases where Django is setting __cause___
in django/db/migrations/loader.py,
django/utils/dictconfig.py and django/utils/timezone.py. It looks like they might have the same problem.
A fix for the first case might possibly be something like this (untested):
--- a/django/db/utils.py +++ b/django/db/utils.py @@ -91,6 +91,8 @@ class DatabaseErrorWrapper(object): if issubclass(exc_type, db_exc_type): dj_exc_value = dj_exc_type(*exc_value.args) dj_exc_value.__cause__ = exc_value + if not hasattr(exc_value, '__traceback__'): + setattr(exc_value, '__traceback__', traceback) # Only set the 'errors_occurred' flag for errors that may make # the connection unusable. if dj_exc_type not in (DataError, IntegrityError):
Change History (6)
comment:1 by , 9 years ago
Severity: | Release blocker → Normal |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 9 years ago
Here's a pull request fixing this ticket: https://github.com/django/django/pull/5721
The test suite passes but I have not tested yet if it really fixes the issue originally reported to Debian. Also master no longer has django/utils/dictconfig.py and you might want to fix that occurrence as well when you backport the fix to 1.8.x / 1.9.x.
comment:3 by , 9 years ago
Has patch: | set |
---|
comment:4 by , 9 years ago
The bug fix doesn't seem to qualify for a backport since the issue has been around as long as Django has supported Python 3 and testtools should be able to prevent the crash.
There is also some documentation to be updated. See the patch from #17601.