summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/sql')
-rw-r--r--lib/sqlalchemy/sql/base.py25
-rw-r--r--lib/sqlalchemy/sql/coercions.py39
-rw-r--r--lib/sqlalchemy/sql/compiler.py15
-rw-r--r--lib/sqlalchemy/sql/ddl.py5
-rw-r--r--lib/sqlalchemy/sql/elements.py66
-rw-r--r--lib/sqlalchemy/sql/schema.py25
-rw-r--r--lib/sqlalchemy/sql/selectable.py22
-rw-r--r--lib/sqlalchemy/sql/sqltypes.py18
-rw-r--r--lib/sqlalchemy/sql/type_api.py44
-rw-r--r--lib/sqlalchemy/sql/visitors.py7
10 files changed, 168 insertions, 98 deletions
diff --git a/lib/sqlalchemy/sql/base.py b/lib/sqlalchemy/sql/base.py
index a7324c45f..2d336360f 100644
--- a/lib/sqlalchemy/sql/base.py
+++ b/lib/sqlalchemy/sql/base.py
@@ -128,8 +128,8 @@ class _DialectArgView(util.collections_abc.MutableMapping):
def _key(self, key):
try:
dialect, value_key = key.split("_", 1)
- except ValueError:
- raise KeyError(key)
+ except ValueError as err:
+ util.raise_(KeyError(key), replace_context=err)
else:
return dialect, value_key
@@ -138,17 +138,20 @@ class _DialectArgView(util.collections_abc.MutableMapping):
try:
opt = self.obj.dialect_options[dialect]
- except exc.NoSuchModuleError:
- raise KeyError(key)
+ except exc.NoSuchModuleError as err:
+ util.raise_(KeyError(key), replace_context=err)
else:
return opt[value_key]
def __setitem__(self, key, value):
try:
dialect, value_key = self._key(key)
- except KeyError:
- raise exc.ArgumentError(
- "Keys must be of the form <dialectname>_<argname>"
+ except KeyError as err:
+ util.raise_(
+ exc.ArgumentError(
+ "Keys must be of the form <dialectname>_<argname>"
+ ),
+ replace_context=err,
)
else:
self.obj.dialect_options[dialect][value_key] = value
@@ -634,17 +637,17 @@ class ColumnCollection(object):
def __getitem__(self, key):
try:
return self._index[key]
- except KeyError:
+ except KeyError as err:
if isinstance(key, util.int_types):
- raise IndexError(key)
+ util.raise_(IndexError(key), replace_context=err)
else:
raise
def __getattr__(self, key):
try:
return self._index[key]
- except KeyError:
- raise AttributeError(key)
+ except KeyError as err:
+ util.raise_(AttributeError(key), replace_context=err)
def __contains__(self, key):
if key not in self._index:
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 (
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index 9c1f50ce1..d31cf67f8 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -1074,7 +1074,7 @@ class SQLCompiler(Compiled):
col = only_froms[element.element]
else:
col = with_cols[element.element]
- except KeyError:
+ except KeyError as err:
coercions._no_text_coercion(
element.element,
extra=(
@@ -1082,6 +1082,7 @@ class SQLCompiler(Compiled):
"GROUP BY / DISTINCT etc."
),
exc_cls=exc.CompileError,
+ err=err,
)
else:
kwargs["render_label_as_label"] = col
@@ -1671,8 +1672,11 @@ class SQLCompiler(Compiled):
else:
try:
opstring = OPERATORS[operator_]
- except KeyError:
- raise exc.UnsupportedCompilationError(self, operator_)
+ except KeyError as err:
+ util.raise_(
+ exc.UnsupportedCompilationError(self, operator_),
+ replace_context=err,
+ )
else:
return self._generate_generic_binary(
binary, opstring, from_linter=from_linter, **kw
@@ -3286,11 +3290,12 @@ class DDLCompiler(Compiled):
if column.primary_key:
first_pk = True
except exc.CompileError as ce:
- util.raise_from_cause(
+ util.raise_(
exc.CompileError(
util.u("(in table '%s', column '%s'): %s")
% (table.description, column.name, ce.args[0])
- )
+ ),
+ from_=ce,
)
const = self.create_table_constraints(
diff --git a/lib/sqlalchemy/sql/ddl.py b/lib/sqlalchemy/sql/ddl.py
index 31bcc34a4..5a2095604 100644
--- a/lib/sqlalchemy/sql/ddl.py
+++ b/lib/sqlalchemy/sql/ddl.py
@@ -801,7 +801,7 @@ class SchemaDropper(DDLBase):
)
collection = [(t, ()) for t in unsorted_tables]
else:
- util.raise_from_cause(
+ util.raise_(
exc.CircularDependencyError(
err2.args[0],
err2.cycles,
@@ -818,7 +818,8 @@ class SchemaDropper(DDLBase):
sorted([t.fullname for t in err2.cycles])
)
),
- )
+ ),
+ from_=err2,
)
seq_coll = [
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py
index df690c383..d0babb1be 100644
--- a/lib/sqlalchemy/sql/elements.py
+++ b/lib/sqlalchemy/sql/elements.py
@@ -747,10 +747,13 @@ class ColumnElement(
def comparator(self):
try:
comparator_factory = self.type.comparator_factory
- except AttributeError:
- raise TypeError(
- "Object %r associated with '.type' attribute "
- "is not a TypeEngine class or object" % self.type
+ except AttributeError as err:
+ util.raise_(
+ TypeError(
+ "Object %r associated with '.type' attribute "
+ "is not a TypeEngine class or object" % self.type
+ ),
+ replace_context=err,
)
else:
return comparator_factory(self)
@@ -758,10 +761,17 @@ class ColumnElement(
def __getattr__(self, key):
try:
return getattr(self.comparator, key)
- except AttributeError:
- raise AttributeError(
- "Neither %r object nor %r object has an attribute %r"
- % (type(self).__name__, type(self.comparator).__name__, key)
+ except AttributeError as err:
+ util.raise_(
+ AttributeError(
+ "Neither %r object nor %r object has an attribute %r"
+ % (
+ type(self).__name__,
+ type(self.comparator).__name__,
+ key,
+ )
+ ),
+ replace_context=err,
)
def operate(self, op, *other, **kwargs):
@@ -1742,10 +1752,13 @@ class TextClause(
# a unique/anonymous key in any case, so use the _orig_key
# so that a text() construct can support unique parameters
existing = new_params[bind._orig_key]
- except KeyError:
- raise exc.ArgumentError(
- "This text() construct doesn't define a "
- "bound parameter named %r" % bind._orig_key
+ except KeyError as err:
+ util.raise_(
+ exc.ArgumentError(
+ "This text() construct doesn't define a "
+ "bound parameter named %r" % bind._orig_key
+ ),
+ replace_context=err,
)
else:
new_params[existing._orig_key] = bind
@@ -1753,10 +1766,13 @@ class TextClause(
for key, value in names_to_values.items():
try:
existing = new_params[key]
- except KeyError:
- raise exc.ArgumentError(
- "This text() construct doesn't define a "
- "bound parameter named %r" % key
+ except KeyError as err:
+ util.raise_(
+ exc.ArgumentError(
+ "This text() construct doesn't define a "
+ "bound parameter named %r" % key
+ ),
+ replace_context=err,
)
else:
new_params[key] = existing._with_value(value)
@@ -3665,9 +3681,12 @@ class Over(ColumnElement):
else:
try:
lower = int(range_[0])
- except ValueError:
- raise exc.ArgumentError(
- "Integer or None expected for range value"
+ except ValueError as err:
+ util.raise_(
+ exc.ArgumentError(
+ "Integer or None expected for range value"
+ ),
+ replace_context=err,
)
else:
if lower == 0:
@@ -3678,9 +3697,12 @@ class Over(ColumnElement):
else:
try:
upper = int(range_[1])
- except ValueError:
- raise exc.ArgumentError(
- "Integer or None expected for range value"
+ except ValueError as err:
+ util.raise_(
+ exc.ArgumentError(
+ "Integer or None expected for range value"
+ ),
+ replace_context=err,
)
else:
if upper == 0:
diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py
index e6d3a6b05..5445a1bce 100644
--- a/lib/sqlalchemy/sql/schema.py
+++ b/lib/sqlalchemy/sql/schema.py
@@ -107,12 +107,13 @@ class SchemaItem(SchemaEventTarget, visitors.Visitable):
if item is not None:
try:
spwd = item._set_parent_with_dispatch
- except AttributeError:
- util.raise_from_cause(
+ except AttributeError as err:
+ util.raise_(
exc.ArgumentError(
"'SchemaItem' object, such as a 'Column' or a "
"'Constraint' expected, got %r" % item
- )
+ ),
+ replace_context=err,
)
else:
spwd(self)
@@ -1569,15 +1570,16 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause):
_proxies=[self],
*fk
)
- except TypeError:
- util.raise_from_cause(
+ except TypeError as err:
+ util.raise_(
TypeError(
"Could not create a copy of this %r object. "
"Ensure the class includes a _constructor() "
"attribute or method which accepts the "
"standard Column constructor arguments, or "
"references the Column class itself." % self.__class__
- )
+ ),
+ from_=err,
)
c.table = selectable
@@ -3187,10 +3189,13 @@ class ForeignKeyConstraint(ColumnCollectionConstraint):
try:
ColumnCollectionConstraint._set_parent(self, table)
except KeyError as ke:
- raise exc.ArgumentError(
- "Can't create ForeignKeyConstraint "
- "on table '%s': no column "
- "named '%s' is present." % (table.description, ke.args[0])
+ util.raise_(
+ exc.ArgumentError(
+ "Can't create ForeignKeyConstraint "
+ "on table '%s': no column "
+ "named '%s' is present." % (table.description, ke.args[0])
+ ),
+ from_=ke,
)
for col, fk in zip(self.columns, self.elements):
diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py
index b8d88e160..b972c13be 100644
--- a/lib/sqlalchemy/sql/selectable.py
+++ b/lib/sqlalchemy/sql/selectable.py
@@ -2620,10 +2620,13 @@ class GenerativeSelect(DeprecatedSelectBaseGenerations, SelectBase):
return None
try:
value = clause._limit_offset_value
- except AttributeError:
- raise exc.CompileError(
- "This SELECT structure does not use a simple "
- "integer value for %s" % attrname
+ except AttributeError as err:
+ util.raise_(
+ exc.CompileError(
+ "This SELECT structure does not use a simple "
+ "integer value for %s" % attrname
+ ),
+ replace_context=err,
)
else:
return util.asint(value)
@@ -3489,10 +3492,13 @@ class Select(
try:
cols_present = bool(columns)
- except TypeError:
- raise exc.ArgumentError(
- "columns argument to select() must "
- "be a Python list or other iterable"
+ except TypeError as err:
+ util.raise_(
+ exc.ArgumentError(
+ "columns argument to select() must "
+ "be a Python list or other iterable"
+ ),
+ from_=err,
)
if cols_present:
diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py
index 22c80cc91..e4a029a3e 100644
--- a/lib/sqlalchemy/sql/sqltypes.py
+++ b/lib/sqlalchemy/sql/sqltypes.py
@@ -1462,7 +1462,7 @@ class Enum(Emulated, String, SchemaType):
def _db_value_for_elem(self, elem):
try:
return self._valid_lookup[elem]
- except KeyError:
+ except KeyError as err:
# for unknown string values, we return as is. While we can
# validate these if we wanted, that does not allow for lesser-used
# end-user use cases, such as using a LIKE comparison with an enum,
@@ -1476,8 +1476,11 @@ class Enum(Emulated, String, SchemaType):
):
return elem
else:
- raise LookupError(
- '"%s" is not among the defined enum values' % elem
+ util.raise_(
+ LookupError(
+ '"%s" is not among the defined enum values' % elem
+ ),
+ replace_context=err,
)
class Comparator(String.Comparator):
@@ -1496,9 +1499,12 @@ class Enum(Emulated, String, SchemaType):
def _object_value_for_elem(self, elem):
try:
return self._object_lookup[elem]
- except KeyError:
- raise LookupError(
- '"%s" is not among the defined enum values' % elem
+ except KeyError as err:
+ util.raise_(
+ LookupError(
+ '"%s" is not among the defined enum values' % elem
+ ),
+ replace_context=err,
)
def __repr__(self):
diff --git a/lib/sqlalchemy/sql/type_api.py b/lib/sqlalchemy/sql/type_api.py
index c6c860844..739f96195 100644
--- a/lib/sqlalchemy/sql/type_api.py
+++ b/lib/sqlalchemy/sql/type_api.py
@@ -479,9 +479,12 @@ class TypeEngine(Traversible):
try:
return dialect._type_memos[self]["literal"]
except KeyError:
- d = self._dialect_info(dialect)
- d["literal"] = lp = d["impl"].literal_processor(dialect)
- return lp
+ pass
+ # avoid KeyError context coming into literal_processor() function
+ # raises
+ d = self._dialect_info(dialect)
+ d["literal"] = lp = d["impl"].literal_processor(dialect)
+ return lp
def _cached_bind_processor(self, dialect):
"""Return a dialect-specific bind processor for this type."""
@@ -489,9 +492,12 @@ class TypeEngine(Traversible):
try:
return dialect._type_memos[self]["bind"]
except KeyError:
- d = self._dialect_info(dialect)
- d["bind"] = bp = d["impl"].bind_processor(dialect)
- return bp
+ pass
+ # avoid KeyError context coming into bind_processor() function
+ # raises
+ d = self._dialect_info(dialect)
+ d["bind"] = bp = d["impl"].bind_processor(dialect)
+ return bp
def _cached_result_processor(self, dialect, coltype):
"""Return a dialect-specific result processor for this type."""
@@ -499,21 +505,27 @@ class TypeEngine(Traversible):
try:
return dialect._type_memos[self][coltype]
except KeyError:
- d = self._dialect_info(dialect)
- # key assumption: DBAPI type codes are
- # constants. Else this dictionary would
- # grow unbounded.
- d[coltype] = rp = d["impl"].result_processor(dialect, coltype)
- return rp
+ pass
+ # avoid KeyError context coming into result_processor() function
+ # raises
+ d = self._dialect_info(dialect)
+ # key assumption: DBAPI type codes are
+ # constants. Else this dictionary would
+ # grow unbounded.
+ d[coltype] = rp = d["impl"].result_processor(dialect, coltype)
+ return rp
def _cached_custom_processor(self, dialect, key, fn):
try:
return dialect._type_memos[self][key]
except KeyError:
- d = self._dialect_info(dialect)
- impl = d["impl"]
- d[key] = result = fn(impl)
- return result
+ pass
+ # avoid KeyError context coming into fn() function
+ # raises
+ d = self._dialect_info(dialect)
+ impl = d["impl"]
+ d[key] = result = fn(impl)
+ return result
def _dialect_info(self, dialect):
"""Return a dialect-specific registry which
diff --git a/lib/sqlalchemy/sql/visitors.py b/lib/sqlalchemy/sql/visitors.py
index 77e6b53a8..fda48c657 100644
--- a/lib/sqlalchemy/sql/visitors.py
+++ b/lib/sqlalchemy/sql/visitors.py
@@ -62,9 +62,10 @@ def _generate_compiler_dispatch(cls):
"def _compiler_dispatch(self, visitor, **kw):\n"
" try:\n"
" meth = visitor.visit_%(name)s\n"
- " except AttributeError:\n"
- " util.raise_from_cause(\n"
- " exc.UnsupportedCompilationError(visitor, cls))\n"
+ " except AttributeError as err:\n"
+ " util.raise_(\n"
+ " exc.UnsupportedCompilationError(visitor, cls), \n"
+ " replace_context=err)\n"
" else:\n"
" return meth(self, **kw)\n"
) % {"name": visit_name}