Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/sqlalchemy/exc.py: 69%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# exc.py
2# Copyright (C) 2005-2026 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 __future__ import annotations
18import typing
19from typing import Any
20from typing import List
21from typing import Optional
22from typing import overload
23from typing import Tuple
24from typing import Type
25from typing import Union
27from .util import compat
28from .util import preloaded as _preloaded
30if typing.TYPE_CHECKING:
31 from .engine.interfaces import _AnyExecuteParams
32 from .engine.interfaces import Dialect
33 from .sql.compiler import Compiled
34 from .sql.compiler import TypeCompiler
35 from .sql.elements import ClauseElement
37if typing.TYPE_CHECKING:
38 _version_token: str
39else:
40 # set by __init__.py
41 _version_token = None
44class HasDescriptionCode:
45 """helper which adds 'code' as an attribute and '_code_str' as a method"""
47 code: Optional[str] = None
49 def __init__(self, *arg: Any, **kw: Any):
50 code = kw.pop("code", None)
51 if code is not None:
52 self.code = code
53 super().__init__(*arg, **kw)
55 _what_are_we = "error"
57 def _code_str(self) -> str:
58 if not self.code:
59 return ""
60 else:
61 return (
62 f"(Background on this {self._what_are_we} at: "
63 f"https://sqlalche.me/e/{_version_token}/{self.code})"
64 )
66 def __str__(self) -> str:
67 message = super().__str__()
68 if self.code:
69 message = "%s %s" % (message, self._code_str())
70 return message
73class SQLAlchemyError(HasDescriptionCode, Exception):
74 """Generic error class."""
76 def _message(self) -> str:
77 # rules:
78 #
79 # 1. single arg string will usually be a unicode
80 # object, but since __str__() must return unicode, check for
81 # bytestring just in case
82 #
83 # 2. for multiple self.args, this is not a case in current
84 # SQLAlchemy though this is happening in at least one known external
85 # library, call str() which does a repr().
86 #
87 text: str
89 if len(self.args) == 1:
90 arg_text = self.args[0]
92 if isinstance(arg_text, bytes):
93 text = compat.decode_backslashreplace(arg_text, "utf-8")
94 # This is for when the argument is not a string of any sort.
95 # Otherwise, converting this exception to string would fail for
96 # non-string arguments.
97 else:
98 text = str(arg_text)
100 return text
101 else:
102 # this is not a normal case within SQLAlchemy but is here for
103 # compatibility with Exception.args - the str() comes out as
104 # a repr() of the tuple
105 return str(self.args)
107 def _sql_message(self) -> str:
108 message = self._message()
110 if self.code:
111 message = "%s %s" % (message, self._code_str())
113 return message
115 def __str__(self) -> str:
116 return self._sql_message()
119class EmulatedDBAPIException(Exception):
120 """Serves as the base of the DBAPI ``Error`` class for dialects where
121 a DBAPI exception hierrchy needs to be emulated.
123 The current example is the asyncpg dialect.
125 .. versionadded:: 2.1
127 """
129 orig: Exception | None
131 def __init__(self, message: str, orig: Exception | None = None):
132 # we accept None for Exception since all DBAPI.Error objects
133 # need to support construction with a message alone
134 super().__init__(message)
135 self.orig = orig
137 @property
138 def driver_exception(self) -> Exception:
139 """The original driver exception that was raised.
141 This exception object will always originate from outside of
142 SQLAlchemy.
144 """
146 if self.orig is None:
147 raise ValueError(
148 "No original exception is present. Was this "
149 "EmulatedDBAPIException constructed without a driver error?"
150 )
151 return self.orig
153 def __reduce__(self) -> Any:
154 return self.__class__, (self.args[0], self.orig)
157class ArgumentError(SQLAlchemyError):
158 """Raised when an invalid or conflicting function argument is supplied.
160 This error generally corresponds to construction time state errors.
162 """
165class DuplicateColumnError(ArgumentError):
166 """a Column is being added to a Table that would replace another
167 Column, without appropriate parameters to allow this in place.
169 .. versionadded:: 2.0.0b4
171 """
174class ObjectNotExecutableError(ArgumentError):
175 """Raised when an object is passed to .execute() that can't be
176 executed as SQL.
178 """
180 def __init__(self, target: Any):
181 super().__init__(f"Not an executable object: {target!r}")
182 self.target = target
184 def __reduce__(self) -> Union[str, Tuple[Any, ...]]:
185 return self.__class__, (self.target,)
188class NoSuchModuleError(ArgumentError):
189 """Raised when a dynamically-loaded module (usually a database dialect)
190 of a particular name cannot be located."""
193class NoForeignKeysError(ArgumentError):
194 """Raised when no foreign keys can be located between two selectables
195 during a join."""
198class AmbiguousForeignKeysError(ArgumentError):
199 """Raised when more than one foreign key matching can be located
200 between two selectables during a join."""
203class ConstraintColumnNotFoundError(ArgumentError):
204 """raised when a constraint refers to a string column name that
205 is not present in the table being constrained.
207 .. versionadded:: 2.0
209 """
212class CircularDependencyError(SQLAlchemyError):
213 """Raised by topological sorts when a circular dependency is detected.
215 There are two scenarios where this error occurs:
217 * In a Session flush operation, if two objects are mutually dependent
218 on each other, they can not be inserted or deleted via INSERT or
219 DELETE statements alone; an UPDATE will be needed to post-associate
220 or pre-deassociate one of the foreign key constrained values.
221 The ``post_update`` flag described at :ref:`post_update` can resolve
222 this cycle.
223 * In a :attr:`_schema.MetaData.sorted_tables` operation, two
224 :class:`_schema.ForeignKey`
225 or :class:`_schema.ForeignKeyConstraint` objects mutually refer to each
226 other. Apply the ``use_alter=True`` flag to one or both,
227 see :ref:`use_alter`.
229 """
231 def __init__(
232 self,
233 message: str,
234 cycles: Any,
235 edges: Any,
236 msg: Optional[str] = None,
237 code: Optional[str] = None,
238 ):
239 if msg is None:
240 message += " (%s)" % ", ".join(repr(s) for s in cycles)
241 else:
242 message = msg
243 SQLAlchemyError.__init__(self, message, code=code)
244 self.cycles = cycles
245 self.edges = edges
247 def __reduce__(self) -> Union[str, Tuple[Any, ...]]:
248 return (
249 self.__class__,
250 (None, self.cycles, self.edges, self.args[0]),
251 {"code": self.code} if self.code is not None else {},
252 )
255class CompileError(SQLAlchemyError):
256 """Raised when an error occurs during SQL compilation"""
259class UnsupportedCompilationError(CompileError):
260 """Raised when an operation is not supported by the given compiler.
262 .. seealso::
264 :ref:`faq_sql_expression_string`
266 :ref:`error_l7de`
267 """
269 code = "l7de"
271 def __init__(
272 self,
273 compiler: Union[Compiled, TypeCompiler],
274 element_type: Type[ClauseElement],
275 message: Optional[str] = None,
276 ):
277 super().__init__(
278 "Compiler %r can't render element of type %s%s"
279 % (compiler, element_type, ": %s" % message if message else "")
280 )
281 self.compiler = compiler
282 self.element_type = element_type
283 self.message = message
285 def __reduce__(self) -> Union[str, Tuple[Any, ...]]:
286 return self.__class__, (self.compiler, self.element_type, self.message)
289class IdentifierError(SQLAlchemyError):
290 """Raised when a schema name is beyond the max character limit"""
293class DisconnectionError(SQLAlchemyError):
294 """A disconnect is detected on a raw DB-API connection.
296 This error is raised and consumed internally by a connection pool. It can
297 be raised by the :meth:`_events.PoolEvents.checkout`
298 event so that the host pool
299 forces a retry; the exception will be caught three times in a row before
300 the pool gives up and raises :class:`~sqlalchemy.exc.InvalidRequestError`
301 regarding the connection attempt.
303 """
305 invalidate_pool: bool = False
308class InvalidatePoolError(DisconnectionError):
309 """Raised when the connection pool should invalidate all stale connections.
311 A subclass of :class:`_exc.DisconnectionError` that indicates that the
312 disconnect situation encountered on the connection probably means the
313 entire pool should be invalidated, as the database has been restarted.
315 This exception will be handled otherwise the same way as
316 :class:`_exc.DisconnectionError`, allowing three attempts to reconnect
317 before giving up.
319 """
321 invalidate_pool: bool = True
324class TimeoutError(SQLAlchemyError): # noqa
325 """Raised when a connection pool times out on getting a connection."""
328class InvalidRequestError(SQLAlchemyError):
329 """SQLAlchemy was asked to do something it can't do.
331 This error generally corresponds to runtime state errors.
333 """
336class IllegalStateChangeError(InvalidRequestError):
337 """An object that tracks state encountered an illegal state change
338 of some kind.
340 .. versionadded:: 2.0
342 """
345class NoInspectionAvailable(InvalidRequestError):
346 """A subject passed to :func:`sqlalchemy.inspection.inspect` produced
347 no context for inspection."""
350class NoDBAPILoaded(InvalidRequestError):
351 """A DBAPI-level attribute was requested from a dialect which has no
352 DBAPI module loaded, or whose DBAPI does not publish the attribute.
354 This is not an error on the part of the dialect; a dialect which is
355 used only to compile statements, rather than to interact with a
356 database, has no DBAPI established, and a DBAPI module is not obliged
357 to publish a version number of its own.
359 .. versionadded:: 2.1
361 """
364class PendingRollbackError(InvalidRequestError):
365 """A transaction has failed and needs to be rolled back before
366 continuing.
368 .. versionadded:: 1.4
370 """
373class ResourceClosedError(InvalidRequestError):
374 """An operation was requested from a connection, cursor, or other
375 object that's in a closed state."""
378class NoSuchColumnError(InvalidRequestError, KeyError):
379 """A nonexistent column is requested from a ``Row``."""
382class AmbiguousColumnError(InvalidRequestError):
383 """Raised when a column/attribute name is ambiguous across multiple
384 entities.
386 This can occur when using :meth:`_sql.Select.filter_by` with multiple
387 joined tables that have columns with the same name.
389 .. versionadded:: 2.1
391 """
394class NoResultFound(InvalidRequestError):
395 """A database result was required but none was found.
398 .. versionchanged:: 1.4 This exception is now part of the
399 ``sqlalchemy.exc`` module in Core, moved from the ORM. The symbol
400 remains importable from ``sqlalchemy.orm.exc``.
403 """
406class MultipleResultsFound(InvalidRequestError):
407 """A single database result was required but more than one were found.
409 .. versionchanged:: 1.4 This exception is now part of the
410 ``sqlalchemy.exc`` module in Core, moved from the ORM. The symbol
411 remains importable from ``sqlalchemy.orm.exc``.
414 """
417class NoReferenceError(InvalidRequestError):
418 """Raised by ``ForeignKey`` to indicate a reference cannot be resolved."""
420 table_name: str
423class AwaitRequired(InvalidRequestError):
424 """Error raised by the async greenlet spawn if no async operation
425 was awaited when it required one.
427 """
429 code = "xd1r"
432class MissingGreenlet(InvalidRequestError):
433 r"""Error raised by the async greenlet await\_ if called while not inside
434 the greenlet spawn context.
436 """
438 code = "xd2s"
441class NoReferencedTableError(NoReferenceError):
442 """Raised by ``ForeignKey`` when the referred ``Table`` cannot be
443 located.
445 """
447 def __init__(self, message: str, tname: str):
448 NoReferenceError.__init__(self, message)
449 self.table_name = tname
451 def __reduce__(self) -> Union[str, Tuple[Any, ...]]:
452 return self.__class__, (self.args[0], self.table_name)
455class NoReferencedColumnError(NoReferenceError):
456 """Raised by ``ForeignKey`` when the referred ``Column`` cannot be
457 located.
459 """
461 def __init__(self, message: str, tname: str, cname: str):
462 NoReferenceError.__init__(self, message)
463 self.table_name = tname
464 self.column_name = cname
466 def __reduce__(self) -> Union[str, Tuple[Any, ...]]:
467 return (
468 self.__class__,
469 (self.args[0], self.table_name, self.column_name),
470 )
473class NoSuchTableError(InvalidRequestError):
474 """Table does not exist or is not visible to a connection."""
477class UnreflectableTableError(InvalidRequestError):
478 """Table exists but can't be reflected for some reason."""
481class UnboundExecutionError(InvalidRequestError):
482 """SQL was attempted without a database connection to execute it on."""
485class DontWrapMixin:
486 """A mixin class which, when applied to a user-defined Exception class,
487 will not be wrapped inside of :exc:`.StatementError` if the error is
488 emitted within the process of executing a statement.
490 E.g.::
492 from sqlalchemy.exc import DontWrapMixin
495 class MyCustomException(Exception, DontWrapMixin):
496 pass
499 class MySpecialType(TypeDecorator):
500 impl = String
502 def process_bind_param(self, value, dialect):
503 if value == "invalid":
504 raise MyCustomException("invalid!")
506 """
509class StatementError(SQLAlchemyError):
510 """An error occurred during execution of a SQL statement.
512 :class:`StatementError` wraps the exception raised
513 during execution, and features :attr:`.statement`
514 and :attr:`.params` attributes which supply context regarding
515 the specifics of the statement which had an issue.
517 The wrapped exception object is available in
518 the :attr:`.orig` attribute.
520 """
522 statement: Optional[str] = None
523 """The string SQL statement being invoked when this exception occurred."""
525 params: Optional[_AnyExecuteParams] = None
526 """The parameter list being used when this exception occurred."""
528 orig: Optional[BaseException] = None
529 """The original exception that was thrown.
531 .. seealso::
533 :attr:`.DBAPIError.driver_exception` - a more specific attribute that
534 is guaranteed to return the exception object raised by the third
535 party driver in use, even when using asyncio.
537 """
539 ismulti: Optional[bool] = None
540 """multi parameter passed to repr_params(). None is meaningful."""
542 connection_invalidated: bool = False
544 def __init__(
545 self,
546 message: str,
547 statement: Optional[str],
548 params: Optional[_AnyExecuteParams],
549 orig: Optional[BaseException],
550 hide_parameters: bool = False,
551 code: Optional[str] = None,
552 ismulti: Optional[bool] = None,
553 ):
554 SQLAlchemyError.__init__(self, message, code=code)
555 self.statement = statement
556 self.params = params
557 self.orig = orig
558 self.ismulti = ismulti
559 self.hide_parameters = hide_parameters
560 self.detail: List[str] = []
562 def add_detail(self, msg: str) -> None:
563 self.detail.append(msg)
565 def __reduce__(self) -> Union[str, Tuple[Any, ...]]:
566 return (
567 self.__class__,
568 (
569 self.args[0],
570 self.statement,
571 self.params,
572 self.orig,
573 self.hide_parameters,
574 self.__dict__.get("code"),
575 self.ismulti,
576 ),
577 {"detail": self.detail},
578 )
580 @_preloaded.preload_module("sqlalchemy.sql.util")
581 def _sql_message(self) -> str:
582 util = _preloaded.sql_util
584 details = [self._message()]
585 if self.statement:
586 stmt_detail = "[SQL: %s]" % self.statement
587 details.append(stmt_detail)
588 if self.params:
589 if self.hide_parameters:
590 details.append(
591 "[SQL parameters hidden due to hide_parameters=True]"
592 )
593 else:
594 params_repr = util._repr_params(
595 self.params, 10, ismulti=self.ismulti
596 )
597 details.append("[parameters: %r]" % params_repr)
598 code_str = self._code_str()
599 if code_str:
600 details.append(code_str)
601 return "\n".join(["(%s)" % det for det in self.detail] + details)
604class DBAPIError(StatementError):
605 """Raised when the execution of a database operation fails.
607 Wraps exceptions raised by the DB-API underlying the
608 database operation. Driver-specific implementations of the standard
609 DB-API exception types are wrapped by matching sub-types of SQLAlchemy's
610 :class:`DBAPIError` when possible. DB-API's ``Error`` type maps to
611 :class:`DBAPIError` in SQLAlchemy, otherwise the names are identical. Note
612 that there is no guarantee that different DB-API implementations will
613 raise the same exception type for any given error condition.
615 :class:`DBAPIError` features :attr:`~.StatementError.statement`
616 and :attr:`~.StatementError.params` attributes which supply context
617 regarding the specifics of the statement which had an issue, for the
618 typical case when the error was raised within the context of
619 emitting a SQL statement.
621 The wrapped exception object is available in the
622 :attr:`~.StatementError.orig` attribute. Its type and properties are
623 DB-API implementation specific.
625 """
627 code = "dbapi"
629 orig: Optional[Exception]
631 @overload
632 @classmethod
633 def instance(
634 cls,
635 statement: Optional[str],
636 params: Optional[_AnyExecuteParams],
637 orig: Exception,
638 dbapi_base_err: Type[Exception],
639 hide_parameters: bool = False,
640 connection_invalidated: bool = False,
641 dialect: Optional[Dialect] = None,
642 ismulti: Optional[bool] = None,
643 ) -> StatementError: ...
645 @overload
646 @classmethod
647 def instance(
648 cls,
649 statement: Optional[str],
650 params: Optional[_AnyExecuteParams],
651 orig: DontWrapMixin,
652 dbapi_base_err: Type[Exception],
653 hide_parameters: bool = False,
654 connection_invalidated: bool = False,
655 dialect: Optional[Dialect] = None,
656 ismulti: Optional[bool] = None,
657 ) -> DontWrapMixin: ...
659 @overload
660 @classmethod
661 def instance(
662 cls,
663 statement: Optional[str],
664 params: Optional[_AnyExecuteParams],
665 orig: BaseException,
666 dbapi_base_err: Type[Exception],
667 hide_parameters: bool = False,
668 connection_invalidated: bool = False,
669 dialect: Optional[Dialect] = None,
670 ismulti: Optional[bool] = None,
671 ) -> BaseException: ...
673 @classmethod
674 def instance(
675 cls,
676 statement: Optional[str],
677 params: Optional[_AnyExecuteParams],
678 orig: Union[BaseException, DontWrapMixin],
679 dbapi_base_err: Type[Exception],
680 hide_parameters: bool = False,
681 connection_invalidated: bool = False,
682 dialect: Optional[Dialect] = None,
683 ismulti: Optional[bool] = None,
684 ) -> Union[BaseException, DontWrapMixin]:
685 # Don't ever wrap these, just return them directly as if
686 # DBAPIError didn't exist.
687 if (
688 isinstance(orig, BaseException) and not isinstance(orig, Exception)
689 ) or isinstance(orig, DontWrapMixin):
690 return orig
692 if orig is not None:
693 # not a DBAPI error, statement is present.
694 # raise a StatementError
695 if isinstance(orig, SQLAlchemyError) and statement:
696 return StatementError(
697 "(%s.%s) %s"
698 % (
699 orig.__class__.__module__,
700 orig.__class__.__name__,
701 orig.args[0],
702 ),
703 statement,
704 params,
705 orig,
706 hide_parameters=hide_parameters,
707 code=orig.code,
708 ismulti=ismulti,
709 )
710 elif not isinstance(orig, dbapi_base_err) and statement:
711 return StatementError(
712 "(%s.%s) %s"
713 % (
714 orig.__class__.__module__,
715 orig.__class__.__name__,
716 orig,
717 ),
718 statement,
719 params,
720 orig,
721 hide_parameters=hide_parameters,
722 ismulti=ismulti,
723 )
725 glob = globals()
726 for super_ in orig.__class__.__mro__:
727 name = super_.__name__
728 if dialect:
729 name = dialect.dbapi_exception_translation_map.get(
730 name, name
731 )
732 if name in glob and issubclass(glob[name], DBAPIError):
733 cls = glob[name]
734 break
736 return cls(
737 statement,
738 params,
739 orig,
740 connection_invalidated=connection_invalidated,
741 hide_parameters=hide_parameters,
742 code=cls.code,
743 ismulti=ismulti,
744 )
746 def __reduce__(self) -> Union[str, Tuple[Any, ...]]:
747 return (
748 self.__class__,
749 (
750 self.statement,
751 self.params,
752 self.orig,
753 self.hide_parameters,
754 self.connection_invalidated,
755 self.__dict__.get("code"),
756 self.ismulti,
757 ),
758 {"detail": self.detail},
759 )
761 def __init__(
762 self,
763 statement: Optional[str],
764 params: Optional[_AnyExecuteParams],
765 orig: BaseException,
766 hide_parameters: bool = False,
767 connection_invalidated: bool = False,
768 code: Optional[str] = None,
769 ismulti: Optional[bool] = None,
770 ):
771 try:
772 text = str(orig)
773 except Exception as e:
774 text = "Error in str() of DB-API-generated exception: " + str(e)
775 StatementError.__init__(
776 self,
777 "(%s.%s) %s"
778 % (orig.__class__.__module__, orig.__class__.__name__, text),
779 statement,
780 params,
781 orig,
782 hide_parameters,
783 code=code,
784 ismulti=ismulti,
785 )
786 self.connection_invalidated = connection_invalidated
788 @property
789 def driver_exception(self) -> Exception:
790 """The exception object originating from the driver (DBAPI) outside
791 of SQLAlchemy.
793 In the case of some asyncio dialects, special steps are taken to
794 resolve the exception to what the third party driver has raised, even
795 for SQLAlchemy dialects that include an "emulated" DBAPI exception
796 hierarchy.
798 For non-asyncio dialects, this attribute will be the same attribute
799 as the :attr:`.StatementError.orig` attribute.
801 For an asyncio dialect provided by SQLAlchemy, depending on if the
802 dialect provides an "emulated" exception hierarchy or if the underlying
803 DBAPI raises DBAPI-style exceptions, it will refer to either the
804 :attr:`.EmulatedDBAPIException.driver_exception` attribute on the
805 :class:`.EmulatedDBAPIException` that's thrown (such as when using
806 asyncpg), or to the actual exception object thrown by the
807 third party driver.
809 .. versionadded:: 2.1
811 """
813 if self.orig is None:
814 raise ValueError(
815 "No original exception is present. Was this "
816 "DBAPIError constructed without a driver error?"
817 )
819 if isinstance(self.orig, EmulatedDBAPIException):
820 return self.orig.driver_exception
821 else:
822 return self.orig
825class InterfaceError(DBAPIError):
826 """Wraps a DB-API InterfaceError."""
828 code = "rvf5"
831class DatabaseError(DBAPIError):
832 """Wraps a DB-API DatabaseError."""
834 code = "4xp6"
837class DataError(DatabaseError):
838 """Wraps a DB-API DataError."""
840 code = "9h9h"
843class OperationalError(DatabaseError):
844 """Wraps a DB-API OperationalError."""
846 code = "e3q8"
849class IntegrityError(DatabaseError):
850 """Wraps a DB-API IntegrityError."""
852 code = "gkpj"
855class InternalError(DatabaseError):
856 """Wraps a DB-API InternalError."""
858 code = "2j85"
861class ProgrammingError(DatabaseError):
862 """Wraps a DB-API ProgrammingError."""
864 code = "f405"
867class NotSupportedError(DatabaseError):
868 """Wraps a DB-API NotSupportedError."""
870 code = "tw8g"
873# Warnings
876class SATestSuiteWarning(Warning):
877 """warning for a condition detected during tests that is non-fatal
879 Currently outside of SAWarning so that we can work around tools like
880 Alembic doing the wrong thing with warnings.
882 """
885class SADeprecationWarning(HasDescriptionCode, DeprecationWarning):
886 """Issued for usage of deprecated APIs."""
888 deprecated_since: Optional[str] = None
889 "Indicates the version that started raising this deprecation warning"
892class Base20DeprecationWarning(SADeprecationWarning):
893 """Issued for usage of APIs specifically deprecated or legacy in
894 SQLAlchemy 2.0.
896 .. seealso::
898 :ref:`error_b8d9`.
900 :ref:`deprecation_20_mode`
902 """
904 deprecated_since: Optional[str] = "1.4"
905 "Indicates the version that started raising this deprecation warning"
907 def __str__(self) -> str:
908 return (
909 super().__str__()
910 + " (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)"
911 )
914class LegacyAPIWarning(Base20DeprecationWarning):
915 """indicates an API that is in 'legacy' status, a long term deprecation."""
918class MovedIn20Warning(Base20DeprecationWarning):
919 """Subtype of Base20DeprecationWarning to indicate an API that moved
920 only.
921 """
924class SAPendingDeprecationWarning(PendingDeprecationWarning):
925 """A similar warning as :class:`_exc.SADeprecationWarning`, this warning
926 is not used in modern versions of SQLAlchemy.
928 """
930 deprecated_since: Optional[str] = None
931 "Indicates the version that started raising this deprecation warning"
934class SAWarning(HasDescriptionCode, RuntimeWarning):
935 """Issued at runtime."""
937 _what_are_we = "warning"