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

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

253 statements  

1# exc.py 

2# Copyright (C) 2005-2025 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 EmulatedDBAPIException(Exception): 

119 """Serves as the base of the DBAPI ``Error`` class for dialects where 

120 a DBAPI exception hierrchy needs to be emulated. 

121 

122 The current example is the asyncpg dialect. 

123 

124 .. versionadded:: 2.1 

125 

126 """ 

127 

128 orig: Exception | None 

129 

130 def __init__(self, message: str, orig: Exception | None = None): 

131 # we accept None for Exception since all DBAPI.Error objects 

132 # need to support construction with a message alone 

133 super().__init__(message) 

134 self.orig = orig 

135 

136 @property 

137 def driver_exception(self) -> Exception: 

138 """The original driver exception that was raised. 

139 

140 This exception object will always originate from outside of 

141 SQLAlchemy. 

142 

143 """ 

144 

145 if self.orig is None: 

146 raise ValueError( 

147 "No original exception is present. Was this " 

148 "EmulatedDBAPIException constructed without a driver error?" 

149 ) 

150 return self.orig 

151 

152 def __reduce__(self) -> Any: 

153 return self.__class__, (self.args[0], self.orig) 

154 

155 

156class ArgumentError(SQLAlchemyError): 

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

158 

159 This error generally corresponds to construction time state errors. 

160 

161 """ 

162 

163 

164class DuplicateColumnError(ArgumentError): 

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

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

167 

168 .. versionadded:: 2.0.0b4 

169 

170 """ 

171 

172 

173class ObjectNotExecutableError(ArgumentError): 

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

175 executed as SQL. 

176 

177 """ 

178 

179 def __init__(self, target: Any): 

180 super().__init__(f"Not an executable object: {target!r}") 

181 self.target = target 

182 

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

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

185 

186 

187class NoSuchModuleError(ArgumentError): 

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

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

190 

191 

192class NoForeignKeysError(ArgumentError): 

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

194 during a join.""" 

195 

196 

197class AmbiguousForeignKeysError(ArgumentError): 

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

199 between two selectables during a join.""" 

200 

201 

202class ConstraintColumnNotFoundError(ArgumentError): 

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

204 is not present in the table being constrained. 

205 

206 .. versionadded:: 2.0 

207 

208 """ 

209 

210 

211class CircularDependencyError(SQLAlchemyError): 

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

213 

214 There are two scenarios where this error occurs: 

215 

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

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

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

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

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

221 this cycle. 

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

223 :class:`_schema.ForeignKey` 

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

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

226 see :ref:`use_alter`. 

227 

228 """ 

229 

230 def __init__( 

231 self, 

232 message: str, 

233 cycles: Any, 

234 edges: Any, 

235 msg: Optional[str] = None, 

236 code: Optional[str] = None, 

237 ): 

238 if msg is None: 

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

240 else: 

241 message = msg 

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

243 self.cycles = cycles 

244 self.edges = edges 

245 

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

247 return ( 

248 self.__class__, 

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

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

251 ) 

252 

253 

254class CompileError(SQLAlchemyError): 

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

256 

257 

258class UnsupportedCompilationError(CompileError): 

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

260 

261 .. seealso:: 

262 

263 :ref:`faq_sql_expression_string` 

264 

265 :ref:`error_l7de` 

266 """ 

267 

268 code = "l7de" 

269 

270 def __init__( 

271 self, 

272 compiler: Union[Compiled, TypeCompiler], 

273 element_type: Type[ClauseElement], 

274 message: Optional[str] = None, 

275 ): 

276 super().__init__( 

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

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

279 ) 

280 self.compiler = compiler 

281 self.element_type = element_type 

282 self.message = message 

283 

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

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

286 

287 

288class IdentifierError(SQLAlchemyError): 

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

290 

291 

292class DisconnectionError(SQLAlchemyError): 

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

294 

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

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

297 event so that the host pool 

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

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

300 regarding the connection attempt. 

301 

302 """ 

303 

304 invalidate_pool: bool = False 

305 

306 

307class InvalidatePoolError(DisconnectionError): 

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

309 

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

311 disconnect situation encountered on the connection probably means the 

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

313 

314 This exception will be handled otherwise the same way as 

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

316 before giving up. 

317 

318 """ 

319 

320 invalidate_pool: bool = True 

321 

322 

323class TimeoutError(SQLAlchemyError): # noqa 

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

325 

326 

327class InvalidRequestError(SQLAlchemyError): 

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

329 

330 This error generally corresponds to runtime state errors. 

331 

332 """ 

333 

334 

335class IllegalStateChangeError(InvalidRequestError): 

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

337 of some kind. 

338 

339 .. versionadded:: 2.0 

340 

341 """ 

342 

343 

344class NoInspectionAvailable(InvalidRequestError): 

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

346 no context for inspection.""" 

347 

348 

349class PendingRollbackError(InvalidRequestError): 

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

351 continuing. 

352 

353 .. versionadded:: 1.4 

354 

355 """ 

356 

357 

358class ResourceClosedError(InvalidRequestError): 

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

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

361 

362 

363class NoSuchColumnError(InvalidRequestError, KeyError): 

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

365 

366 

367class AmbiguousColumnError(InvalidRequestError): 

368 """Raised when a column/attribute name is ambiguous across multiple 

369 entities. 

370 

371 This can occur when using :meth:`_sql.Select.filter_by` with multiple 

372 joined tables that have columns with the same name. 

373 

374 .. versionadded:: 2.1 

375 

376 """ 

377 

378 

379class NoResultFound(InvalidRequestError): 

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

381 

382 

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

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

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

386 

387 

388 """ 

389 

390 

391class MultipleResultsFound(InvalidRequestError): 

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

393 

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

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

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

397 

398 

399 """ 

400 

401 

402class NoReferenceError(InvalidRequestError): 

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

404 

405 table_name: str 

406 

407 

408class AwaitRequired(InvalidRequestError): 

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

410 was awaited when it required one. 

411 

412 """ 

413 

414 code = "xd1r" 

415 

416 

417class MissingGreenlet(InvalidRequestError): 

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

419 the greenlet spawn context. 

420 

421 """ 

422 

423 code = "xd2s" 

424 

425 

426class NoReferencedTableError(NoReferenceError): 

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

428 located. 

429 

430 """ 

431 

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

433 NoReferenceError.__init__(self, message) 

434 self.table_name = tname 

435 

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

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

438 

439 

440class NoReferencedColumnError(NoReferenceError): 

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

442 located. 

443 

444 """ 

445 

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

447 NoReferenceError.__init__(self, message) 

448 self.table_name = tname 

449 self.column_name = cname 

450 

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

452 return ( 

453 self.__class__, 

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

455 ) 

456 

457 

458class NoSuchTableError(InvalidRequestError): 

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

460 

461 

462class UnreflectableTableError(InvalidRequestError): 

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

464 

465 

466class UnboundExecutionError(InvalidRequestError): 

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

468 

469 

470class DontWrapMixin: 

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

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

473 emitted within the process of executing a statement. 

474 

475 E.g.:: 

476 

477 from sqlalchemy.exc import DontWrapMixin 

478 

479 

480 class MyCustomException(Exception, DontWrapMixin): 

481 pass 

482 

483 

484 class MySpecialType(TypeDecorator): 

485 impl = String 

486 

487 def process_bind_param(self, value, dialect): 

488 if value == "invalid": 

489 raise MyCustomException("invalid!") 

490 

491 """ 

492 

493 

494class StatementError(SQLAlchemyError): 

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

496 

497 :class:`StatementError` wraps the exception raised 

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

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

500 the specifics of the statement which had an issue. 

501 

502 The wrapped exception object is available in 

503 the :attr:`.orig` attribute. 

504 

505 """ 

506 

507 statement: Optional[str] = None 

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

509 

510 params: Optional[_AnyExecuteParams] = None 

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

512 

513 orig: Optional[BaseException] = None 

514 """The original exception that was thrown. 

515 

516 .. seealso:: 

517 

518 :attr:`.DBAPIError.driver_exception` - a more specific attribute that 

519 is guaranteed to return the exception object raised by the third 

520 party driver in use, even when using asyncio. 

521 

522 """ 

523 

524 ismulti: Optional[bool] = None 

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

526 

527 connection_invalidated: bool = False 

528 

529 def __init__( 

530 self, 

531 message: str, 

532 statement: Optional[str], 

533 params: Optional[_AnyExecuteParams], 

534 orig: Optional[BaseException], 

535 hide_parameters: bool = False, 

536 code: Optional[str] = None, 

537 ismulti: Optional[bool] = None, 

538 ): 

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

540 self.statement = statement 

541 self.params = params 

542 self.orig = orig 

543 self.ismulti = ismulti 

544 self.hide_parameters = hide_parameters 

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

546 

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

548 self.detail.append(msg) 

549 

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

551 return ( 

552 self.__class__, 

553 ( 

554 self.args[0], 

555 self.statement, 

556 self.params, 

557 self.orig, 

558 self.hide_parameters, 

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

560 self.ismulti, 

561 ), 

562 {"detail": self.detail}, 

563 ) 

564 

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

566 def _sql_message(self) -> str: 

567 util = _preloaded.sql_util 

568 

569 details = [self._message()] 

570 if self.statement: 

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

572 details.append(stmt_detail) 

573 if self.params: 

574 if self.hide_parameters: 

575 details.append( 

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

577 ) 

578 else: 

579 params_repr = util._repr_params( 

580 self.params, 10, ismulti=self.ismulti 

581 ) 

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

583 code_str = self._code_str() 

584 if code_str: 

585 details.append(code_str) 

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

587 

588 

589class DBAPIError(StatementError): 

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

591 

592 Wraps exceptions raised by the DB-API underlying the 

593 database operation. Driver-specific implementations of the standard 

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

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

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

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

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

599 

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

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

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

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

604 emitting a SQL statement. 

605 

606 The wrapped exception object is available in the 

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

608 DB-API implementation specific. 

609 

610 """ 

611 

612 code = "dbapi" 

613 

614 orig: Optional[Exception] 

615 

616 @overload 

617 @classmethod 

618 def instance( 

619 cls, 

620 statement: Optional[str], 

621 params: Optional[_AnyExecuteParams], 

622 orig: Exception, 

623 dbapi_base_err: Type[Exception], 

624 hide_parameters: bool = False, 

625 connection_invalidated: bool = False, 

626 dialect: Optional[Dialect] = None, 

627 ismulti: Optional[bool] = None, 

628 ) -> StatementError: ... 

629 

630 @overload 

631 @classmethod 

632 def instance( 

633 cls, 

634 statement: Optional[str], 

635 params: Optional[_AnyExecuteParams], 

636 orig: DontWrapMixin, 

637 dbapi_base_err: Type[Exception], 

638 hide_parameters: bool = False, 

639 connection_invalidated: bool = False, 

640 dialect: Optional[Dialect] = None, 

641 ismulti: Optional[bool] = None, 

642 ) -> DontWrapMixin: ... 

643 

644 @overload 

645 @classmethod 

646 def instance( 

647 cls, 

648 statement: Optional[str], 

649 params: Optional[_AnyExecuteParams], 

650 orig: BaseException, 

651 dbapi_base_err: Type[Exception], 

652 hide_parameters: bool = False, 

653 connection_invalidated: bool = False, 

654 dialect: Optional[Dialect] = None, 

655 ismulti: Optional[bool] = None, 

656 ) -> BaseException: ... 

657 

658 @classmethod 

659 def instance( 

660 cls, 

661 statement: Optional[str], 

662 params: Optional[_AnyExecuteParams], 

663 orig: Union[BaseException, DontWrapMixin], 

664 dbapi_base_err: Type[Exception], 

665 hide_parameters: bool = False, 

666 connection_invalidated: bool = False, 

667 dialect: Optional[Dialect] = None, 

668 ismulti: Optional[bool] = None, 

669 ) -> Union[BaseException, DontWrapMixin]: 

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

671 # DBAPIError didn't exist. 

672 if ( 

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

674 ) or isinstance(orig, DontWrapMixin): 

675 return orig 

676 

677 if orig is not None: 

678 # not a DBAPI error, statement is present. 

679 # raise a StatementError 

680 if isinstance(orig, SQLAlchemyError) and statement: 

681 return StatementError( 

682 "(%s.%s) %s" 

683 % ( 

684 orig.__class__.__module__, 

685 orig.__class__.__name__, 

686 orig.args[0], 

687 ), 

688 statement, 

689 params, 

690 orig, 

691 hide_parameters=hide_parameters, 

692 code=orig.code, 

693 ismulti=ismulti, 

694 ) 

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

696 return StatementError( 

697 "(%s.%s) %s" 

698 % ( 

699 orig.__class__.__module__, 

700 orig.__class__.__name__, 

701 orig, 

702 ), 

703 statement, 

704 params, 

705 orig, 

706 hide_parameters=hide_parameters, 

707 ismulti=ismulti, 

708 ) 

709 

710 glob = globals() 

711 for super_ in orig.__class__.__mro__: 

712 name = super_.__name__ 

713 if dialect: 

714 name = dialect.dbapi_exception_translation_map.get( 

715 name, name 

716 ) 

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

718 cls = glob[name] 

719 break 

720 

721 return cls( 

722 statement, 

723 params, 

724 orig, 

725 connection_invalidated=connection_invalidated, 

726 hide_parameters=hide_parameters, 

727 code=cls.code, 

728 ismulti=ismulti, 

729 ) 

730 

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

732 return ( 

733 self.__class__, 

734 ( 

735 self.statement, 

736 self.params, 

737 self.orig, 

738 self.hide_parameters, 

739 self.connection_invalidated, 

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

741 self.ismulti, 

742 ), 

743 {"detail": self.detail}, 

744 ) 

745 

746 def __init__( 

747 self, 

748 statement: Optional[str], 

749 params: Optional[_AnyExecuteParams], 

750 orig: BaseException, 

751 hide_parameters: bool = False, 

752 connection_invalidated: bool = False, 

753 code: Optional[str] = None, 

754 ismulti: Optional[bool] = None, 

755 ): 

756 try: 

757 text = str(orig) 

758 except Exception as e: 

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

760 StatementError.__init__( 

761 self, 

762 "(%s.%s) %s" 

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

764 statement, 

765 params, 

766 orig, 

767 hide_parameters, 

768 code=code, 

769 ismulti=ismulti, 

770 ) 

771 self.connection_invalidated = connection_invalidated 

772 

773 @property 

774 def driver_exception(self) -> Exception: 

775 """The exception object originating from the driver (DBAPI) outside 

776 of SQLAlchemy. 

777 

778 In the case of some asyncio dialects, special steps are taken to 

779 resolve the exception to what the third party driver has raised, even 

780 for SQLAlchemy dialects that include an "emulated" DBAPI exception 

781 hierarchy. 

782 

783 For non-asyncio dialects, this attribute will be the same attribute 

784 as the :attr:`.StatementError.orig` attribute. 

785 

786 For an asyncio dialect provided by SQLAlchemy, depending on if the 

787 dialect provides an "emulated" exception hierarchy or if the underlying 

788 DBAPI raises DBAPI-style exceptions, it will refer to either the 

789 :attr:`.EmulatedDBAPIException.driver_exception` attribute on the 

790 :class:`.EmulatedDBAPIException` that's thrown (such as when using 

791 asyncpg), or to the actual exception object thrown by the 

792 third party driver. 

793 

794 .. versionadded:: 2.1 

795 

796 """ 

797 

798 if self.orig is None: 

799 raise ValueError( 

800 "No original exception is present. Was this " 

801 "DBAPIError constructed without a driver error?" 

802 ) 

803 

804 if isinstance(self.orig, EmulatedDBAPIException): 

805 return self.orig.driver_exception 

806 else: 

807 return self.orig 

808 

809 

810class InterfaceError(DBAPIError): 

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

812 

813 code = "rvf5" 

814 

815 

816class DatabaseError(DBAPIError): 

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

818 

819 code = "4xp6" 

820 

821 

822class DataError(DatabaseError): 

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

824 

825 code = "9h9h" 

826 

827 

828class OperationalError(DatabaseError): 

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

830 

831 code = "e3q8" 

832 

833 

834class IntegrityError(DatabaseError): 

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

836 

837 code = "gkpj" 

838 

839 

840class InternalError(DatabaseError): 

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

842 

843 code = "2j85" 

844 

845 

846class ProgrammingError(DatabaseError): 

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

848 

849 code = "f405" 

850 

851 

852class NotSupportedError(DatabaseError): 

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

854 

855 code = "tw8g" 

856 

857 

858# Warnings 

859 

860 

861class SATestSuiteWarning(Warning): 

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

863 

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

865 Alembic doing the wrong thing with warnings. 

866 

867 """ 

868 

869 

870class SADeprecationWarning(HasDescriptionCode, DeprecationWarning): 

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

872 

873 deprecated_since: Optional[str] = None 

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

875 

876 

877class Base20DeprecationWarning(SADeprecationWarning): 

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

879 SQLAlchemy 2.0. 

880 

881 .. seealso:: 

882 

883 :ref:`error_b8d9`. 

884 

885 :ref:`deprecation_20_mode` 

886 

887 """ 

888 

889 deprecated_since: Optional[str] = "1.4" 

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

891 

892 def __str__(self) -> str: 

893 return ( 

894 super().__str__() 

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

896 ) 

897 

898 

899class LegacyAPIWarning(Base20DeprecationWarning): 

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

901 

902 

903class MovedIn20Warning(Base20DeprecationWarning): 

904 """Subtype of Base20DeprecationWarning to indicate an API that moved 

905 only. 

906 """ 

907 

908 

909class SAPendingDeprecationWarning(PendingDeprecationWarning): 

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

911 is not used in modern versions of SQLAlchemy. 

912 

913 """ 

914 

915 deprecated_since: Optional[str] = None 

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

917 

918 

919class SAWarning(HasDescriptionCode, RuntimeWarning): 

920 """Issued at runtime.""" 

921 

922 _what_are_we = "warning"