Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/sqlalchemy/exc.py: 70%

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

226 statements  

1# exc.py 

2# Copyright (C) 2005-2024 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 

7 

8"""Exceptions used with SQLAlchemy. 

9 

10The base exception class is :exc:`.SQLAlchemyError`. Exceptions which are 

11raised as a result of DBAPI exceptions are all subclasses of 

12:exc:`.DBAPIError`. 

13 

14""" 

15from __future__ import annotations 

16 

17import typing 

18from typing import Any 

19from typing import List 

20from typing import Optional 

21from typing import overload 

22from typing import Tuple 

23from typing import Type 

24from typing import Union 

25 

26from .util import compat 

27from .util import preloaded as _preloaded 

28 

29if typing.TYPE_CHECKING: 

30 from .engine.interfaces import _AnyExecuteParams 

31 from .engine.interfaces import Dialect 

32 from .sql.compiler import Compiled 

33 from .sql.compiler import TypeCompiler 

34 from .sql.elements import ClauseElement 

35 

36if typing.TYPE_CHECKING: 

37 _version_token: str 

38else: 

39 # set by __init__.py 

40 _version_token = None 

41 

42 

43class HasDescriptionCode: 

44 """helper which adds 'code' as an attribute and '_code_str' as a method""" 

45 

46 code: Optional[str] = None 

47 

48 def __init__(self, *arg: Any, **kw: Any): 

49 code = kw.pop("code", None) 

50 if code is not None: 

51 self.code = code 

52 super().__init__(*arg, **kw) 

53 

54 _what_are_we = "error" 

55 

56 def _code_str(self) -> str: 

57 if not self.code: 

58 return "" 

59 else: 

60 return ( 

61 f"(Background on this {self._what_are_we} at: " 

62 f"https://sqlalche.me/e/{_version_token}/{self.code})" 

63 ) 

64 

65 def __str__(self) -> str: 

66 message = super().__str__() 

67 if self.code: 

68 message = "%s %s" % (message, self._code_str()) 

69 return message 

70 

71 

72class SQLAlchemyError(HasDescriptionCode, Exception): 

73 """Generic error class.""" 

74 

75 def _message(self) -> str: 

76 # rules: 

77 # 

78 # 1. single arg string will usually be a unicode 

79 # object, but since __str__() must return unicode, check for 

80 # bytestring just in case 

81 # 

82 # 2. for multiple self.args, this is not a case in current 

83 # SQLAlchemy though this is happening in at least one known external 

84 # library, call str() which does a repr(). 

85 # 

86 text: str 

87 

88 if len(self.args) == 1: 

89 arg_text = self.args[0] 

90 

91 if isinstance(arg_text, bytes): 

92 text = compat.decode_backslashreplace(arg_text, "utf-8") 

93 # This is for when the argument is not a string of any sort. 

94 # Otherwise, converting this exception to string would fail for 

95 # non-string arguments. 

96 else: 

97 text = str(arg_text) 

98 

99 return text 

100 else: 

101 # this is not a normal case within SQLAlchemy but is here for 

102 # compatibility with Exception.args - the str() comes out as 

103 # a repr() of the tuple 

104 return str(self.args) 

105 

106 def _sql_message(self) -> str: 

107 message = self._message() 

108 

109 if self.code: 

110 message = "%s %s" % (message, self._code_str()) 

111 

112 return message 

113 

114 def __str__(self) -> str: 

115 return self._sql_message() 

116 

117 

118class ArgumentError(SQLAlchemyError): 

119 """Raised when an invalid or conflicting function argument is supplied. 

120 

121 This error generally corresponds to construction time state errors. 

122 

123 """ 

124 

125 

126class DuplicateColumnError(ArgumentError): 

127 """a Column is being added to a Table that would replace another 

128 Column, without appropriate parameters to allow this in place. 

129 

130 .. versionadded:: 2.0.0b4 

131 

132 """ 

133 

134 

135class ObjectNotExecutableError(ArgumentError): 

136 """Raised when an object is passed to .execute() that can't be 

137 executed as SQL. 

138 

139 """ 

140 

141 def __init__(self, target: Any): 

142 super().__init__("Not an executable object: %r" % target) 

143 self.target = target 

144 

145 def __reduce__(self) -> Union[str, Tuple[Any, ...]]: 

146 return self.__class__, (self.target,) 

147 

148 

149class NoSuchModuleError(ArgumentError): 

150 """Raised when a dynamically-loaded module (usually a database dialect) 

151 of a particular name cannot be located.""" 

152 

153 

154class NoForeignKeysError(ArgumentError): 

155 """Raised when no foreign keys can be located between two selectables 

156 during a join.""" 

157 

158 

159class AmbiguousForeignKeysError(ArgumentError): 

160 """Raised when more than one foreign key matching can be located 

161 between two selectables during a join.""" 

162 

163 

164class ConstraintColumnNotFoundError(ArgumentError): 

165 """raised when a constraint refers to a string column name that 

166 is not present in the table being constrained. 

167 

168 .. versionadded:: 2.0 

169 

170 """ 

171 

172 

173class CircularDependencyError(SQLAlchemyError): 

174 """Raised by topological sorts when a circular dependency is detected. 

175 

176 There are two scenarios where this error occurs: 

177 

178 * In a Session flush operation, if two objects are mutually dependent 

179 on each other, they can not be inserted or deleted via INSERT or 

180 DELETE statements alone; an UPDATE will be needed to post-associate 

181 or pre-deassociate one of the foreign key constrained values. 

182 The ``post_update`` flag described at :ref:`post_update` can resolve 

183 this cycle. 

184 * In a :attr:`_schema.MetaData.sorted_tables` operation, two 

185 :class:`_schema.ForeignKey` 

186 or :class:`_schema.ForeignKeyConstraint` objects mutually refer to each 

187 other. Apply the ``use_alter=True`` flag to one or both, 

188 see :ref:`use_alter`. 

189 

190 """ 

191 

192 def __init__( 

193 self, 

194 message: str, 

195 cycles: Any, 

196 edges: Any, 

197 msg: Optional[str] = None, 

198 code: Optional[str] = None, 

199 ): 

200 if msg is None: 

201 message += " (%s)" % ", ".join(repr(s) for s in cycles) 

202 else: 

203 message = msg 

204 SQLAlchemyError.__init__(self, message, code=code) 

205 self.cycles = cycles 

206 self.edges = edges 

207 

208 def __reduce__(self) -> Union[str, Tuple[Any, ...]]: 

209 return ( 

210 self.__class__, 

211 (None, self.cycles, self.edges, self.args[0]), 

212 {"code": self.code} if self.code is not None else {}, 

213 ) 

214 

215 

216class CompileError(SQLAlchemyError): 

217 """Raised when an error occurs during SQL compilation""" 

218 

219 

220class UnsupportedCompilationError(CompileError): 

221 """Raised when an operation is not supported by the given compiler. 

222 

223 .. seealso:: 

224 

225 :ref:`faq_sql_expression_string` 

226 

227 :ref:`error_l7de` 

228 """ 

229 

230 code = "l7de" 

231 

232 def __init__( 

233 self, 

234 compiler: Union[Compiled, TypeCompiler], 

235 element_type: Type[ClauseElement], 

236 message: Optional[str] = None, 

237 ): 

238 super().__init__( 

239 "Compiler %r can't render element of type %s%s" 

240 % (compiler, element_type, ": %s" % message if message else "") 

241 ) 

242 self.compiler = compiler 

243 self.element_type = element_type 

244 self.message = message 

245 

246 def __reduce__(self) -> Union[str, Tuple[Any, ...]]: 

247 return self.__class__, (self.compiler, self.element_type, self.message) 

248 

249 

250class IdentifierError(SQLAlchemyError): 

251 """Raised when a schema name is beyond the max character limit""" 

252 

253 

254class DisconnectionError(SQLAlchemyError): 

255 """A disconnect is detected on a raw DB-API connection. 

256 

257 This error is raised and consumed internally by a connection pool. It can 

258 be raised by the :meth:`_events.PoolEvents.checkout` 

259 event so that the host pool 

260 forces a retry; the exception will be caught three times in a row before 

261 the pool gives up and raises :class:`~sqlalchemy.exc.InvalidRequestError` 

262 regarding the connection attempt. 

263 

264 """ 

265 

266 invalidate_pool: bool = False 

267 

268 

269class InvalidatePoolError(DisconnectionError): 

270 """Raised when the connection pool should invalidate all stale connections. 

271 

272 A subclass of :class:`_exc.DisconnectionError` that indicates that the 

273 disconnect situation encountered on the connection probably means the 

274 entire pool should be invalidated, as the database has been restarted. 

275 

276 This exception will be handled otherwise the same way as 

277 :class:`_exc.DisconnectionError`, allowing three attempts to reconnect 

278 before giving up. 

279 

280 .. versionadded:: 1.2 

281 

282 """ 

283 

284 invalidate_pool: bool = True 

285 

286 

287class TimeoutError(SQLAlchemyError): # noqa 

288 """Raised when a connection pool times out on getting a connection.""" 

289 

290 

291class InvalidRequestError(SQLAlchemyError): 

292 """SQLAlchemy was asked to do something it can't do. 

293 

294 This error generally corresponds to runtime state errors. 

295 

296 """ 

297 

298 

299class IllegalStateChangeError(InvalidRequestError): 

300 """An object that tracks state encountered an illegal state change 

301 of some kind. 

302 

303 .. versionadded:: 2.0 

304 

305 """ 

306 

307 

308class NoInspectionAvailable(InvalidRequestError): 

309 """A subject passed to :func:`sqlalchemy.inspection.inspect` produced 

310 no context for inspection.""" 

311 

312 

313class PendingRollbackError(InvalidRequestError): 

314 """A transaction has failed and needs to be rolled back before 

315 continuing. 

316 

317 .. versionadded:: 1.4 

318 

319 """ 

320 

321 

322class ResourceClosedError(InvalidRequestError): 

323 """An operation was requested from a connection, cursor, or other 

324 object that's in a closed state.""" 

325 

326 

327class NoSuchColumnError(InvalidRequestError, KeyError): 

328 """A nonexistent column is requested from a ``Row``.""" 

329 

330 

331class NoResultFound(InvalidRequestError): 

332 """A database result was required but none was found. 

333 

334 

335 .. versionchanged:: 1.4 This exception is now part of the 

336 ``sqlalchemy.exc`` module in Core, moved from the ORM. The symbol 

337 remains importable from ``sqlalchemy.orm.exc``. 

338 

339 

340 """ 

341 

342 

343class MultipleResultsFound(InvalidRequestError): 

344 """A single database result was required but more than one were found. 

345 

346 .. versionchanged:: 1.4 This exception is now part of the 

347 ``sqlalchemy.exc`` module in Core, moved from the ORM. The symbol 

348 remains importable from ``sqlalchemy.orm.exc``. 

349 

350 

351 """ 

352 

353 

354class NoReferenceError(InvalidRequestError): 

355 """Raised by ``ForeignKey`` to indicate a reference cannot be resolved.""" 

356 

357 table_name: str 

358 

359 

360class AwaitRequired(InvalidRequestError): 

361 """Error raised by the async greenlet spawn if no async operation 

362 was awaited when it required one. 

363 

364 """ 

365 

366 code = "xd1r" 

367 

368 

369class MissingGreenlet(InvalidRequestError): 

370 r"""Error raised by the async greenlet await\_ if called while not inside 

371 the greenlet spawn context. 

372 

373 """ 

374 

375 code = "xd2s" 

376 

377 

378class NoReferencedTableError(NoReferenceError): 

379 """Raised by ``ForeignKey`` when the referred ``Table`` cannot be 

380 located. 

381 

382 """ 

383 

384 def __init__(self, message: str, tname: str): 

385 NoReferenceError.__init__(self, message) 

386 self.table_name = tname 

387 

388 def __reduce__(self) -> Union[str, Tuple[Any, ...]]: 

389 return self.__class__, (self.args[0], self.table_name) 

390 

391 

392class NoReferencedColumnError(NoReferenceError): 

393 """Raised by ``ForeignKey`` when the referred ``Column`` cannot be 

394 located. 

395 

396 """ 

397 

398 def __init__(self, message: str, tname: str, cname: str): 

399 NoReferenceError.__init__(self, message) 

400 self.table_name = tname 

401 self.column_name = cname 

402 

403 def __reduce__(self) -> Union[str, Tuple[Any, ...]]: 

404 return ( 

405 self.__class__, 

406 (self.args[0], self.table_name, self.column_name), 

407 ) 

408 

409 

410class NoSuchTableError(InvalidRequestError): 

411 """Table does not exist or is not visible to a connection.""" 

412 

413 

414class UnreflectableTableError(InvalidRequestError): 

415 """Table exists but can't be reflected for some reason. 

416 

417 .. versionadded:: 1.2 

418 

419 """ 

420 

421 

422class UnboundExecutionError(InvalidRequestError): 

423 """SQL was attempted without a database connection to execute it on.""" 

424 

425 

426class DontWrapMixin: 

427 """A mixin class which, when applied to a user-defined Exception class, 

428 will not be wrapped inside of :exc:`.StatementError` if the error is 

429 emitted within the process of executing a statement. 

430 

431 E.g.:: 

432 

433 from sqlalchemy.exc import DontWrapMixin 

434 

435 class MyCustomException(Exception, DontWrapMixin): 

436 pass 

437 

438 class MySpecialType(TypeDecorator): 

439 impl = String 

440 

441 def process_bind_param(self, value, dialect): 

442 if value == 'invalid': 

443 raise MyCustomException("invalid!") 

444 

445 """ 

446 

447 

448class StatementError(SQLAlchemyError): 

449 """An error occurred during execution of a SQL statement. 

450 

451 :class:`StatementError` wraps the exception raised 

452 during execution, and features :attr:`.statement` 

453 and :attr:`.params` attributes which supply context regarding 

454 the specifics of the statement which had an issue. 

455 

456 The wrapped exception object is available in 

457 the :attr:`.orig` attribute. 

458 

459 """ 

460 

461 statement: Optional[str] = None 

462 """The string SQL statement being invoked when this exception occurred.""" 

463 

464 params: Optional[_AnyExecuteParams] = None 

465 """The parameter list being used when this exception occurred.""" 

466 

467 orig: Optional[BaseException] = None 

468 """The original exception that was thrown. 

469 

470 """ 

471 

472 ismulti: Optional[bool] = None 

473 """multi parameter passed to repr_params(). None is meaningful.""" 

474 

475 connection_invalidated: bool = False 

476 

477 def __init__( 

478 self, 

479 message: str, 

480 statement: Optional[str], 

481 params: Optional[_AnyExecuteParams], 

482 orig: Optional[BaseException], 

483 hide_parameters: bool = False, 

484 code: Optional[str] = None, 

485 ismulti: Optional[bool] = None, 

486 ): 

487 SQLAlchemyError.__init__(self, message, code=code) 

488 self.statement = statement 

489 self.params = params 

490 self.orig = orig 

491 self.ismulti = ismulti 

492 self.hide_parameters = hide_parameters 

493 self.detail: List[str] = [] 

494 

495 def add_detail(self, msg: str) -> None: 

496 self.detail.append(msg) 

497 

498 def __reduce__(self) -> Union[str, Tuple[Any, ...]]: 

499 return ( 

500 self.__class__, 

501 ( 

502 self.args[0], 

503 self.statement, 

504 self.params, 

505 self.orig, 

506 self.hide_parameters, 

507 self.__dict__.get("code"), 

508 self.ismulti, 

509 ), 

510 {"detail": self.detail}, 

511 ) 

512 

513 @_preloaded.preload_module("sqlalchemy.sql.util") 

514 def _sql_message(self) -> str: 

515 util = _preloaded.sql_util 

516 

517 details = [self._message()] 

518 if self.statement: 

519 stmt_detail = "[SQL: %s]" % self.statement 

520 details.append(stmt_detail) 

521 if self.params: 

522 if self.hide_parameters: 

523 details.append( 

524 "[SQL parameters hidden due to hide_parameters=True]" 

525 ) 

526 else: 

527 params_repr = util._repr_params( 

528 self.params, 10, ismulti=self.ismulti 

529 ) 

530 details.append("[parameters: %r]" % params_repr) 

531 code_str = self._code_str() 

532 if code_str: 

533 details.append(code_str) 

534 return "\n".join(["(%s)" % det for det in self.detail] + details) 

535 

536 

537class DBAPIError(StatementError): 

538 """Raised when the execution of a database operation fails. 

539 

540 Wraps exceptions raised by the DB-API underlying the 

541 database operation. Driver-specific implementations of the standard 

542 DB-API exception types are wrapped by matching sub-types of SQLAlchemy's 

543 :class:`DBAPIError` when possible. DB-API's ``Error`` type maps to 

544 :class:`DBAPIError` in SQLAlchemy, otherwise the names are identical. Note 

545 that there is no guarantee that different DB-API implementations will 

546 raise the same exception type for any given error condition. 

547 

548 :class:`DBAPIError` features :attr:`~.StatementError.statement` 

549 and :attr:`~.StatementError.params` attributes which supply context 

550 regarding the specifics of the statement which had an issue, for the 

551 typical case when the error was raised within the context of 

552 emitting a SQL statement. 

553 

554 The wrapped exception object is available in the 

555 :attr:`~.StatementError.orig` attribute. Its type and properties are 

556 DB-API implementation specific. 

557 

558 """ 

559 

560 code = "dbapi" 

561 

562 @overload 

563 @classmethod 

564 def instance( 

565 cls, 

566 statement: Optional[str], 

567 params: Optional[_AnyExecuteParams], 

568 orig: Exception, 

569 dbapi_base_err: Type[Exception], 

570 hide_parameters: bool = False, 

571 connection_invalidated: bool = False, 

572 dialect: Optional[Dialect] = None, 

573 ismulti: Optional[bool] = None, 

574 ) -> StatementError: ... 

575 

576 @overload 

577 @classmethod 

578 def instance( 

579 cls, 

580 statement: Optional[str], 

581 params: Optional[_AnyExecuteParams], 

582 orig: DontWrapMixin, 

583 dbapi_base_err: Type[Exception], 

584 hide_parameters: bool = False, 

585 connection_invalidated: bool = False, 

586 dialect: Optional[Dialect] = None, 

587 ismulti: Optional[bool] = None, 

588 ) -> DontWrapMixin: ... 

589 

590 @overload 

591 @classmethod 

592 def instance( 

593 cls, 

594 statement: Optional[str], 

595 params: Optional[_AnyExecuteParams], 

596 orig: BaseException, 

597 dbapi_base_err: Type[Exception], 

598 hide_parameters: bool = False, 

599 connection_invalidated: bool = False, 

600 dialect: Optional[Dialect] = None, 

601 ismulti: Optional[bool] = None, 

602 ) -> BaseException: ... 

603 

604 @classmethod 

605 def instance( 

606 cls, 

607 statement: Optional[str], 

608 params: Optional[_AnyExecuteParams], 

609 orig: Union[BaseException, DontWrapMixin], 

610 dbapi_base_err: Type[Exception], 

611 hide_parameters: bool = False, 

612 connection_invalidated: bool = False, 

613 dialect: Optional[Dialect] = None, 

614 ismulti: Optional[bool] = None, 

615 ) -> Union[BaseException, DontWrapMixin]: 

616 # Don't ever wrap these, just return them directly as if 

617 # DBAPIError didn't exist. 

618 if ( 

619 isinstance(orig, BaseException) and not isinstance(orig, Exception) 

620 ) or isinstance(orig, DontWrapMixin): 

621 return orig 

622 

623 if orig is not None: 

624 # not a DBAPI error, statement is present. 

625 # raise a StatementError 

626 if isinstance(orig, SQLAlchemyError) and statement: 

627 return StatementError( 

628 "(%s.%s) %s" 

629 % ( 

630 orig.__class__.__module__, 

631 orig.__class__.__name__, 

632 orig.args[0], 

633 ), 

634 statement, 

635 params, 

636 orig, 

637 hide_parameters=hide_parameters, 

638 code=orig.code, 

639 ismulti=ismulti, 

640 ) 

641 elif not isinstance(orig, dbapi_base_err) and statement: 

642 return StatementError( 

643 "(%s.%s) %s" 

644 % ( 

645 orig.__class__.__module__, 

646 orig.__class__.__name__, 

647 orig, 

648 ), 

649 statement, 

650 params, 

651 orig, 

652 hide_parameters=hide_parameters, 

653 ismulti=ismulti, 

654 ) 

655 

656 glob = globals() 

657 for super_ in orig.__class__.__mro__: 

658 name = super_.__name__ 

659 if dialect: 

660 name = dialect.dbapi_exception_translation_map.get( 

661 name, name 

662 ) 

663 if name in glob and issubclass(glob[name], DBAPIError): 

664 cls = glob[name] 

665 break 

666 

667 return cls( 

668 statement, 

669 params, 

670 orig, 

671 connection_invalidated=connection_invalidated, 

672 hide_parameters=hide_parameters, 

673 code=cls.code, 

674 ismulti=ismulti, 

675 ) 

676 

677 def __reduce__(self) -> Union[str, Tuple[Any, ...]]: 

678 return ( 

679 self.__class__, 

680 ( 

681 self.statement, 

682 self.params, 

683 self.orig, 

684 self.hide_parameters, 

685 self.connection_invalidated, 

686 self.__dict__.get("code"), 

687 self.ismulti, 

688 ), 

689 {"detail": self.detail}, 

690 ) 

691 

692 def __init__( 

693 self, 

694 statement: Optional[str], 

695 params: Optional[_AnyExecuteParams], 

696 orig: BaseException, 

697 hide_parameters: bool = False, 

698 connection_invalidated: bool = False, 

699 code: Optional[str] = None, 

700 ismulti: Optional[bool] = None, 

701 ): 

702 try: 

703 text = str(orig) 

704 except Exception as e: 

705 text = "Error in str() of DB-API-generated exception: " + str(e) 

706 StatementError.__init__( 

707 self, 

708 "(%s.%s) %s" 

709 % (orig.__class__.__module__, orig.__class__.__name__, text), 

710 statement, 

711 params, 

712 orig, 

713 hide_parameters, 

714 code=code, 

715 ismulti=ismulti, 

716 ) 

717 self.connection_invalidated = connection_invalidated 

718 

719 

720class InterfaceError(DBAPIError): 

721 """Wraps a DB-API InterfaceError.""" 

722 

723 code = "rvf5" 

724 

725 

726class DatabaseError(DBAPIError): 

727 """Wraps a DB-API DatabaseError.""" 

728 

729 code = "4xp6" 

730 

731 

732class DataError(DatabaseError): 

733 """Wraps a DB-API DataError.""" 

734 

735 code = "9h9h" 

736 

737 

738class OperationalError(DatabaseError): 

739 """Wraps a DB-API OperationalError.""" 

740 

741 code = "e3q8" 

742 

743 

744class IntegrityError(DatabaseError): 

745 """Wraps a DB-API IntegrityError.""" 

746 

747 code = "gkpj" 

748 

749 

750class InternalError(DatabaseError): 

751 """Wraps a DB-API InternalError.""" 

752 

753 code = "2j85" 

754 

755 

756class ProgrammingError(DatabaseError): 

757 """Wraps a DB-API ProgrammingError.""" 

758 

759 code = "f405" 

760 

761 

762class NotSupportedError(DatabaseError): 

763 """Wraps a DB-API NotSupportedError.""" 

764 

765 code = "tw8g" 

766 

767 

768# Warnings 

769 

770 

771class SATestSuiteWarning(Warning): 

772 """warning for a condition detected during tests that is non-fatal 

773 

774 Currently outside of SAWarning so that we can work around tools like 

775 Alembic doing the wrong thing with warnings. 

776 

777 """ 

778 

779 

780class SADeprecationWarning(HasDescriptionCode, DeprecationWarning): 

781 """Issued for usage of deprecated APIs.""" 

782 

783 deprecated_since: Optional[str] = None 

784 "Indicates the version that started raising this deprecation warning" 

785 

786 

787class Base20DeprecationWarning(SADeprecationWarning): 

788 """Issued for usage of APIs specifically deprecated or legacy in 

789 SQLAlchemy 2.0. 

790 

791 .. seealso:: 

792 

793 :ref:`error_b8d9`. 

794 

795 :ref:`deprecation_20_mode` 

796 

797 """ 

798 

799 deprecated_since: Optional[str] = "1.4" 

800 "Indicates the version that started raising this deprecation warning" 

801 

802 def __str__(self) -> str: 

803 return ( 

804 super().__str__() 

805 + " (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)" 

806 ) 

807 

808 

809class LegacyAPIWarning(Base20DeprecationWarning): 

810 """indicates an API that is in 'legacy' status, a long term deprecation.""" 

811 

812 

813class MovedIn20Warning(Base20DeprecationWarning): 

814 """Subtype of RemovedIn20Warning to indicate an API that moved only.""" 

815 

816 

817class SAPendingDeprecationWarning(PendingDeprecationWarning): 

818 """A similar warning as :class:`_exc.SADeprecationWarning`, this warning 

819 is not used in modern versions of SQLAlchemy. 

820 

821 """ 

822 

823 deprecated_since: Optional[str] = None 

824 "Indicates the version that started raising this deprecation warning" 

825 

826 

827class SAWarning(HasDescriptionCode, RuntimeWarning): 

828 """Issued at runtime.""" 

829 

830 _what_are_we = "warning"