Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/sqlalchemy/exc.py : 49%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# sqlalchemy/exc.py
2# Copyright (C) 2005-2020 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: http://www.opensource.org/licenses/mit-license.php
8"""Exceptions used with SQLAlchemy.
10The base exception class is :exc:`.SQLAlchemyError`. Exceptions which are
11raised as a result of DBAPI exceptions are all subclasses of
12:exc:`.DBAPIError`.
14"""
16from .util import compat
18_version_token = None
21class SQLAlchemyError(Exception):
22 """Generic error class."""
24 code = None
26 def __init__(self, *arg, **kw):
27 code = kw.pop("code", None)
28 if code is not None:
29 self.code = code
30 super(SQLAlchemyError, self).__init__(*arg, **kw)
32 def _code_str(self):
33 if not self.code:
34 return ""
35 else:
36 return (
37 "(Background on this error at: "
38 "http://sqlalche.me/e/%s/%s)" % (_version_token, self.code,)
39 )
41 def _message(self, as_unicode=compat.py3k):
42 # rules:
43 #
44 # 1. under py2k, for __str__ return single string arg as it was
45 # given without converting to unicode. for __unicode__
46 # do a conversion but check that it's not unicode already just in
47 # case
48 #
49 # 2. under py3k, single arg string will usually be a unicode
50 # object, but since __str__() must return unicode, check for
51 # bytestring just in case
52 #
53 # 3. for multiple self.args, this is not a case in current
54 # SQLAlchemy though this is happening in at least one known external
55 # library, call str() which does a repr().
56 #
57 if len(self.args) == 1:
58 text = self.args[0]
59 if as_unicode and isinstance(text, compat.binary_types):
60 return compat.decode_backslashreplace(text, "utf-8")
61 else:
62 return self.args[0]
63 else:
64 # this is not a normal case within SQLAlchemy but is here for
65 # compatibility with Exception.args - the str() comes out as
66 # a repr() of the tuple
67 return str(self.args)
69 def _sql_message(self, as_unicode):
70 message = self._message(as_unicode)
72 if self.code:
73 message = "%s %s" % (message, self._code_str())
75 return message
77 def __str__(self):
78 return self._sql_message(compat.py3k)
80 def __unicode__(self):
81 return self._sql_message(as_unicode=True)
84class ArgumentError(SQLAlchemyError):
85 """Raised when an invalid or conflicting function argument is supplied.
87 This error generally corresponds to construction time state errors.
89 """
92class ObjectNotExecutableError(ArgumentError):
93 """Raised when an object is passed to .execute() that can't be
94 executed as SQL.
96 .. versionadded:: 1.1
98 """
100 def __init__(self, target):
101 super(ObjectNotExecutableError, self).__init__(
102 "Not an executable object: %r" % target
103 )
106class NoSuchModuleError(ArgumentError):
107 """Raised when a dynamically-loaded module (usually a database dialect)
108 of a particular name cannot be located."""
111class NoForeignKeysError(ArgumentError):
112 """Raised when no foreign keys can be located between two selectables
113 during a join."""
116class AmbiguousForeignKeysError(ArgumentError):
117 """Raised when more than one foreign key matching can be located
118 between two selectables during a join."""
121class CircularDependencyError(SQLAlchemyError):
122 """Raised by topological sorts when a circular dependency is detected.
124 There are two scenarios where this error occurs:
126 * In a Session flush operation, if two objects are mutually dependent
127 on each other, they can not be inserted or deleted via INSERT or
128 DELETE statements alone; an UPDATE will be needed to post-associate
129 or pre-deassociate one of the foreign key constrained values.
130 The ``post_update`` flag described at :ref:`post_update` can resolve
131 this cycle.
132 * In a :attr:`_schema.MetaData.sorted_tables` operation, two
133 :class:`_schema.ForeignKey`
134 or :class:`_schema.ForeignKeyConstraint` objects mutually refer to each
135 other. Apply the ``use_alter=True`` flag to one or both,
136 see :ref:`use_alter`.
138 """
140 def __init__(self, message, cycles, edges, msg=None, code=None):
141 if msg is None:
142 message += " (%s)" % ", ".join(repr(s) for s in cycles)
143 else:
144 message = msg
145 SQLAlchemyError.__init__(self, message, code=code)
146 self.cycles = cycles
147 self.edges = edges
149 def __reduce__(self):
150 return self.__class__, (None, self.cycles, self.edges, self.args[0])
153class CompileError(SQLAlchemyError):
154 """Raised when an error occurs during SQL compilation"""
157class UnsupportedCompilationError(CompileError):
158 """Raised when an operation is not supported by the given compiler.
160 .. seealso::
162 :ref:`faq_sql_expression_string`
164 :ref:`error_l7de`
165 """
167 code = "l7de"
169 def __init__(self, compiler, element_type):
170 super(UnsupportedCompilationError, self).__init__(
171 "Compiler %r can't render element of type %s"
172 % (compiler, element_type)
173 )
176class IdentifierError(SQLAlchemyError):
177 """Raised when a schema name is beyond the max character limit"""
180class DisconnectionError(SQLAlchemyError):
181 """A disconnect is detected on a raw DB-API connection.
183 This error is raised and consumed internally by a connection pool. It can
184 be raised by the :meth:`_events.PoolEvents.checkout`
185 event so that the host pool
186 forces a retry; the exception will be caught three times in a row before
187 the pool gives up and raises :class:`~sqlalchemy.exc.InvalidRequestError`
188 regarding the connection attempt.
190 """
192 invalidate_pool = False
195class InvalidatePoolError(DisconnectionError):
196 """Raised when the connection pool should invalidate all stale connections.
198 A subclass of :class:`_exc.DisconnectionError` that indicates that the
199 disconnect situation encountered on the connection probably means the
200 entire pool should be invalidated, as the database has been restarted.
202 This exception will be handled otherwise the same way as
203 :class:`_exc.DisconnectionError`, allowing three attempts to reconnect
204 before giving up.
206 .. versionadded:: 1.2
208 """
210 invalidate_pool = True
213class TimeoutError(SQLAlchemyError): # noqa
214 """Raised when a connection pool times out on getting a connection."""
217class InvalidRequestError(SQLAlchemyError):
218 """SQLAlchemy was asked to do something it can't do.
220 This error generally corresponds to runtime state errors.
222 """
225class NoInspectionAvailable(InvalidRequestError):
226 """A subject passed to :func:`sqlalchemy.inspection.inspect` produced
227 no context for inspection."""
230class ResourceClosedError(InvalidRequestError):
231 """An operation was requested from a connection, cursor, or other
232 object that's in a closed state."""
235class NoSuchColumnError(KeyError, InvalidRequestError):
236 """A nonexistent column is requested from a ``RowProxy``."""
239class NoReferenceError(InvalidRequestError):
240 """Raised by ``ForeignKey`` to indicate a reference cannot be resolved."""
243class NoReferencedTableError(NoReferenceError):
244 """Raised by ``ForeignKey`` when the referred ``Table`` cannot be
245 located.
247 """
249 def __init__(self, message, tname):
250 NoReferenceError.__init__(self, message)
251 self.table_name = tname
253 def __reduce__(self):
254 return self.__class__, (self.args[0], self.table_name)
257class NoReferencedColumnError(NoReferenceError):
258 """Raised by ``ForeignKey`` when the referred ``Column`` cannot be
259 located.
261 """
263 def __init__(self, message, tname, cname):
264 NoReferenceError.__init__(self, message)
265 self.table_name = tname
266 self.column_name = cname
268 def __reduce__(self):
269 return (
270 self.__class__,
271 (self.args[0], self.table_name, self.column_name),
272 )
275class NoSuchTableError(InvalidRequestError):
276 """Table does not exist or is not visible to a connection."""
279class UnreflectableTableError(InvalidRequestError):
280 """Table exists but can't be reflected for some reason.
282 .. versionadded:: 1.2
284 """
287class UnboundExecutionError(InvalidRequestError):
288 """SQL was attempted without a database connection to execute it on."""
291class DontWrapMixin(object):
292 """A mixin class which, when applied to a user-defined Exception class,
293 will not be wrapped inside of :exc:`.StatementError` if the error is
294 emitted within the process of executing a statement.
296 E.g.::
298 from sqlalchemy.exc import DontWrapMixin
300 class MyCustomException(Exception, DontWrapMixin):
301 pass
303 class MySpecialType(TypeDecorator):
304 impl = String
306 def process_bind_param(self, value, dialect):
307 if value == 'invalid':
308 raise MyCustomException("invalid!")
310 """
313# Moved to orm.exc; compatibility definition installed by orm import until 0.6
314UnmappedColumnError = None
317class StatementError(SQLAlchemyError):
318 """An error occurred during execution of a SQL statement.
320 :class:`StatementError` wraps the exception raised
321 during execution, and features :attr:`.statement`
322 and :attr:`.params` attributes which supply context regarding
323 the specifics of the statement which had an issue.
325 The wrapped exception object is available in
326 the :attr:`.orig` attribute.
328 """
330 statement = None
331 """The string SQL statement being invoked when this exception occurred."""
333 params = None
334 """The parameter list being used when this exception occurred."""
336 orig = None
337 """The DBAPI exception object."""
339 ismulti = None
341 def __init__(
342 self,
343 message,
344 statement,
345 params,
346 orig,
347 hide_parameters=False,
348 code=None,
349 ismulti=None,
350 ):
351 SQLAlchemyError.__init__(self, message, code=code)
352 self.statement = statement
353 self.params = params
354 self.orig = orig
355 self.ismulti = ismulti
356 self.hide_parameters = hide_parameters
357 self.detail = []
359 def add_detail(self, msg):
360 self.detail.append(msg)
362 def __reduce__(self):
363 return (
364 self.__class__,
365 (
366 self.args[0],
367 self.statement,
368 self.params,
369 self.orig,
370 self.hide_parameters,
371 self.ismulti,
372 ),
373 )
375 def _sql_message(self, as_unicode):
376 from sqlalchemy.sql import util
378 details = [self._message(as_unicode=as_unicode)]
379 if self.statement:
380 if not as_unicode and not compat.py3k:
381 stmt_detail = "[SQL: %s]" % compat.safe_bytestring(
382 self.statement
383 )
384 else:
385 stmt_detail = "[SQL: %s]" % self.statement
386 details.append(stmt_detail)
387 if self.params:
388 if self.hide_parameters:
389 details.append(
390 "[SQL parameters hidden due to hide_parameters=True]"
391 )
392 else:
393 params_repr = util._repr_params(
394 self.params, 10, ismulti=self.ismulti
395 )
396 details.append("[parameters: %r]" % params_repr)
397 code_str = self._code_str()
398 if code_str:
399 details.append(code_str)
400 return "\n".join(["(%s)" % det for det in self.detail] + details)
403class DBAPIError(StatementError):
404 """Raised when the execution of a database operation fails.
406 Wraps exceptions raised by the DB-API underlying the
407 database operation. Driver-specific implementations of the standard
408 DB-API exception types are wrapped by matching sub-types of SQLAlchemy's
409 :class:`DBAPIError` when possible. DB-API's ``Error`` type maps to
410 :class:`DBAPIError` in SQLAlchemy, otherwise the names are identical. Note
411 that there is no guarantee that different DB-API implementations will
412 raise the same exception type for any given error condition.
414 :class:`DBAPIError` features :attr:`~.StatementError.statement`
415 and :attr:`~.StatementError.params` attributes which supply context
416 regarding the specifics of the statement which had an issue, for the
417 typical case when the error was raised within the context of
418 emitting a SQL statement.
420 The wrapped exception object is available in the
421 :attr:`~.StatementError.orig` attribute. Its type and properties are
422 DB-API implementation specific.
424 """
426 code = "dbapi"
428 @classmethod
429 def instance(
430 cls,
431 statement,
432 params,
433 orig,
434 dbapi_base_err,
435 hide_parameters=False,
436 connection_invalidated=False,
437 dialect=None,
438 ismulti=None,
439 ):
440 # Don't ever wrap these, just return them directly as if
441 # DBAPIError didn't exist.
442 if (
443 isinstance(orig, BaseException) and not isinstance(orig, Exception)
444 ) or isinstance(orig, DontWrapMixin):
445 return orig
447 if orig is not None:
448 # not a DBAPI error, statement is present.
449 # raise a StatementError
450 if isinstance(orig, SQLAlchemyError) and statement:
451 return StatementError(
452 "(%s.%s) %s"
453 % (
454 orig.__class__.__module__,
455 orig.__class__.__name__,
456 orig.args[0],
457 ),
458 statement,
459 params,
460 orig,
461 hide_parameters=hide_parameters,
462 code=orig.code,
463 ismulti=ismulti,
464 )
465 elif not isinstance(orig, dbapi_base_err) and statement:
466 return StatementError(
467 "(%s.%s) %s"
468 % (
469 orig.__class__.__module__,
470 orig.__class__.__name__,
471 orig,
472 ),
473 statement,
474 params,
475 orig,
476 hide_parameters=hide_parameters,
477 ismulti=ismulti,
478 )
480 glob = globals()
481 for super_ in orig.__class__.__mro__:
482 name = super_.__name__
483 if dialect:
484 name = dialect.dbapi_exception_translation_map.get(
485 name, name
486 )
487 if name in glob and issubclass(glob[name], DBAPIError):
488 cls = glob[name]
489 break
491 return cls(
492 statement,
493 params,
494 orig,
495 connection_invalidated=connection_invalidated,
496 hide_parameters=hide_parameters,
497 code=cls.code,
498 ismulti=ismulti,
499 )
501 def __reduce__(self):
502 return (
503 self.__class__,
504 (
505 self.statement,
506 self.params,
507 self.orig,
508 self.hide_parameters,
509 self.connection_invalidated,
510 self.ismulti,
511 ),
512 )
514 def __init__(
515 self,
516 statement,
517 params,
518 orig,
519 hide_parameters=False,
520 connection_invalidated=False,
521 code=None,
522 ismulti=None,
523 ):
524 try:
525 text = str(orig)
526 except Exception as e:
527 text = "Error in str() of DB-API-generated exception: " + str(e)
528 StatementError.__init__(
529 self,
530 "(%s.%s) %s"
531 % (orig.__class__.__module__, orig.__class__.__name__, text),
532 statement,
533 params,
534 orig,
535 hide_parameters,
536 code=code,
537 ismulti=ismulti,
538 )
539 self.connection_invalidated = connection_invalidated
542class InterfaceError(DBAPIError):
543 """Wraps a DB-API InterfaceError."""
545 code = "rvf5"
548class DatabaseError(DBAPIError):
549 """Wraps a DB-API DatabaseError."""
551 code = "4xp6"
554class DataError(DatabaseError):
555 """Wraps a DB-API DataError."""
557 code = "9h9h"
560class OperationalError(DatabaseError):
561 """Wraps a DB-API OperationalError."""
563 code = "e3q8"
566class IntegrityError(DatabaseError):
567 """Wraps a DB-API IntegrityError."""
569 code = "gkpj"
572class InternalError(DatabaseError):
573 """Wraps a DB-API InternalError."""
575 code = "2j85"
578class ProgrammingError(DatabaseError):
579 """Wraps a DB-API ProgrammingError."""
581 code = "f405"
584class NotSupportedError(DatabaseError):
585 """Wraps a DB-API NotSupportedError."""
587 code = "tw8g"
590# Warnings
593class SADeprecationWarning(DeprecationWarning):
594 """Issued once per usage of a deprecated API."""
597class SAPendingDeprecationWarning(PendingDeprecationWarning):
598 """Issued once per usage of a deprecated API."""
601class SAWarning(RuntimeWarning):
602 """Issued at runtime."""