diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-02-29 14:40:45 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-03-02 17:24:19 -0500 |
commit | 57dc36a01b2b334a996f73f6a78b3bfbe4d9f2ec (patch) | |
tree | 77cbb0199ca91be3b0816e3a5bd4c217e36a7d1b /lib/sqlalchemy/sql/coercions.py | |
parent | 649de79950dcf952d7a44069faf36925c23c4e63 (diff) | |
download | sqlalchemy-57dc36a01b2b334a996f73f6a78b3bfbe4d9f2ec.tar.gz |
Ensure all nested exception throws have a cause
Applied an explicit "cause" to most if not all internally raised exceptions
that are raised from within an internal exception catch, to avoid
misleading stacktraces that suggest an error within the handling of an
exception. While it would be preferable to suppress the internally caught
exception in the way that the ``__suppress_context__`` attribute would,
there does not as yet seem to be a way to do this without suppressing an
enclosing user constructed context, so for now it exposes the internally
caught exception as the cause so that full information about the context
of the error is maintained.
Fixes: #4849
Change-Id: I55a86b29023675d9e5e49bc7edc5a2dc0bcd4751
Diffstat (limited to 'lib/sqlalchemy/sql/coercions.py')
-rw-r--r-- | lib/sqlalchemy/sql/coercions.py | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/lib/sqlalchemy/sql/coercions.py b/lib/sqlalchemy/sql/coercions.py index b3bf4e93b..fc841bb4b 100644 --- a/lib/sqlalchemy/sql/coercions.py +++ b/lib/sqlalchemy/sql/coercions.py @@ -133,7 +133,13 @@ class RoleImpl(object): self._raise_for_expected(element, argname, resolved) def _raise_for_expected( - self, element, argname=None, resolved=None, advice=None, code=None + self, + element, + argname=None, + resolved=None, + advice=None, + code=None, + err=None, ): if argname: msg = "%s expected for argument %r; got %r." % ( @@ -147,7 +153,7 @@ class RoleImpl(object): if advice: msg += " " + advice - raise exc.ArgumentError(msg, code=code) + util.raise_(exc.ArgumentError(msg, code=code), replace_context=err) class _Deannotate(object): @@ -201,16 +207,19 @@ class _ColumnCoercions(object): def _no_text_coercion( - element, argname=None, exc_cls=exc.ArgumentError, extra=None + element, argname=None, exc_cls=exc.ArgumentError, extra=None, err=None ): - raise exc_cls( - "%(extra)sTextual SQL expression %(expr)r %(argname)sshould be " - "explicitly declared as text(%(expr)r)" - % { - "expr": util.ellipses_string(element), - "argname": "for argument %s" % (argname,) if argname else "", - "extra": "%s " % extra if extra else "", - } + util.raise_( + exc_cls( + "%(extra)sTextual SQL expression %(expr)r %(argname)sshould be " + "explicitly declared as text(%(expr)r)" + % { + "expr": util.ellipses_string(element), + "argname": "for argument %s" % (argname,) if argname else "", + "extra": "%s " % extra if extra else "", + } + ), + replace_context=err, ) @@ -290,8 +299,8 @@ class ExpressionElementImpl( return elements.BindParameter( name, element, type_, unique=True ) - except exc.ArgumentError: - self._raise_for_expected(element) + except exc.ArgumentError as err: + self._raise_for_expected(element, err=err) class BinaryElementImpl( @@ -302,8 +311,8 @@ class BinaryElementImpl( ): try: return expr._bind_param(operator, element, type_=bindparam_type) - except exc.ArgumentError: - self._raise_for_expected(element) + except exc.ArgumentError as err: + self._raise_for_expected(element, err=err) def _post_coercion(self, resolved, expr, **kw): if ( |