Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/sqlalchemy/exc.py: 54%
199 statements
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
1# sqlalchemy/exc.py
2# Copyright (C) 2005-2022 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: https://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 _preloaded
17from .util import compat
19_version_token = None
22class HasDescriptionCode(object):
23 """helper which adds 'code' as an attribute and '_code_str' as a method"""
25 code = None
27 def __init__(self, *arg, **kw):
28 code = kw.pop("code", None)
29 if code is not None:
30 self.code = code
31 super(HasDescriptionCode, self).__init__(*arg, **kw)
33 def _code_str(self):
34 if not self.code:
35 return ""
36 else:
37 return (
38 "(Background on this error at: "
39 "https://sqlalche.me/e/%s/%s)"
40 % (
41 _version_token,
42 self.code,
43 )
44 )
46 def __str__(self):
47 message = super(HasDescriptionCode, self).__str__()
48 if self.code:
49 message = "%s %s" % (message, self._code_str())
50 return message
53class SQLAlchemyError(HasDescriptionCode, Exception):
54 """Generic error class."""
56 def _message(self, as_unicode=compat.py3k):
57 # rules:
58 #
59 # 1. under py2k, for __str__ return single string arg as it was
60 # given without converting to unicode. for __unicode__
61 # do a conversion but check that it's not unicode already just in
62 # case
63 #
64 # 2. under py3k, single arg string will usually be a unicode
65 # object, but since __str__() must return unicode, check for
66 # bytestring just in case
67 #
68 # 3. for multiple self.args, this is not a case in current
69 # SQLAlchemy though this is happening in at least one known external
70 # library, call str() which does a repr().
71 #
72 if len(self.args) == 1:
73 text = self.args[0]
75 if as_unicode and isinstance(text, compat.binary_types):
76 text = compat.decode_backslashreplace(text, "utf-8")
77 # This is for when the argument is not a string of any sort.
78 # Otherwise, converting this exception to string would fail for
79 # non-string arguments.
80 elif compat.py3k or not as_unicode:
81 text = str(text)
82 else:
83 text = compat.text_type(text)
85 return text
86 else:
87 # this is not a normal case within SQLAlchemy but is here for
88 # compatibility with Exception.args - the str() comes out as
89 # a repr() of the tuple
90 return str(self.args)
92 def _sql_message(self, as_unicode):
93 message = self._message(as_unicode)
95 if self.code:
96 message = "%s %s" % (message, self._code_str())
98 return message
100 def __str__(self):
101 return self._sql_message(compat.py3k)
103 def __unicode__(self):
104 return self._sql_message(as_unicode=True)
107class ArgumentError(SQLAlchemyError):
108 """Raised when an invalid or conflicting function argument is supplied.
110 This error generally corresponds to construction time state errors.
112 """
115class ObjectNotExecutableError(ArgumentError):
116 """Raised when an object is passed to .execute() that can't be
117 executed as SQL.
119 .. versionadded:: 1.1
121 """
123 def __init__(self, target):
124 super(ObjectNotExecutableError, self).__init__(
125 "Not an executable object: %r" % target
126 )
127 self.target = target
129 def __reduce__(self):
130 return self.__class__, (self.target,)
133class NoSuchModuleError(ArgumentError):
134 """Raised when a dynamically-loaded module (usually a database dialect)
135 of a particular name cannot be located."""
138class NoForeignKeysError(ArgumentError):
139 """Raised when no foreign keys can be located between two selectables
140 during a join."""
143class AmbiguousForeignKeysError(ArgumentError):
144 """Raised when more than one foreign key matching can be located
145 between two selectables during a join."""
148class CircularDependencyError(SQLAlchemyError):
149 """Raised by topological sorts when a circular dependency is detected.
151 There are two scenarios where this error occurs:
153 * In a Session flush operation, if two objects are mutually dependent
154 on each other, they can not be inserted or deleted via INSERT or
155 DELETE statements alone; an UPDATE will be needed to post-associate
156 or pre-deassociate one of the foreign key constrained values.
157 The ``post_update`` flag described at :ref:`post_update` can resolve
158 this cycle.
159 * In a :attr:`_schema.MetaData.sorted_tables` operation, two
160 :class:`_schema.ForeignKey`
161 or :class:`_schema.ForeignKeyConstraint` objects mutually refer to each
162 other. Apply the ``use_alter=True`` flag to one or both,
163 see :ref:`use_alter`.
165 """
167 def __init__(self, message, cycles, edges, msg=None, code=None):
168 if msg is None:
169 message += " (%s)" % ", ".join(repr(s) for s in cycles)
170 else:
171 message = msg
172 SQLAlchemyError.__init__(self, message, code=code)
173 self.cycles = cycles
174 self.edges = edges
176 def __reduce__(self):
177 return (
178 self.__class__,
179 (None, self.cycles, self.edges, self.args[0]),
180 {"code": self.code} if self.code is not None else {},
181 )
184class CompileError(SQLAlchemyError):
185 """Raised when an error occurs during SQL compilation"""
188class UnsupportedCompilationError(CompileError):
189 """Raised when an operation is not supported by the given compiler.
191 .. seealso::
193 :ref:`faq_sql_expression_string`
195 :ref:`error_l7de`
196 """
198 code = "l7de"
200 def __init__(self, compiler, element_type, message=None):
201 super(UnsupportedCompilationError, self).__init__(
202 "Compiler %r can't render element of type %s%s"
203 % (compiler, element_type, ": %s" % message if message else "")
204 )
205 self.compiler = compiler
206 self.element_type = element_type
207 self.message = message
209 def __reduce__(self):
210 return self.__class__, (self.compiler, self.element_type, self.message)
213class IdentifierError(SQLAlchemyError):
214 """Raised when a schema name is beyond the max character limit"""
217class DisconnectionError(SQLAlchemyError):
218 """A disconnect is detected on a raw DB-API connection.
220 This error is raised and consumed internally by a connection pool. It can
221 be raised by the :meth:`_events.PoolEvents.checkout`
222 event so that the host pool
223 forces a retry; the exception will be caught three times in a row before
224 the pool gives up and raises :class:`~sqlalchemy.exc.InvalidRequestError`
225 regarding the connection attempt.
227 """
229 invalidate_pool = False
232class InvalidatePoolError(DisconnectionError):
233 """Raised when the connection pool should invalidate all stale connections.
235 A subclass of :class:`_exc.DisconnectionError` that indicates that the
236 disconnect situation encountered on the connection probably means the
237 entire pool should be invalidated, as the database has been restarted.
239 This exception will be handled otherwise the same way as
240 :class:`_exc.DisconnectionError`, allowing three attempts to reconnect
241 before giving up.
243 .. versionadded:: 1.2
245 """
247 invalidate_pool = True
250class TimeoutError(SQLAlchemyError): # noqa
251 """Raised when a connection pool times out on getting a connection."""
254class InvalidRequestError(SQLAlchemyError):
255 """SQLAlchemy was asked to do something it can't do.
257 This error generally corresponds to runtime state errors.
259 """
262class NoInspectionAvailable(InvalidRequestError):
263 """A subject passed to :func:`sqlalchemy.inspection.inspect` produced
264 no context for inspection."""
267class PendingRollbackError(InvalidRequestError):
268 """A transaction has failed and needs to be rolled back before
269 continuing.
271 .. versionadded:: 1.4
273 """
276class ResourceClosedError(InvalidRequestError):
277 """An operation was requested from a connection, cursor, or other
278 object that's in a closed state."""
281class NoSuchColumnError(InvalidRequestError, KeyError):
282 """A nonexistent column is requested from a ``Row``."""
285class NoResultFound(InvalidRequestError):
286 """A database result was required but none was found.
289 .. versionchanged:: 1.4 This exception is now part of the
290 ``sqlalchemy.exc`` module in Core, moved from the ORM. The symbol
291 remains importable from ``sqlalchemy.orm.exc``.
294 """
297class MultipleResultsFound(InvalidRequestError):
298 """A single database result was required but more than one were found.
300 .. versionchanged:: 1.4 This exception is now part of the
301 ``sqlalchemy.exc`` module in Core, moved from the ORM. The symbol
302 remains importable from ``sqlalchemy.orm.exc``.
305 """
308class NoReferenceError(InvalidRequestError):
309 """Raised by ``ForeignKey`` to indicate a reference cannot be resolved."""
312class AwaitRequired(InvalidRequestError):
313 """Error raised by the async greenlet spawn if no async operation
314 was awaited when it required one.
316 """
318 code = "xd1r"
321class MissingGreenlet(InvalidRequestError):
322 r"""Error raised by the async greenlet await\_ if called while not inside
323 the greenlet spawn context.
325 """
327 code = "xd2s"
330class NoReferencedTableError(NoReferenceError):
331 """Raised by ``ForeignKey`` when the referred ``Table`` cannot be
332 located.
334 """
336 def __init__(self, message, tname):
337 NoReferenceError.__init__(self, message)
338 self.table_name = tname
340 def __reduce__(self):
341 return self.__class__, (self.args[0], self.table_name)
344class NoReferencedColumnError(NoReferenceError):
345 """Raised by ``ForeignKey`` when the referred ``Column`` cannot be
346 located.
348 """
350 def __init__(self, message, tname, cname):
351 NoReferenceError.__init__(self, message)
352 self.table_name = tname
353 self.column_name = cname
355 def __reduce__(self):
356 return (
357 self.__class__,
358 (self.args[0], self.table_name, self.column_name),
359 )
362class NoSuchTableError(InvalidRequestError):
363 """Table does not exist or is not visible to a connection."""
366class UnreflectableTableError(InvalidRequestError):
367 """Table exists but can't be reflected for some reason.
369 .. versionadded:: 1.2
371 """
374class UnboundExecutionError(InvalidRequestError):
375 """SQL was attempted without a database connection to execute it on."""
378class DontWrapMixin(object):
379 """A mixin class which, when applied to a user-defined Exception class,
380 will not be wrapped inside of :exc:`.StatementError` if the error is
381 emitted within the process of executing a statement.
383 E.g.::
385 from sqlalchemy.exc import DontWrapMixin
387 class MyCustomException(Exception, DontWrapMixin):
388 pass
390 class MySpecialType(TypeDecorator):
391 impl = String
393 def process_bind_param(self, value, dialect):
394 if value == 'invalid':
395 raise MyCustomException("invalid!")
397 """
400class StatementError(SQLAlchemyError):
401 """An error occurred during execution of a SQL statement.
403 :class:`StatementError` wraps the exception raised
404 during execution, and features :attr:`.statement`
405 and :attr:`.params` attributes which supply context regarding
406 the specifics of the statement which had an issue.
408 The wrapped exception object is available in
409 the :attr:`.orig` attribute.
411 """
413 statement = None
414 """The string SQL statement being invoked when this exception occurred."""
416 params = None
417 """The parameter list being used when this exception occurred."""
419 orig = None
420 """The DBAPI exception object."""
422 ismulti = None
424 def __init__(
425 self,
426 message,
427 statement,
428 params,
429 orig,
430 hide_parameters=False,
431 code=None,
432 ismulti=None,
433 ):
434 SQLAlchemyError.__init__(self, message, code=code)
435 self.statement = statement
436 self.params = params
437 self.orig = orig
438 self.ismulti = ismulti
439 self.hide_parameters = hide_parameters
440 self.detail = []
442 def add_detail(self, msg):
443 self.detail.append(msg)
445 def __reduce__(self):
446 return (
447 self.__class__,
448 (
449 self.args[0],
450 self.statement,
451 self.params,
452 self.orig,
453 self.hide_parameters,
454 self.__dict__.get("code"),
455 self.ismulti,
456 ),
457 {"detail": self.detail},
458 )
460 @_preloaded.preload_module("sqlalchemy.sql.util")
461 def _sql_message(self, as_unicode):
462 util = _preloaded.preloaded.sql_util
464 details = [self._message(as_unicode=as_unicode)]
465 if self.statement:
466 if not as_unicode and not compat.py3k:
467 stmt_detail = "[SQL: %s]" % compat.safe_bytestring(
468 self.statement
469 )
470 else:
471 stmt_detail = "[SQL: %s]" % self.statement
472 details.append(stmt_detail)
473 if self.params:
474 if self.hide_parameters:
475 details.append(
476 "[SQL parameters hidden due to hide_parameters=True]"
477 )
478 else:
479 params_repr = util._repr_params(
480 self.params, 10, ismulti=self.ismulti
481 )
482 details.append("[parameters: %r]" % params_repr)
483 code_str = self._code_str()
484 if code_str:
485 details.append(code_str)
486 return "\n".join(["(%s)" % det for det in self.detail] + details)
489class DBAPIError(StatementError):
490 """Raised when the execution of a database operation fails.
492 Wraps exceptions raised by the DB-API underlying the
493 database operation. Driver-specific implementations of the standard
494 DB-API exception types are wrapped by matching sub-types of SQLAlchemy's
495 :class:`DBAPIError` when possible. DB-API's ``Error`` type maps to
496 :class:`DBAPIError` in SQLAlchemy, otherwise the names are identical. Note
497 that there is no guarantee that different DB-API implementations will
498 raise the same exception type for any given error condition.
500 :class:`DBAPIError` features :attr:`~.StatementError.statement`
501 and :attr:`~.StatementError.params` attributes which supply context
502 regarding the specifics of the statement which had an issue, for the
503 typical case when the error was raised within the context of
504 emitting a SQL statement.
506 The wrapped exception object is available in the
507 :attr:`~.StatementError.orig` attribute. Its type and properties are
508 DB-API implementation specific.
510 """
512 code = "dbapi"
514 @classmethod
515 def instance(
516 cls,
517 statement,
518 params,
519 orig,
520 dbapi_base_err,
521 hide_parameters=False,
522 connection_invalidated=False,
523 dialect=None,
524 ismulti=None,
525 ):
526 # Don't ever wrap these, just return them directly as if
527 # DBAPIError didn't exist.
528 if (
529 isinstance(orig, BaseException) and not isinstance(orig, Exception)
530 ) or isinstance(orig, DontWrapMixin):
531 return orig
533 if orig is not None:
534 # not a DBAPI error, statement is present.
535 # raise a StatementError
536 if isinstance(orig, SQLAlchemyError) and statement:
537 return StatementError(
538 "(%s.%s) %s"
539 % (
540 orig.__class__.__module__,
541 orig.__class__.__name__,
542 orig.args[0],
543 ),
544 statement,
545 params,
546 orig,
547 hide_parameters=hide_parameters,
548 code=orig.code,
549 ismulti=ismulti,
550 )
551 elif not isinstance(orig, dbapi_base_err) and statement:
552 return StatementError(
553 "(%s.%s) %s"
554 % (
555 orig.__class__.__module__,
556 orig.__class__.__name__,
557 orig,
558 ),
559 statement,
560 params,
561 orig,
562 hide_parameters=hide_parameters,
563 ismulti=ismulti,
564 )
566 glob = globals()
567 for super_ in orig.__class__.__mro__:
568 name = super_.__name__
569 if dialect:
570 name = dialect.dbapi_exception_translation_map.get(
571 name, name
572 )
573 if name in glob and issubclass(glob[name], DBAPIError):
574 cls = glob[name]
575 break
577 return cls(
578 statement,
579 params,
580 orig,
581 connection_invalidated=connection_invalidated,
582 hide_parameters=hide_parameters,
583 code=cls.code,
584 ismulti=ismulti,
585 )
587 def __reduce__(self):
588 return (
589 self.__class__,
590 (
591 self.statement,
592 self.params,
593 self.orig,
594 self.hide_parameters,
595 self.connection_invalidated,
596 self.__dict__.get("code"),
597 self.ismulti,
598 ),
599 {"detail": self.detail},
600 )
602 def __init__(
603 self,
604 statement,
605 params,
606 orig,
607 hide_parameters=False,
608 connection_invalidated=False,
609 code=None,
610 ismulti=None,
611 ):
612 try:
613 text = str(orig)
614 except Exception as e:
615 text = "Error in str() of DB-API-generated exception: " + str(e)
616 StatementError.__init__(
617 self,
618 "(%s.%s) %s"
619 % (orig.__class__.__module__, orig.__class__.__name__, text),
620 statement,
621 params,
622 orig,
623 hide_parameters,
624 code=code,
625 ismulti=ismulti,
626 )
627 self.connection_invalidated = connection_invalidated
630class InterfaceError(DBAPIError):
631 """Wraps a DB-API InterfaceError."""
633 code = "rvf5"
636class DatabaseError(DBAPIError):
637 """Wraps a DB-API DatabaseError."""
639 code = "4xp6"
642class DataError(DatabaseError):
643 """Wraps a DB-API DataError."""
645 code = "9h9h"
648class OperationalError(DatabaseError):
649 """Wraps a DB-API OperationalError."""
651 code = "e3q8"
654class IntegrityError(DatabaseError):
655 """Wraps a DB-API IntegrityError."""
657 code = "gkpj"
660class InternalError(DatabaseError):
661 """Wraps a DB-API InternalError."""
663 code = "2j85"
666class ProgrammingError(DatabaseError):
667 """Wraps a DB-API ProgrammingError."""
669 code = "f405"
672class NotSupportedError(DatabaseError):
673 """Wraps a DB-API NotSupportedError."""
675 code = "tw8g"
678# Warnings
681class SADeprecationWarning(HasDescriptionCode, DeprecationWarning):
682 """Issued for usage of deprecated APIs."""
684 deprecated_since = None
685 "Indicates the version that started raising this deprecation warning"
688class Base20DeprecationWarning(SADeprecationWarning):
689 """Issued for usage of APIs specifically deprecated or legacy in
690 SQLAlchemy 2.0.
692 .. seealso::
694 :ref:`error_b8d9`.
696 :ref:`deprecation_20_mode`
698 """
700 deprecated_since = "1.4"
701 "Indicates the version that started raising this deprecation warning"
703 def __str__(self):
704 return (
705 super(Base20DeprecationWarning, self).__str__()
706 + " (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)"
707 )
710class LegacyAPIWarning(Base20DeprecationWarning):
711 """indicates an API that is in 'legacy' status, a long term deprecation."""
714class RemovedIn20Warning(Base20DeprecationWarning):
715 """indicates an API that will be fully removed in SQLAlchemy 2.0."""
718class MovedIn20Warning(RemovedIn20Warning):
719 """Subtype of RemovedIn20Warning to indicate an API that moved only."""
722class SAPendingDeprecationWarning(PendingDeprecationWarning):
723 """A similar warning as :class:`_exc.SADeprecationWarning`, this warning
724 is not used in modern versions of SQLAlchemy.
726 """
728 deprecated_since = None
729 "Indicates the version that started raising this deprecation warning"
732class SAWarning(HasDescriptionCode, RuntimeWarning):
733 """Issued at runtime."""