summaryrefslogtreecommitdiff
path: root/venv/lib/python3.11/site-packages/sqlalchemy/engine/events.py
diff options
context:
space:
mode:
authorcyfraeviolae <cyfraeviolae>2024-04-03 03:17:55 -0400
committercyfraeviolae <cyfraeviolae>2024-04-03 03:17:55 -0400
commit12cf076118570eebbff08c6b3090e0d4798447a1 (patch)
tree3ba25e17e3c3a5e82316558ba3864b955919ff72 /venv/lib/python3.11/site-packages/sqlalchemy/engine/events.py
parentc45662ff3923b34614ddcc8feb9195541166dcc5 (diff)
no venv
Diffstat (limited to 'venv/lib/python3.11/site-packages/sqlalchemy/engine/events.py')
-rw-r--r--venv/lib/python3.11/site-packages/sqlalchemy/engine/events.py951
1 files changed, 0 insertions, 951 deletions
diff --git a/venv/lib/python3.11/site-packages/sqlalchemy/engine/events.py b/venv/lib/python3.11/site-packages/sqlalchemy/engine/events.py
deleted file mode 100644
index b8e8936..0000000
--- a/venv/lib/python3.11/site-packages/sqlalchemy/engine/events.py
+++ /dev/null
@@ -1,951 +0,0 @@
-# engine/events.py
-# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
-# <see AUTHORS file>
-#
-# This module is part of SQLAlchemy and is released under
-# the MIT License: https://www.opensource.org/licenses/mit-license.php
-
-
-from __future__ import annotations
-
-import typing
-from typing import Any
-from typing import Dict
-from typing import Optional
-from typing import Tuple
-from typing import Type
-from typing import Union
-
-from .base import Connection
-from .base import Engine
-from .interfaces import ConnectionEventsTarget
-from .interfaces import DBAPIConnection
-from .interfaces import DBAPICursor
-from .interfaces import Dialect
-from .. import event
-from .. import exc
-from ..util.typing import Literal
-
-if typing.TYPE_CHECKING:
- from .interfaces import _CoreMultiExecuteParams
- from .interfaces import _CoreSingleExecuteParams
- from .interfaces import _DBAPIAnyExecuteParams
- from .interfaces import _DBAPIMultiExecuteParams
- from .interfaces import _DBAPISingleExecuteParams
- from .interfaces import _ExecuteOptions
- from .interfaces import ExceptionContext
- from .interfaces import ExecutionContext
- from .result import Result
- from ..pool import ConnectionPoolEntry
- from ..sql import Executable
- from ..sql.elements import BindParameter
-
-
-class ConnectionEvents(event.Events[ConnectionEventsTarget]):
- """Available events for
- :class:`_engine.Connection` and :class:`_engine.Engine`.
-
- The methods here define the name of an event as well as the names of
- members that are passed to listener functions.
-
- An event listener can be associated with any
- :class:`_engine.Connection` or :class:`_engine.Engine`
- class or instance, such as an :class:`_engine.Engine`, e.g.::
-
- from sqlalchemy import event, create_engine
-
- def before_cursor_execute(conn, cursor, statement, parameters, context,
- executemany):
- log.info("Received statement: %s", statement)
-
- engine = create_engine('postgresql+psycopg2://scott:tiger@localhost/test')
- event.listen(engine, "before_cursor_execute", before_cursor_execute)
-
- or with a specific :class:`_engine.Connection`::
-
- with engine.begin() as conn:
- @event.listens_for(conn, 'before_cursor_execute')
- def before_cursor_execute(conn, cursor, statement, parameters,
- context, executemany):
- log.info("Received statement: %s", statement)
-
- When the methods are called with a `statement` parameter, such as in
- :meth:`.after_cursor_execute` or :meth:`.before_cursor_execute`,
- the statement is the exact SQL string that was prepared for transmission
- to the DBAPI ``cursor`` in the connection's :class:`.Dialect`.
-
- The :meth:`.before_execute` and :meth:`.before_cursor_execute`
- events can also be established with the ``retval=True`` flag, which
- allows modification of the statement and parameters to be sent
- to the database. The :meth:`.before_cursor_execute` event is
- particularly useful here to add ad-hoc string transformations, such
- as comments, to all executions::
-
- from sqlalchemy.engine import Engine
- from sqlalchemy import event
-
- @event.listens_for(Engine, "before_cursor_execute", retval=True)
- def comment_sql_calls(conn, cursor, statement, parameters,
- context, executemany):
- statement = statement + " -- some comment"
- return statement, parameters
-
- .. note:: :class:`_events.ConnectionEvents` can be established on any
- combination of :class:`_engine.Engine`, :class:`_engine.Connection`,
- as well
- as instances of each of those classes. Events across all
- four scopes will fire off for a given instance of
- :class:`_engine.Connection`. However, for performance reasons, the
- :class:`_engine.Connection` object determines at instantiation time
- whether or not its parent :class:`_engine.Engine` has event listeners
- established. Event listeners added to the :class:`_engine.Engine`
- class or to an instance of :class:`_engine.Engine`
- *after* the instantiation
- of a dependent :class:`_engine.Connection` instance will usually
- *not* be available on that :class:`_engine.Connection` instance.
- The newly
- added listeners will instead take effect for
- :class:`_engine.Connection`
- instances created subsequent to those event listeners being
- established on the parent :class:`_engine.Engine` class or instance.
-
- :param retval=False: Applies to the :meth:`.before_execute` and
- :meth:`.before_cursor_execute` events only. When True, the
- user-defined event function must have a return value, which
- is a tuple of parameters that replace the given statement
- and parameters. See those methods for a description of
- specific return arguments.
-
- """ # noqa
-
- _target_class_doc = "SomeEngine"
- _dispatch_target = ConnectionEventsTarget
-
- @classmethod
- def _accept_with(
- cls,
- target: Union[ConnectionEventsTarget, Type[ConnectionEventsTarget]],
- identifier: str,
- ) -> Optional[Union[ConnectionEventsTarget, Type[ConnectionEventsTarget]]]:
- default_dispatch = super()._accept_with(target, identifier)
- if default_dispatch is None and hasattr(
- target, "_no_async_engine_events"
- ):
- target._no_async_engine_events()
-
- return default_dispatch
-
- @classmethod
- def _listen(
- cls,
- event_key: event._EventKey[ConnectionEventsTarget],
- *,
- retval: bool = False,
- **kw: Any,
- ) -> None:
- target, identifier, fn = (
- event_key.dispatch_target,
- event_key.identifier,
- event_key._listen_fn,
- )
- target._has_events = True
-
- if not retval:
- if identifier == "before_execute":
- orig_fn = fn
-
- def wrap_before_execute( # type: ignore
- conn, clauseelement, multiparams, params, execution_options
- ):
- orig_fn(
- conn,
- clauseelement,
- multiparams,
- params,
- execution_options,
- )
- return clauseelement, multiparams, params
-
- fn = wrap_before_execute
- elif identifier == "before_cursor_execute":
- orig_fn = fn
-
- def wrap_before_cursor_execute( # type: ignore
- conn, cursor, statement, parameters, context, executemany
- ):
- orig_fn(
- conn,
- cursor,
- statement,
- parameters,
- context,
- executemany,
- )
- return statement, parameters
-
- fn = wrap_before_cursor_execute
- elif retval and identifier not in (
- "before_execute",
- "before_cursor_execute",
- ):
- raise exc.ArgumentError(
- "Only the 'before_execute', "
- "'before_cursor_execute' and 'handle_error' engine "
- "event listeners accept the 'retval=True' "
- "argument."
- )
- event_key.with_wrapper(fn).base_listen()
-
- @event._legacy_signature(
- "1.4",
- ["conn", "clauseelement", "multiparams", "params"],
- lambda conn, clauseelement, multiparams, params, execution_options: (
- conn,
- clauseelement,
- multiparams,
- params,
- ),
- )
- def before_execute(
- self,
- conn: Connection,
- clauseelement: Executable,
- multiparams: _CoreMultiExecuteParams,
- params: _CoreSingleExecuteParams,
- execution_options: _ExecuteOptions,
- ) -> Optional[
- Tuple[Executable, _CoreMultiExecuteParams, _CoreSingleExecuteParams]
- ]:
- """Intercept high level execute() events, receiving uncompiled
- SQL constructs and other objects prior to rendering into SQL.
-
- This event is good for debugging SQL compilation issues as well
- as early manipulation of the parameters being sent to the database,
- as the parameter lists will be in a consistent format here.
-
- This event can be optionally established with the ``retval=True``
- flag. The ``clauseelement``, ``multiparams``, and ``params``
- arguments should be returned as a three-tuple in this case::
-
- @event.listens_for(Engine, "before_execute", retval=True)
- def before_execute(conn, clauseelement, multiparams, params):
- # do something with clauseelement, multiparams, params
- return clauseelement, multiparams, params
-
- :param conn: :class:`_engine.Connection` object
- :param clauseelement: SQL expression construct, :class:`.Compiled`
- instance, or string statement passed to
- :meth:`_engine.Connection.execute`.
- :param multiparams: Multiple parameter sets, a list of dictionaries.
- :param params: Single parameter set, a single dictionary.
- :param execution_options: dictionary of execution
- options passed along with the statement, if any. This is a merge
- of all options that will be used, including those of the statement,
- the connection, and those passed in to the method itself for
- the 2.0 style of execution.
-
- .. versionadded: 1.4
-
- .. seealso::
-
- :meth:`.before_cursor_execute`
-
- """
-
- @event._legacy_signature(
- "1.4",
- ["conn", "clauseelement", "multiparams", "params", "result"],
- lambda conn, clauseelement, multiparams, params, execution_options, result: ( # noqa
- conn,
- clauseelement,
- multiparams,
- params,
- result,
- ),
- )
- def after_execute(
- self,
- conn: Connection,
- clauseelement: Executable,
- multiparams: _CoreMultiExecuteParams,
- params: _CoreSingleExecuteParams,
- execution_options: _ExecuteOptions,
- result: Result[Any],
- ) -> None:
- """Intercept high level execute() events after execute.
-
-
- :param conn: :class:`_engine.Connection` object
- :param clauseelement: SQL expression construct, :class:`.Compiled`
- instance, or string statement passed to
- :meth:`_engine.Connection.execute`.
- :param multiparams: Multiple parameter sets, a list of dictionaries.
- :param params: Single parameter set, a single dictionary.
- :param execution_options: dictionary of execution
- options passed along with the statement, if any. This is a merge
- of all options that will be used, including those of the statement,
- the connection, and those passed in to the method itself for
- the 2.0 style of execution.
-
- .. versionadded: 1.4
-
- :param result: :class:`_engine.CursorResult` generated by the
- execution.
-
- """
-
- def before_cursor_execute(
- self,
- conn: Connection,
- cursor: DBAPICursor,
- statement: str,
- parameters: _DBAPIAnyExecuteParams,
- context: Optional[ExecutionContext],
- executemany: bool,
- ) -> Optional[Tuple[str, _DBAPIAnyExecuteParams]]:
- """Intercept low-level cursor execute() events before execution,
- receiving the string SQL statement and DBAPI-specific parameter list to
- be invoked against a cursor.
-
- This event is a good choice for logging as well as late modifications
- to the SQL string. It's less ideal for parameter modifications except
- for those which are specific to a target backend.
-
- This event can be optionally established with the ``retval=True``
- flag. The ``statement`` and ``parameters`` arguments should be
- returned as a two-tuple in this case::
-
- @event.listens_for(Engine, "before_cursor_execute", retval=True)
- def before_cursor_execute(conn, cursor, statement,
- parameters, context, executemany):
- # do something with statement, parameters
- return statement, parameters
-
- See the example at :class:`_events.ConnectionEvents`.
-
- :param conn: :class:`_engine.Connection` object
- :param cursor: DBAPI cursor object
- :param statement: string SQL statement, as to be passed to the DBAPI
- :param parameters: Dictionary, tuple, or list of parameters being
- passed to the ``execute()`` or ``executemany()`` method of the
- DBAPI ``cursor``. In some cases may be ``None``.
- :param context: :class:`.ExecutionContext` object in use. May
- be ``None``.
- :param executemany: boolean, if ``True``, this is an ``executemany()``
- call, if ``False``, this is an ``execute()`` call.
-
- .. seealso::
-
- :meth:`.before_execute`
-
- :meth:`.after_cursor_execute`
-
- """
-
- def after_cursor_execute(
- self,
- conn: Connection,
- cursor: DBAPICursor,
- statement: str,
- parameters: _DBAPIAnyExecuteParams,
- context: Optional[ExecutionContext],
- executemany: bool,
- ) -> None:
- """Intercept low-level cursor execute() events after execution.
-
- :param conn: :class:`_engine.Connection` object
- :param cursor: DBAPI cursor object. Will have results pending
- if the statement was a SELECT, but these should not be consumed
- as they will be needed by the :class:`_engine.CursorResult`.
- :param statement: string SQL statement, as passed to the DBAPI
- :param parameters: Dictionary, tuple, or list of parameters being
- passed to the ``execute()`` or ``executemany()`` method of the
- DBAPI ``cursor``. In some cases may be ``None``.
- :param context: :class:`.ExecutionContext` object in use. May
- be ``None``.
- :param executemany: boolean, if ``True``, this is an ``executemany()``
- call, if ``False``, this is an ``execute()`` call.
-
- """
-
- @event._legacy_signature(
- "2.0", ["conn", "branch"], converter=lambda conn: (conn, False)
- )
- def engine_connect(self, conn: Connection) -> None:
- """Intercept the creation of a new :class:`_engine.Connection`.
-
- This event is called typically as the direct result of calling
- the :meth:`_engine.Engine.connect` method.
-
- It differs from the :meth:`_events.PoolEvents.connect` method, which
- refers to the actual connection to a database at the DBAPI level;
- a DBAPI connection may be pooled and reused for many operations.
- In contrast, this event refers only to the production of a higher level
- :class:`_engine.Connection` wrapper around such a DBAPI connection.
-
- It also differs from the :meth:`_events.PoolEvents.checkout` event
- in that it is specific to the :class:`_engine.Connection` object,
- not the
- DBAPI connection that :meth:`_events.PoolEvents.checkout` deals with,
- although
- this DBAPI connection is available here via the
- :attr:`_engine.Connection.connection` attribute.
- But note there can in fact
- be multiple :meth:`_events.PoolEvents.checkout`
- events within the lifespan
- of a single :class:`_engine.Connection` object, if that
- :class:`_engine.Connection`
- is invalidated and re-established.
-
- :param conn: :class:`_engine.Connection` object.
-
- .. seealso::
-
- :meth:`_events.PoolEvents.checkout`
- the lower-level pool checkout event
- for an individual DBAPI connection
-
- """
-
- def set_connection_execution_options(
- self, conn: Connection, opts: Dict[str, Any]
- ) -> None:
- """Intercept when the :meth:`_engine.Connection.execution_options`
- method is called.
-
- This method is called after the new :class:`_engine.Connection`
- has been
- produced, with the newly updated execution options collection, but
- before the :class:`.Dialect` has acted upon any of those new options.
-
- Note that this method is not called when a new
- :class:`_engine.Connection`
- is produced which is inheriting execution options from its parent
- :class:`_engine.Engine`; to intercept this condition, use the
- :meth:`_events.ConnectionEvents.engine_connect` event.
-
- :param conn: The newly copied :class:`_engine.Connection` object
-
- :param opts: dictionary of options that were passed to the
- :meth:`_engine.Connection.execution_options` method.
- This dictionary may be modified in place to affect the ultimate
- options which take effect.
-
- .. versionadded:: 2.0 the ``opts`` dictionary may be modified
- in place.
-
-
- .. seealso::
-
- :meth:`_events.ConnectionEvents.set_engine_execution_options`
- - event
- which is called when :meth:`_engine.Engine.execution_options`
- is called.
-
-
- """
-
- def set_engine_execution_options(
- self, engine: Engine, opts: Dict[str, Any]
- ) -> None:
- """Intercept when the :meth:`_engine.Engine.execution_options`
- method is called.
-
- The :meth:`_engine.Engine.execution_options` method produces a shallow
- copy of the :class:`_engine.Engine` which stores the new options.
- That new
- :class:`_engine.Engine` is passed here.
- A particular application of this
- method is to add a :meth:`_events.ConnectionEvents.engine_connect`
- event
- handler to the given :class:`_engine.Engine`
- which will perform some per-
- :class:`_engine.Connection` task specific to these execution options.
-
- :param conn: The newly copied :class:`_engine.Engine` object
-
- :param opts: dictionary of options that were passed to the
- :meth:`_engine.Connection.execution_options` method.
- This dictionary may be modified in place to affect the ultimate
- options which take effect.
-
- .. versionadded:: 2.0 the ``opts`` dictionary may be modified
- in place.
-
- .. seealso::
-
- :meth:`_events.ConnectionEvents.set_connection_execution_options`
- - event
- which is called when :meth:`_engine.Connection.execution_options`
- is
- called.
-
- """
-
- def engine_disposed(self, engine: Engine) -> None:
- """Intercept when the :meth:`_engine.Engine.dispose` method is called.
-
- The :meth:`_engine.Engine.dispose` method instructs the engine to
- "dispose" of it's connection pool (e.g. :class:`_pool.Pool`), and
- replaces it with a new one. Disposing of the old pool has the
- effect that existing checked-in connections are closed. The new
- pool does not establish any new connections until it is first used.
-
- This event can be used to indicate that resources related to the
- :class:`_engine.Engine` should also be cleaned up,
- keeping in mind that the
- :class:`_engine.Engine`
- can still be used for new requests in which case
- it re-acquires connection resources.
-
- """
-
- def begin(self, conn: Connection) -> None:
- """Intercept begin() events.
-
- :param conn: :class:`_engine.Connection` object
-
- """
-
- def rollback(self, conn: Connection) -> None:
- """Intercept rollback() events, as initiated by a
- :class:`.Transaction`.
-
- Note that the :class:`_pool.Pool` also "auto-rolls back"
- a DBAPI connection upon checkin, if the ``reset_on_return``
- flag is set to its default value of ``'rollback'``.
- To intercept this
- rollback, use the :meth:`_events.PoolEvents.reset` hook.
-
- :param conn: :class:`_engine.Connection` object
-
- .. seealso::
-
- :meth:`_events.PoolEvents.reset`
-
- """
-
- def commit(self, conn: Connection) -> None:
- """Intercept commit() events, as initiated by a
- :class:`.Transaction`.
-
- Note that the :class:`_pool.Pool` may also "auto-commit"
- a DBAPI connection upon checkin, if the ``reset_on_return``
- flag is set to the value ``'commit'``. To intercept this
- commit, use the :meth:`_events.PoolEvents.reset` hook.
-
- :param conn: :class:`_engine.Connection` object
- """
-
- def savepoint(self, conn: Connection, name: str) -> None:
- """Intercept savepoint() events.
-
- :param conn: :class:`_engine.Connection` object
- :param name: specified name used for the savepoint.
-
- """
-
- def rollback_savepoint(
- self, conn: Connection, name: str, context: None
- ) -> None:
- """Intercept rollback_savepoint() events.
-
- :param conn: :class:`_engine.Connection` object
- :param name: specified name used for the savepoint.
- :param context: not used
-
- """
- # TODO: deprecate "context"
-
- def release_savepoint(
- self, conn: Connection, name: str, context: None
- ) -> None:
- """Intercept release_savepoint() events.
-
- :param conn: :class:`_engine.Connection` object
- :param name: specified name used for the savepoint.
- :param context: not used
-
- """
- # TODO: deprecate "context"
-
- def begin_twophase(self, conn: Connection, xid: Any) -> None:
- """Intercept begin_twophase() events.
-
- :param conn: :class:`_engine.Connection` object
- :param xid: two-phase XID identifier
-
- """
-
- def prepare_twophase(self, conn: Connection, xid: Any) -> None:
- """Intercept prepare_twophase() events.
-
- :param conn: :class:`_engine.Connection` object
- :param xid: two-phase XID identifier
- """
-
- def rollback_twophase(
- self, conn: Connection, xid: Any, is_prepared: bool
- ) -> None:
- """Intercept rollback_twophase() events.
-
- :param conn: :class:`_engine.Connection` object
- :param xid: two-phase XID identifier
- :param is_prepared: boolean, indicates if
- :meth:`.TwoPhaseTransaction.prepare` was called.
-
- """
-
- def commit_twophase(
- self, conn: Connection, xid: Any, is_prepared: bool
- ) -> None:
- """Intercept commit_twophase() events.
-
- :param conn: :class:`_engine.Connection` object
- :param xid: two-phase XID identifier
- :param is_prepared: boolean, indicates if
- :meth:`.TwoPhaseTransaction.prepare` was called.
-
- """
-
-
-class DialectEvents(event.Events[Dialect]):
- """event interface for execution-replacement functions.
-
- These events allow direct instrumentation and replacement
- of key dialect functions which interact with the DBAPI.
-
- .. note::
-
- :class:`.DialectEvents` hooks should be considered **semi-public**
- and experimental.
- These hooks are not for general use and are only for those situations
- where intricate re-statement of DBAPI mechanics must be injected onto
- an existing dialect. For general-use statement-interception events,
- please use the :class:`_events.ConnectionEvents` interface.
-
- .. seealso::
-
- :meth:`_events.ConnectionEvents.before_cursor_execute`
-
- :meth:`_events.ConnectionEvents.before_execute`
-
- :meth:`_events.ConnectionEvents.after_cursor_execute`
-
- :meth:`_events.ConnectionEvents.after_execute`
-
- """
-
- _target_class_doc = "SomeEngine"
- _dispatch_target = Dialect
-
- @classmethod
- def _listen(
- cls,
- event_key: event._EventKey[Dialect],
- *,
- retval: bool = False,
- **kw: Any,
- ) -> None:
- target = event_key.dispatch_target
-
- target._has_events = True
- event_key.base_listen()
-
- @classmethod
- def _accept_with(
- cls,
- target: Union[Engine, Type[Engine], Dialect, Type[Dialect]],
- identifier: str,
- ) -> Optional[Union[Dialect, Type[Dialect]]]:
- if isinstance(target, type):
- if issubclass(target, Engine):
- return Dialect
- elif issubclass(target, Dialect):
- return target
- elif isinstance(target, Engine):
- return target.dialect
- elif isinstance(target, Dialect):
- return target
- elif isinstance(target, Connection) and identifier == "handle_error":
- raise exc.InvalidRequestError(
- "The handle_error() event hook as of SQLAlchemy 2.0 is "
- "established on the Dialect, and may only be applied to the "
- "Engine as a whole or to a specific Dialect as a whole, "
- "not on a per-Connection basis."
- )
- elif hasattr(target, "_no_async_engine_events"):
- target._no_async_engine_events()
- else:
- return None
-
- def handle_error(
- self, exception_context: ExceptionContext
- ) -> Optional[BaseException]:
- r"""Intercept all exceptions processed by the
- :class:`_engine.Dialect`, typically but not limited to those
- emitted within the scope of a :class:`_engine.Connection`.
-
- .. versionchanged:: 2.0 the :meth:`.DialectEvents.handle_error` event
- is moved to the :class:`.DialectEvents` class, moved from the
- :class:`.ConnectionEvents` class, so that it may also participate in
- the "pre ping" operation configured with the
- :paramref:`_sa.create_engine.pool_pre_ping` parameter. The event
- remains registered by using the :class:`_engine.Engine` as the event
- target, however note that using the :class:`_engine.Connection` as
- an event target for :meth:`.DialectEvents.handle_error` is no longer
- supported.
-
- This includes all exceptions emitted by the DBAPI as well as
- within SQLAlchemy's statement invocation process, including
- encoding errors and other statement validation errors. Other areas
- in which the event is invoked include transaction begin and end,
- result row fetching, cursor creation.
-
- Note that :meth:`.handle_error` may support new kinds of exceptions
- and new calling scenarios at *any time*. Code which uses this
- event must expect new calling patterns to be present in minor
- releases.
-
- To support the wide variety of members that correspond to an exception,
- as well as to allow extensibility of the event without backwards
- incompatibility, the sole argument received is an instance of
- :class:`.ExceptionContext`. This object contains data members
- representing detail about the exception.
-
- Use cases supported by this hook include:
-
- * read-only, low-level exception handling for logging and
- debugging purposes
- * Establishing whether a DBAPI connection error message indicates
- that the database connection needs to be reconnected, including
- for the "pre_ping" handler used by **some** dialects
- * Establishing or disabling whether a connection or the owning
- connection pool is invalidated or expired in response to a
- specific exception
- * exception re-writing
-
- The hook is called while the cursor from the failed operation
- (if any) is still open and accessible. Special cleanup operations
- can be called on this cursor; SQLAlchemy will attempt to close
- this cursor subsequent to this hook being invoked.
-
- As of SQLAlchemy 2.0, the "pre_ping" handler enabled using the
- :paramref:`_sa.create_engine.pool_pre_ping` parameter will also
- participate in the :meth:`.handle_error` process, **for those dialects
- that rely upon disconnect codes to detect database liveness**. Note
- that some dialects such as psycopg, psycopg2, and most MySQL dialects
- make use of a native ``ping()`` method supplied by the DBAPI which does
- not make use of disconnect codes.
-
- .. versionchanged:: 2.0.0 The :meth:`.DialectEvents.handle_error`
- event hook participates in connection pool "pre-ping" operations.
- Within this usage, the :attr:`.ExceptionContext.engine` attribute
- will be ``None``, however the :class:`.Dialect` in use is always
- available via the :attr:`.ExceptionContext.dialect` attribute.
-
- .. versionchanged:: 2.0.5 Added :attr:`.ExceptionContext.is_pre_ping`
- attribute which will be set to ``True`` when the
- :meth:`.DialectEvents.handle_error` event hook is triggered within
- a connection pool pre-ping operation.
-
- .. versionchanged:: 2.0.5 An issue was repaired that allows for the
- PostgreSQL ``psycopg`` and ``psycopg2`` drivers, as well as all
- MySQL drivers, to properly participate in the
- :meth:`.DialectEvents.handle_error` event hook during
- connection pool "pre-ping" operations; previously, the
- implementation was non-working for these drivers.
-
-
- A handler function has two options for replacing
- the SQLAlchemy-constructed exception into one that is user
- defined. It can either raise this new exception directly, in
- which case all further event listeners are bypassed and the
- exception will be raised, after appropriate cleanup as taken
- place::
-
- @event.listens_for(Engine, "handle_error")
- def handle_exception(context):
- if isinstance(context.original_exception,
- psycopg2.OperationalError) and \
- "failed" in str(context.original_exception):
- raise MySpecialException("failed operation")
-
- .. warning:: Because the
- :meth:`_events.DialectEvents.handle_error`
- event specifically provides for exceptions to be re-thrown as
- the ultimate exception raised by the failed statement,
- **stack traces will be misleading** if the user-defined event
- handler itself fails and throws an unexpected exception;
- the stack trace may not illustrate the actual code line that
- failed! It is advised to code carefully here and use
- logging and/or inline debugging if unexpected exceptions are
- occurring.
-
- Alternatively, a "chained" style of event handling can be
- used, by configuring the handler with the ``retval=True``
- modifier and returning the new exception instance from the
- function. In this case, event handling will continue onto the
- next handler. The "chained" exception is available using
- :attr:`.ExceptionContext.chained_exception`::
-
- @event.listens_for(Engine, "handle_error", retval=True)
- def handle_exception(context):
- if context.chained_exception is not None and \
- "special" in context.chained_exception.message:
- return MySpecialException("failed",
- cause=context.chained_exception)
-
- Handlers that return ``None`` may be used within the chain; when
- a handler returns ``None``, the previous exception instance,
- if any, is maintained as the current exception that is passed onto the
- next handler.
-
- When a custom exception is raised or returned, SQLAlchemy raises
- this new exception as-is, it is not wrapped by any SQLAlchemy
- object. If the exception is not a subclass of
- :class:`sqlalchemy.exc.StatementError`,
- certain features may not be available; currently this includes
- the ORM's feature of adding a detail hint about "autoflush" to
- exceptions raised within the autoflush process.
-
- :param context: an :class:`.ExceptionContext` object. See this
- class for details on all available members.
-
-
- .. seealso::
-
- :ref:`pool_new_disconnect_codes`
-
- """
-
- def do_connect(
- self,
- dialect: Dialect,
- conn_rec: ConnectionPoolEntry,
- cargs: Tuple[Any, ...],
- cparams: Dict[str, Any],
- ) -> Optional[DBAPIConnection]:
- """Receive connection arguments before a connection is made.
-
- This event is useful in that it allows the handler to manipulate the
- cargs and/or cparams collections that control how the DBAPI
- ``connect()`` function will be called. ``cargs`` will always be a
- Python list that can be mutated in-place, and ``cparams`` a Python
- dictionary that may also be mutated::
-
- e = create_engine("postgresql+psycopg2://user@host/dbname")
-
- @event.listens_for(e, 'do_connect')
- def receive_do_connect(dialect, conn_rec, cargs, cparams):
- cparams["password"] = "some_password"
-
- The event hook may also be used to override the call to ``connect()``
- entirely, by returning a non-``None`` DBAPI connection object::
-
- e = create_engine("postgresql+psycopg2://user@host/dbname")
-
- @event.listens_for(e, 'do_connect')
- def receive_do_connect(dialect, conn_rec, cargs, cparams):
- return psycopg2.connect(*cargs, **cparams)
-
- .. seealso::
-
- :ref:`custom_dbapi_args`
-
- """
-
- def do_executemany(
- self,
- cursor: DBAPICursor,
- statement: str,
- parameters: _DBAPIMultiExecuteParams,
- context: ExecutionContext,
- ) -> Optional[Literal[True]]:
- """Receive a cursor to have executemany() called.
-
- Return the value True to halt further events from invoking,
- and to indicate that the cursor execution has already taken
- place within the event handler.
-
- """
-
- def do_execute_no_params(
- self, cursor: DBAPICursor, statement: str, context: ExecutionContext
- ) -> Optional[Literal[True]]:
- """Receive a cursor to have execute() with no parameters called.
-
- Return the value True to halt further events from invoking,
- and to indicate that the cursor execution has already taken
- place within the event handler.
-
- """
-
- def do_execute(
- self,
- cursor: DBAPICursor,
- statement: str,
- parameters: _DBAPISingleExecuteParams,
- context: ExecutionContext,
- ) -> Optional[Literal[True]]:
- """Receive a cursor to have execute() called.
-
- Return the value True to halt further events from invoking,
- and to indicate that the cursor execution has already taken
- place within the event handler.
-
- """
-
- def do_setinputsizes(
- self,
- inputsizes: Dict[BindParameter[Any], Any],
- cursor: DBAPICursor,
- statement: str,
- parameters: _DBAPIAnyExecuteParams,
- context: ExecutionContext,
- ) -> None:
- """Receive the setinputsizes dictionary for possible modification.
-
- This event is emitted in the case where the dialect makes use of the
- DBAPI ``cursor.setinputsizes()`` method which passes information about
- parameter binding for a particular statement. The given
- ``inputsizes`` dictionary will contain :class:`.BindParameter` objects
- as keys, linked to DBAPI-specific type objects as values; for
- parameters that are not bound, they are added to the dictionary with
- ``None`` as the value, which means the parameter will not be included
- in the ultimate setinputsizes call. The event may be used to inspect
- and/or log the datatypes that are being bound, as well as to modify the
- dictionary in place. Parameters can be added, modified, or removed
- from this dictionary. Callers will typically want to inspect the
- :attr:`.BindParameter.type` attribute of the given bind objects in
- order to make decisions about the DBAPI object.
-
- After the event, the ``inputsizes`` dictionary is converted into
- an appropriate datastructure to be passed to ``cursor.setinputsizes``;
- either a list for a positional bound parameter execution style,
- or a dictionary of string parameter keys to DBAPI type objects for
- a named bound parameter execution style.
-
- The setinputsizes hook overall is only used for dialects which include
- the flag ``use_setinputsizes=True``. Dialects which use this
- include cx_Oracle, pg8000, asyncpg, and pyodbc dialects.
-
- .. note::
-
- For use with pyodbc, the ``use_setinputsizes`` flag
- must be passed to the dialect, e.g.::
-
- create_engine("mssql+pyodbc://...", use_setinputsizes=True)
-
- .. seealso::
-
- :ref:`mssql_pyodbc_setinputsizes`
-
- .. versionadded:: 1.2.9
-
- .. seealso::
-
- :ref:`cx_oracle_setinputsizes`
-
- """
- pass