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-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 

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""" 

15 

16from __future__ import annotations 

17 

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 

26 

27from .util import compat 

28from .util import preloaded as _preloaded 

29 

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 

36 

37if typing.TYPE_CHECKING: 

38 _version_token: str 

39else: 

40 # set by __init__.py 

41 _version_token = None 

42 

43 

44class HasDescriptionCode: 

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

46 

47 code: Optional[str] = None 

48 

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) 

54 

55 _what_are_we = "error" 

56 

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 ) 

65 

66 def __str__(self) -> str: 

67 message = super().__str__() 

68 if self.code: 

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

70 return message 

71 

72 

73class SQLAlchemyError(HasDescriptionCode, Exception): 

74 """Generic error class.""" 

75 

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 

88 

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

90 arg_text = self.args[0] 

91 

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) 

99 

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) 

106 

107 def _sql_message(self) -> str: 

108 message = self._message() 

109 

110 if self.code: 

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

112 

113 return message 

114 

115 def __str__(self) -> str: 

116 return self._sql_message() 

117 

118 

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. 

122 

123 The current example is the asyncpg dialect. 

124 

125 .. versionadded:: 2.1 

126 

127 """ 

128 

129 orig: Exception | None 

130 

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 

136 

137 @property 

138 def driver_exception(self) -> Exception: 

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

140 

141 This exception object will always originate from outside of 

142 SQLAlchemy. 

143 

144 """ 

145 

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 

152 

153 def __reduce__(self) -> Any: 

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

155 

156 

157class ArgumentError(SQLAlchemyError): 

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

159 

160 This error generally corresponds to construction time state errors. 

161 

162 """ 

163 

164 

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. 

168 

169 .. versionadded:: 2.0.0b4 

170 

171 """ 

172 

173 

174class ObjectNotExecutableError(ArgumentError): 

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

176 executed as SQL. 

177 

178 """ 

179 

180 def __init__(self, target: Any): 

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

182 self.target = target 

183 

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

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

186 

187 

188class NoSuchModuleError(ArgumentError): 

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

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

191 

192 

193class NoForeignKeysError(ArgumentError): 

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

195 during a join.""" 

196 

197 

198class AmbiguousForeignKeysError(ArgumentError): 

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

200 between two selectables during a join.""" 

201 

202 

203class ConstraintColumnNotFoundError(ArgumentError): 

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

205 is not present in the table being constrained. 

206 

207 .. versionadded:: 2.0 

208 

209 """ 

210 

211 

212class CircularDependencyError(SQLAlchemyError): 

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

214 

215 There are two scenarios where this error occurs: 

216 

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`. 

228 

229 """ 

230 

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 

246 

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 ) 

253 

254 

255class CompileError(SQLAlchemyError): 

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

257 

258 

259class UnsupportedCompilationError(CompileError): 

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

261 

262 .. seealso:: 

263 

264 :ref:`faq_sql_expression_string` 

265 

266 :ref:`error_l7de` 

267 """ 

268 

269 code = "l7de" 

270 

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 

284 

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

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

287 

288 

289class IdentifierError(SQLAlchemyError): 

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

291 

292 

293class DisconnectionError(SQLAlchemyError): 

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

295 

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. 

302 

303 """ 

304 

305 invalidate_pool: bool = False 

306 

307 

308class InvalidatePoolError(DisconnectionError): 

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

310 

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. 

314 

315 This exception will be handled otherwise the same way as 

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

317 before giving up. 

318 

319 """ 

320 

321 invalidate_pool: bool = True 

322 

323 

324class TimeoutError(SQLAlchemyError): # noqa 

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

326 

327 

328class InvalidRequestError(SQLAlchemyError): 

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

330 

331 This error generally corresponds to runtime state errors. 

332 

333 """ 

334 

335 

336class IllegalStateChangeError(InvalidRequestError): 

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

338 of some kind. 

339 

340 .. versionadded:: 2.0 

341 

342 """ 

343 

344 

345class NoInspectionAvailable(InvalidRequestError): 

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

347 no context for inspection.""" 

348 

349 

350class PendingRollbackError(InvalidRequestError): 

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

352 continuing. 

353 

354 .. versionadded:: 1.4 

355 

356 """ 

357 

358 

359class ResourceClosedError(InvalidRequestError): 

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

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

362 

363 

364class NoSuchColumnError(InvalidRequestError, KeyError): 

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

366 

367 

368class AmbiguousColumnError(InvalidRequestError): 

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

370 entities. 

371 

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

373 joined tables that have columns with the same name. 

374 

375 .. versionadded:: 2.1 

376 

377 """ 

378 

379 

380class NoResultFound(InvalidRequestError): 

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

382 

383 

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

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

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

387 

388 

389 """ 

390 

391 

392class MultipleResultsFound(InvalidRequestError): 

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

394 

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

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

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

398 

399 

400 """ 

401 

402 

403class NoReferenceError(InvalidRequestError): 

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

405 

406 table_name: str 

407 

408 

409class AwaitRequired(InvalidRequestError): 

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

411 was awaited when it required one. 

412 

413 """ 

414 

415 code = "xd1r" 

416 

417 

418class MissingGreenlet(InvalidRequestError): 

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

420 the greenlet spawn context. 

421 

422 """ 

423 

424 code = "xd2s" 

425 

426 

427class NoReferencedTableError(NoReferenceError): 

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

429 located. 

430 

431 """ 

432 

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

434 NoReferenceError.__init__(self, message) 

435 self.table_name = tname 

436 

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

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

439 

440 

441class NoReferencedColumnError(NoReferenceError): 

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

443 located. 

444 

445 """ 

446 

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

448 NoReferenceError.__init__(self, message) 

449 self.table_name = tname 

450 self.column_name = cname 

451 

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

453 return ( 

454 self.__class__, 

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

456 ) 

457 

458 

459class NoSuchTableError(InvalidRequestError): 

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

461 

462 

463class UnreflectableTableError(InvalidRequestError): 

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

465 

466 

467class UnboundExecutionError(InvalidRequestError): 

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

469 

470 

471class DontWrapMixin: 

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

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

474 emitted within the process of executing a statement. 

475 

476 E.g.:: 

477 

478 from sqlalchemy.exc import DontWrapMixin 

479 

480 

481 class MyCustomException(Exception, DontWrapMixin): 

482 pass 

483 

484 

485 class MySpecialType(TypeDecorator): 

486 impl = String 

487 

488 def process_bind_param(self, value, dialect): 

489 if value == "invalid": 

490 raise MyCustomException("invalid!") 

491 

492 """ 

493 

494 

495class StatementError(SQLAlchemyError): 

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

497 

498 :class:`StatementError` wraps the exception raised 

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

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

501 the specifics of the statement which had an issue. 

502 

503 The wrapped exception object is available in 

504 the :attr:`.orig` attribute. 

505 

506 """ 

507 

508 statement: Optional[str] = None 

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

510 

511 params: Optional[_AnyExecuteParams] = None 

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

513 

514 orig: Optional[BaseException] = None 

515 """The original exception that was thrown. 

516 

517 .. seealso:: 

518 

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

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

521 party driver in use, even when using asyncio. 

522 

523 """ 

524 

525 ismulti: Optional[bool] = None 

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

527 

528 connection_invalidated: bool = False 

529 

530 def __init__( 

531 self, 

532 message: str, 

533 statement: Optional[str], 

534 params: Optional[_AnyExecuteParams], 

535 orig: Optional[BaseException], 

536 hide_parameters: bool = False, 

537 code: Optional[str] = None, 

538 ismulti: Optional[bool] = None, 

539 ): 

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

541 self.statement = statement 

542 self.params = params 

543 self.orig = orig 

544 self.ismulti = ismulti 

545 self.hide_parameters = hide_parameters 

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

547 

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

549 self.detail.append(msg) 

550 

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

552 return ( 

553 self.__class__, 

554 ( 

555 self.args[0], 

556 self.statement, 

557 self.params, 

558 self.orig, 

559 self.hide_parameters, 

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

561 self.ismulti, 

562 ), 

563 {"detail": self.detail}, 

564 ) 

565 

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

567 def _sql_message(self) -> str: 

568 util = _preloaded.sql_util 

569 

570 details = [self._message()] 

571 if self.statement: 

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

573 details.append(stmt_detail) 

574 if self.params: 

575 if self.hide_parameters: 

576 details.append( 

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

578 ) 

579 else: 

580 params_repr = util._repr_params( 

581 self.params, 10, ismulti=self.ismulti 

582 ) 

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

584 code_str = self._code_str() 

585 if code_str: 

586 details.append(code_str) 

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

588 

589 

590class DBAPIError(StatementError): 

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

592 

593 Wraps exceptions raised by the DB-API underlying the 

594 database operation. Driver-specific implementations of the standard 

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

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

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

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

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

600 

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

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

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

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

605 emitting a SQL statement. 

606 

607 The wrapped exception object is available in the 

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

609 DB-API implementation specific. 

610 

611 """ 

612 

613 code = "dbapi" 

614 

615 orig: Optional[Exception] 

616 

617 @overload 

618 @classmethod 

619 def instance( 

620 cls, 

621 statement: Optional[str], 

622 params: Optional[_AnyExecuteParams], 

623 orig: Exception, 

624 dbapi_base_err: Type[Exception], 

625 hide_parameters: bool = False, 

626 connection_invalidated: bool = False, 

627 dialect: Optional[Dialect] = None, 

628 ismulti: Optional[bool] = None, 

629 ) -> StatementError: ... 

630 

631 @overload 

632 @classmethod 

633 def instance( 

634 cls, 

635 statement: Optional[str], 

636 params: Optional[_AnyExecuteParams], 

637 orig: DontWrapMixin, 

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 ) -> DontWrapMixin: ... 

644 

645 @overload 

646 @classmethod 

647 def instance( 

648 cls, 

649 statement: Optional[str], 

650 params: Optional[_AnyExecuteParams], 

651 orig: BaseException, 

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 ) -> BaseException: ... 

658 

659 @classmethod 

660 def instance( 

661 cls, 

662 statement: Optional[str], 

663 params: Optional[_AnyExecuteParams], 

664 orig: Union[BaseException, DontWrapMixin], 

665 dbapi_base_err: Type[Exception], 

666 hide_parameters: bool = False, 

667 connection_invalidated: bool = False, 

668 dialect: Optional[Dialect] = None, 

669 ismulti: Optional[bool] = None, 

670 ) -> Union[BaseException, DontWrapMixin]: 

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

672 # DBAPIError didn't exist. 

673 if ( 

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

675 ) or isinstance(orig, DontWrapMixin): 

676 return orig 

677 

678 if orig is not None: 

679 # not a DBAPI error, statement is present. 

680 # raise a StatementError 

681 if isinstance(orig, SQLAlchemyError) and statement: 

682 return StatementError( 

683 "(%s.%s) %s" 

684 % ( 

685 orig.__class__.__module__, 

686 orig.__class__.__name__, 

687 orig.args[0], 

688 ), 

689 statement, 

690 params, 

691 orig, 

692 hide_parameters=hide_parameters, 

693 code=orig.code, 

694 ismulti=ismulti, 

695 ) 

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

697 return StatementError( 

698 "(%s.%s) %s" 

699 % ( 

700 orig.__class__.__module__, 

701 orig.__class__.__name__, 

702 orig, 

703 ), 

704 statement, 

705 params, 

706 orig, 

707 hide_parameters=hide_parameters, 

708 ismulti=ismulti, 

709 ) 

710 

711 glob = globals() 

712 for super_ in orig.__class__.__mro__: 

713 name = super_.__name__ 

714 if dialect: 

715 name = dialect.dbapi_exception_translation_map.get( 

716 name, name 

717 ) 

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

719 cls = glob[name] 

720 break 

721 

722 return cls( 

723 statement, 

724 params, 

725 orig, 

726 connection_invalidated=connection_invalidated, 

727 hide_parameters=hide_parameters, 

728 code=cls.code, 

729 ismulti=ismulti, 

730 ) 

731 

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

733 return ( 

734 self.__class__, 

735 ( 

736 self.statement, 

737 self.params, 

738 self.orig, 

739 self.hide_parameters, 

740 self.connection_invalidated, 

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

742 self.ismulti, 

743 ), 

744 {"detail": self.detail}, 

745 ) 

746 

747 def __init__( 

748 self, 

749 statement: Optional[str], 

750 params: Optional[_AnyExecuteParams], 

751 orig: BaseException, 

752 hide_parameters: bool = False, 

753 connection_invalidated: bool = False, 

754 code: Optional[str] = None, 

755 ismulti: Optional[bool] = None, 

756 ): 

757 try: 

758 text = str(orig) 

759 except Exception as e: 

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

761 StatementError.__init__( 

762 self, 

763 "(%s.%s) %s" 

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

765 statement, 

766 params, 

767 orig, 

768 hide_parameters, 

769 code=code, 

770 ismulti=ismulti, 

771 ) 

772 self.connection_invalidated = connection_invalidated 

773 

774 @property 

775 def driver_exception(self) -> Exception: 

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

777 of SQLAlchemy. 

778 

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

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

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

782 hierarchy. 

783 

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

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

786 

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

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

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

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

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

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

793 third party driver. 

794 

795 .. versionadded:: 2.1 

796 

797 """ 

798 

799 if self.orig is None: 

800 raise ValueError( 

801 "No original exception is present. Was this " 

802 "DBAPIError constructed without a driver error?" 

803 ) 

804 

805 if isinstance(self.orig, EmulatedDBAPIException): 

806 return self.orig.driver_exception 

807 else: 

808 return self.orig 

809 

810 

811class InterfaceError(DBAPIError): 

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

813 

814 code = "rvf5" 

815 

816 

817class DatabaseError(DBAPIError): 

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

819 

820 code = "4xp6" 

821 

822 

823class DataError(DatabaseError): 

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

825 

826 code = "9h9h" 

827 

828 

829class OperationalError(DatabaseError): 

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

831 

832 code = "e3q8" 

833 

834 

835class IntegrityError(DatabaseError): 

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

837 

838 code = "gkpj" 

839 

840 

841class InternalError(DatabaseError): 

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

843 

844 code = "2j85" 

845 

846 

847class ProgrammingError(DatabaseError): 

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

849 

850 code = "f405" 

851 

852 

853class NotSupportedError(DatabaseError): 

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

855 

856 code = "tw8g" 

857 

858 

859# Warnings 

860 

861 

862class SATestSuiteWarning(Warning): 

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

864 

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

866 Alembic doing the wrong thing with warnings. 

867 

868 """ 

869 

870 

871class SADeprecationWarning(HasDescriptionCode, DeprecationWarning): 

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

873 

874 deprecated_since: Optional[str] = None 

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

876 

877 

878class Base20DeprecationWarning(SADeprecationWarning): 

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

880 SQLAlchemy 2.0. 

881 

882 .. seealso:: 

883 

884 :ref:`error_b8d9`. 

885 

886 :ref:`deprecation_20_mode` 

887 

888 """ 

889 

890 deprecated_since: Optional[str] = "1.4" 

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

892 

893 def __str__(self) -> str: 

894 return ( 

895 super().__str__() 

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

897 ) 

898 

899 

900class LegacyAPIWarning(Base20DeprecationWarning): 

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

902 

903 

904class MovedIn20Warning(Base20DeprecationWarning): 

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

906 only. 

907 """ 

908 

909 

910class SAPendingDeprecationWarning(PendingDeprecationWarning): 

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

912 is not used in modern versions of SQLAlchemy. 

913 

914 """ 

915 

916 deprecated_since: Optional[str] = None 

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

918 

919 

920class SAWarning(HasDescriptionCode, RuntimeWarning): 

921 """Issued at runtime.""" 

922 

923 _what_are_we = "warning"