1# sqlalchemy/events.py 
    2# Copyright (C) 2005-2021 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: http://www.opensource.org/licenses/mit-license.php 
    7 
    8"""Core event interfaces.""" 
    9 
    10from . import event 
    11from . import exc 
    12from . import util 
    13from .engine import Connectable 
    14from .engine import Dialect 
    15from .engine import Engine 
    16from .pool import Pool 
    17from .sql.base import SchemaEventTarget 
    18 
    19 
    20class DDLEvents(event.Events): 
    21    """ 
    22    Define event listeners for schema objects, 
    23    that is, :class:`.SchemaItem` and other :class:`.SchemaEventTarget` 
    24    subclasses, including :class:`_schema.MetaData`, :class:`_schema.Table`, 
    25    :class:`_schema.Column`. 
    26 
    27    :class:`_schema.MetaData` and :class:`_schema.Table` support events 
    28    specifically regarding when CREATE and DROP 
    29    DDL is emitted to the database. 
    30 
    31    Attachment events are also provided to customize 
    32    behavior whenever a child schema element is associated 
    33    with a parent, such as, when a :class:`_schema.Column` is associated 
    34    with its :class:`_schema.Table`, when a 
    35    :class:`_schema.ForeignKeyConstraint` 
    36    is associated with a :class:`_schema.Table`, etc. 
    37 
    38    Example using the ``after_create`` event:: 
    39 
    40        from sqlalchemy import event 
    41        from sqlalchemy import Table, Column, Metadata, Integer 
    42 
    43        m = MetaData() 
    44        some_table = Table('some_table', m, Column('data', Integer)) 
    45 
    46        def after_create(target, connection, **kw): 
    47            connection.execute("ALTER TABLE %s SET name=foo_%s" % 
    48                                    (target.name, target.name)) 
    49 
    50        event.listen(some_table, "after_create", after_create) 
    51 
    52    DDL events integrate closely with the 
    53    :class:`.DDL` class and the :class:`.DDLElement` hierarchy 
    54    of DDL clause constructs, which are themselves appropriate 
    55    as listener callables:: 
    56 
    57        from sqlalchemy import DDL 
    58        event.listen( 
    59            some_table, 
    60            "after_create", 
    61            DDL("ALTER TABLE %(table)s SET name=foo_%(table)s") 
    62        ) 
    63 
    64    The methods here define the name of an event as well 
    65    as the names of members that are passed to listener 
    66    functions. 
    67 
    68    For all :class:`.DDLEvent` events, the ``propagate=True`` keyword argument 
    69    will ensure that a given event handler is propagated to copies of the 
    70    object, which are made when using the :meth:`_schema.Table.tometadata` 
    71    method:: 
    72 
    73        from sqlalchemy import DDL 
    74        event.listen( 
    75            some_table, 
    76            "after_create", 
    77            DDL("ALTER TABLE %(table)s SET name=foo_%(table)s"), 
    78            propagate=True 
    79        ) 
    80 
    81        new_table = some_table.tometadata(new_metadata) 
    82 
    83    The above :class:`.DDL` object will also be associated with the 
    84    :class:`_schema.Table` object represented by ``new_table``. 
    85 
    86    .. seealso:: 
    87 
    88        :ref:`event_toplevel` 
    89 
    90        :class:`.DDLElement` 
    91 
    92        :class:`.DDL` 
    93 
    94        :ref:`schema_ddl_sequences` 
    95 
    96    """ 
    97 
    98    _target_class_doc = "SomeSchemaClassOrObject" 
    99    _dispatch_target = SchemaEventTarget 
    100 
    101    def before_create(self, target, connection, **kw): 
    102        r"""Called before CREATE statements are emitted. 
    103 
    104        :param target: the :class:`_schema.MetaData` or :class:`_schema.Table` 
    105         object which is the target of the event. 
    106        :param connection: the :class:`_engine.Connection` where the 
    107         CREATE statement or statements will be emitted. 
    108        :param \**kw: additional keyword arguments relevant 
    109         to the event.  The contents of this dictionary 
    110         may vary across releases, and include the 
    111         list of tables being generated for a metadata-level 
    112         event, the checkfirst flag, and other 
    113         elements used by internal events. 
    114 
    115        :func:`.event.listen` also accepts the ``propagate=True`` 
    116        modifier for this event; when True, the listener function will 
    117        be established for any copies made of the target object, 
    118        i.e. those copies that are generated when 
    119        :meth:`_schema.Table.tometadata` is used. 
    120 
    121        """ 
    122 
    123    def after_create(self, target, connection, **kw): 
    124        r"""Called after CREATE statements are emitted. 
    125 
    126        :param target: the :class:`_schema.MetaData` or :class:`_schema.Table` 
    127         object which is the target of the event. 
    128        :param connection: the :class:`_engine.Connection` where the 
    129         CREATE statement or statements have been emitted. 
    130        :param \**kw: additional keyword arguments relevant 
    131         to the event.  The contents of this dictionary 
    132         may vary across releases, and include the 
    133         list of tables being generated for a metadata-level 
    134         event, the checkfirst flag, and other 
    135         elements used by internal events. 
    136 
    137        :func:`.event.listen` also accepts the ``propagate=True`` 
    138        modifier for this event; when True, the listener function will 
    139        be established for any copies made of the target object, 
    140        i.e. those copies that are generated when 
    141        :meth:`_schema.Table.tometadata` is used. 
    142 
    143        """ 
    144 
    145    def before_drop(self, target, connection, **kw): 
    146        r"""Called before DROP statements are emitted. 
    147 
    148        :param target: the :class:`_schema.MetaData` or :class:`_schema.Table` 
    149         object which is the target of the event. 
    150        :param connection: the :class:`_engine.Connection` where the 
    151         DROP statement or statements will be emitted. 
    152        :param \**kw: additional keyword arguments relevant 
    153         to the event.  The contents of this dictionary 
    154         may vary across releases, and include the 
    155         list of tables being generated for a metadata-level 
    156         event, the checkfirst flag, and other 
    157         elements used by internal events. 
    158 
    159        :func:`.event.listen` also accepts the ``propagate=True`` 
    160        modifier for this event; when True, the listener function will 
    161        be established for any copies made of the target object, 
    162        i.e. those copies that are generated when 
    163        :meth:`_schema.Table.tometadata` is used. 
    164 
    165        """ 
    166 
    167    def after_drop(self, target, connection, **kw): 
    168        r"""Called after DROP statements are emitted. 
    169 
    170        :param target: the :class:`_schema.MetaData` or :class:`_schema.Table` 
    171         object which is the target of the event. 
    172        :param connection: the :class:`_engine.Connection` where the 
    173         DROP statement or statements have been emitted. 
    174        :param \**kw: additional keyword arguments relevant 
    175         to the event.  The contents of this dictionary 
    176         may vary across releases, and include the 
    177         list of tables being generated for a metadata-level 
    178         event, the checkfirst flag, and other 
    179         elements used by internal events. 
    180 
    181        :func:`.event.listen` also accepts the ``propagate=True`` 
    182        modifier for this event; when True, the listener function will 
    183        be established for any copies made of the target object, 
    184        i.e. those copies that are generated when 
    185        :meth:`_schema.Table.tometadata` is used. 
    186 
    187        """ 
    188 
    189    def before_parent_attach(self, target, parent): 
    190        """Called before a :class:`.SchemaItem` is associated with 
    191        a parent :class:`.SchemaItem`. 
    192 
    193        :param target: the target object 
    194        :param parent: the parent to which the target is being attached. 
    195 
    196        :func:`.event.listen` also accepts the ``propagate=True`` 
    197        modifier for this event; when True, the listener function will 
    198        be established for any copies made of the target object, 
    199        i.e. those copies that are generated when 
    200        :meth:`_schema.Table.tometadata` is used. 
    201 
    202        """ 
    203 
    204    def after_parent_attach(self, target, parent): 
    205        """Called after a :class:`.SchemaItem` is associated with 
    206        a parent :class:`.SchemaItem`. 
    207 
    208        :param target: the target object 
    209        :param parent: the parent to which the target is being attached. 
    210 
    211        :func:`.event.listen` also accepts the ``propagate=True`` 
    212        modifier for this event; when True, the listener function will 
    213        be established for any copies made of the target object, 
    214        i.e. those copies that are generated when 
    215        :meth:`_schema.Table.tometadata` is used. 
    216 
    217        """ 
    218 
    219    def _sa_event_column_added_to_pk_constraint(self, const, col): 
    220        """internal event hook used for primary key naming convention 
    221        updates. 
    222 
    223        """ 
    224 
    225    def column_reflect(self, inspector, table, column_info): 
    226        """Called for each unit of 'column info' retrieved when 
    227        a :class:`_schema.Table` is being reflected. 
    228 
    229        Currently, this event may only be applied to the :class:`_schema.Table` 
    230        class directly:: 
    231 
    232            from sqlalchemy import Table 
    233 
    234            @event.listens_for(Table, 'column_reflect') 
    235            def receive_column_reflect(inspector, table, column_info): 
    236                # receives for all Table objects that are reflected 
    237 
    238        Or applied using the 
    239        :paramref:`_schema.Table.listeners` parameter:: 
    240 
    241            t1 = Table( 
    242                "my_table", 
    243                autoload_with=some_engine, 
    244                listeners=[ 
    245                    ('column_reflect', receive_column_reflect) 
    246                ] 
    247            ) 
    248 
    249        A future release will allow it to be associated with a specific 
    250        :class:`_schema.MetaData` object as well. 
    251 
    252        The dictionary of column information as returned by the 
    253        dialect is passed, and can be modified.  The dictionary 
    254        is that returned in each element of the list returned 
    255        by :meth:`.reflection.Inspector.get_columns`: 
    256 
    257            * ``name`` - the column's name, is applied to the 
    258              :paramref:`_schema.Column.name` parameter 
    259 
    260            * ``type`` - the type of this column, which should be an instance 
    261              of :class:`~sqlalchemy.types.TypeEngine`, is applied to the 
    262              :paramref:`_schema.Column.type` parameter 
    263 
    264            * ``nullable`` - boolean flag if the column is NULL or NOT NULL, 
    265              is applied to the :paramref:`_schema.Column.nullable` parameter 
    266 
    267            * ``default`` - the column's server default value.  This is 
    268              normally specified as a plain string SQL expression, however the 
    269              event can pass a :class:`.FetchedValue`, :class:`.DefaultClause`, 
    270              or :func:`_expression.text` object as well.  Is applied to the 
    271              :paramref:`_schema.Column.server_default` parameter 
    272 
    273              .. versionchanged:: 1.1.6 
    274 
    275                    The :meth:`.DDLEvents.column_reflect` event allows a non 
    276                    string :class:`.FetchedValue`, 
    277                    :func:`_expression.text`, or derived object to be 
    278                    specified as the value of ``default`` in the column 
    279                    dictionary. 
    280 
    281        The event is called before any action is taken against 
    282        this dictionary, and the contents can be modified; the following 
    283        additional keys may be added to the dictionary to further modify 
    284        how the :class:`_schema.Column` is constructed: 
    285 
    286 
    287            * ``key`` - the string key that will be used to access this 
    288              :class:`_schema.Column` in the ``.c`` collection; will be applied 
    289              to the :paramref:`_schema.Column.key` parameter. Is also used 
    290              for ORM mapping.  See the section 
    291              :ref:`mapper_automated_reflection_schemes` for an example. 
    292 
    293            * ``quote`` - force or un-force quoting on the column name; 
    294              is applied to the :paramref:`_schema.Column.quote` parameter. 
    295 
    296            * ``info`` - a dictionary of arbitrary data to follow along with 
    297              the :class:`_schema.Column`, is applied to the 
    298              :paramref:`_schema.Column.info` parameter. 
    299 
    300        :func:`.event.listen` also accepts the ``propagate=True`` 
    301        modifier for this event; when True, the listener function will 
    302        be established for any copies made of the target object, 
    303        i.e. those copies that are generated when 
    304        :meth:`_schema.Table.to_metadata` is used. 
    305 
    306        """ 
    307 
    308 
    309class PoolEvents(event.Events): 
    310    """Available events for :class:`_pool.Pool`. 
    311 
    312    The methods here define the name of an event as well 
    313    as the names of members that are passed to listener 
    314    functions. 
    315 
    316    e.g.:: 
    317 
    318        from sqlalchemy import event 
    319 
    320        def my_on_checkout(dbapi_conn, connection_rec, connection_proxy): 
    321            "handle an on checkout event" 
    322 
    323        event.listen(Pool, 'checkout', my_on_checkout) 
    324 
    325    In addition to accepting the :class:`_pool.Pool` class and 
    326    :class:`_pool.Pool` instances, :class:`_events.PoolEvents` also accepts 
    327    :class:`_engine.Engine` objects and the :class:`_engine.Engine` class as 
    328    targets, which will be resolved to the ``.pool`` attribute of the 
    329    given engine or the :class:`_pool.Pool` class:: 
    330 
    331        engine = create_engine("postgresql://scott:tiger@localhost/test") 
    332 
    333        # will associate with engine.pool 
    334        event.listen(engine, 'checkout', my_on_checkout) 
    335 
    336    """ 
    337 
    338    _target_class_doc = "SomeEngineOrPool" 
    339    _dispatch_target = Pool 
    340 
    341    @classmethod 
    342    def _accept_with(cls, target): 
    343        if isinstance(target, type): 
    344            if issubclass(target, Engine): 
    345                return Pool 
    346            elif issubclass(target, Pool): 
    347                return target 
    348        elif isinstance(target, Engine): 
    349            return target.pool 
    350        else: 
    351            return target 
    352 
    353    def connect(self, dbapi_connection, connection_record): 
    354        """Called at the moment a particular DBAPI connection is first 
    355        created for a given :class:`_pool.Pool`. 
    356 
    357        This event allows one to capture the point directly after which 
    358        the DBAPI module-level ``.connect()`` method has been used in order 
    359        to produce a new DBAPI connection. 
    360 
    361        :param dbapi_connection: a DBAPI connection. 
    362 
    363        :param connection_record: the :class:`._ConnectionRecord` managing the 
    364         DBAPI connection. 
    365 
    366        """ 
    367 
    368    def first_connect(self, dbapi_connection, connection_record): 
    369        """Called exactly once for the first time a DBAPI connection is 
    370        checked out from a particular :class:`_pool.Pool`. 
    371 
    372        The rationale for :meth:`_events.PoolEvents.first_connect` 
    373        is to determine 
    374        information about a particular series of database connections based 
    375        on the settings used for all connections.  Since a particular 
    376        :class:`_pool.Pool` 
    377        refers to a single "creator" function (which in terms 
    378        of a :class:`_engine.Engine` 
    379        refers to the URL and connection options used), 
    380        it is typically valid to make observations about a single connection 
    381        that can be safely assumed to be valid about all subsequent 
    382        connections, such as the database version, the server and client 
    383        encoding settings, collation settings, and many others. 
    384 
    385        :param dbapi_connection: a DBAPI connection. 
    386 
    387        :param connection_record: the :class:`._ConnectionRecord` managing the 
    388         DBAPI connection. 
    389 
    390        """ 
    391 
    392    def checkout(self, dbapi_connection, connection_record, connection_proxy): 
    393        """Called when a connection is retrieved from the Pool. 
    394 
    395        :param dbapi_connection: a DBAPI connection. 
    396 
    397        :param connection_record: the :class:`._ConnectionRecord` managing the 
    398         DBAPI connection. 
    399 
    400        :param connection_proxy: the :class:`._ConnectionFairy` object which 
    401          will proxy the public interface of the DBAPI connection for the 
    402          lifespan of the checkout. 
    403 
    404        If you raise a :class:`~sqlalchemy.exc.DisconnectionError`, the current 
    405        connection will be disposed and a fresh connection retrieved. 
    406        Processing of all checkout listeners will abort and restart 
    407        using the new connection. 
    408 
    409        .. seealso:: :meth:`_events.ConnectionEvents.engine_connect` 
    410           - a similar event 
    411           which occurs upon creation of a new :class:`_engine.Connection`. 
    412 
    413        """ 
    414 
    415    def checkin(self, dbapi_connection, connection_record): 
    416        """Called when a connection returns to the pool. 
    417 
    418        Note that the connection may be closed, and may be None if the 
    419        connection has been invalidated.  ``checkin`` will not be called 
    420        for detached connections.  (They do not return to the pool.) 
    421 
    422        :param dbapi_connection: a DBAPI connection. 
    423 
    424        :param connection_record: the :class:`._ConnectionRecord` managing the 
    425         DBAPI connection. 
    426 
    427        """ 
    428 
    429    def reset(self, dbapi_connection, connection_record): 
    430        """Called before the "reset" action occurs for a pooled connection. 
    431 
    432        This event represents 
    433        when the ``rollback()`` method is called on the DBAPI connection 
    434        before it is returned to the pool.  The behavior of "reset" can 
    435        be controlled, including disabled, using the ``reset_on_return`` 
    436        pool argument. 
    437 
    438 
    439        The :meth:`_events.PoolEvents.reset` event is usually followed by the 
    440        :meth:`_events.PoolEvents.checkin` event is called, except in those 
    441        cases where the connection is discarded immediately after reset. 
    442 
    443        :param dbapi_connection: a DBAPI connection. 
    444 
    445        :param connection_record: the :class:`._ConnectionRecord` managing the 
    446         DBAPI connection. 
    447 
    448        .. seealso:: 
    449 
    450            :meth:`_events.ConnectionEvents.rollback` 
    451 
    452            :meth:`_events.ConnectionEvents.commit` 
    453 
    454        """ 
    455 
    456    def invalidate(self, dbapi_connection, connection_record, exception): 
    457        """Called when a DBAPI connection is to be "invalidated". 
    458 
    459        This event is called any time the :meth:`._ConnectionRecord.invalidate` 
    460        method is invoked, either from API usage or via "auto-invalidation", 
    461        without the ``soft`` flag. 
    462 
    463        The event occurs before a final attempt to call ``.close()`` on the 
    464        connection occurs. 
    465 
    466        :param dbapi_connection: a DBAPI connection. 
    467 
    468        :param connection_record: the :class:`._ConnectionRecord` managing the 
    469         DBAPI connection. 
    470 
    471        :param exception: the exception object corresponding to the reason 
    472         for this invalidation, if any.  May be ``None``. 
    473 
    474        .. versionadded:: 0.9.2 Added support for connection invalidation 
    475           listening. 
    476 
    477        .. seealso:: 
    478 
    479            :ref:`pool_connection_invalidation` 
    480 
    481        """ 
    482 
    483    def soft_invalidate(self, dbapi_connection, connection_record, exception): 
    484        """Called when a DBAPI connection is to be "soft invalidated". 
    485 
    486        This event is called any time the :meth:`._ConnectionRecord.invalidate` 
    487        method is invoked with the ``soft`` flag. 
    488 
    489        Soft invalidation refers to when the connection record that tracks 
    490        this connection will force a reconnect after the current connection 
    491        is checked in.   It does not actively close the dbapi_connection 
    492        at the point at which it is called. 
    493 
    494        .. versionadded:: 1.0.3 
    495 
    496        """ 
    497 
    498    def close(self, dbapi_connection, connection_record): 
    499        """Called when a DBAPI connection is closed. 
    500 
    501        The event is emitted before the close occurs. 
    502 
    503        The close of a connection can fail; typically this is because 
    504        the connection is already closed.  If the close operation fails, 
    505        the connection is discarded. 
    506 
    507        The :meth:`.close` event corresponds to a connection that's still 
    508        associated with the pool. To intercept close events for detached 
    509        connections use :meth:`.close_detached`. 
    510 
    511        .. versionadded:: 1.1 
    512 
    513        """ 
    514 
    515    def detach(self, dbapi_connection, connection_record): 
    516        """Called when a DBAPI connection is "detached" from a pool. 
    517 
    518        This event is emitted after the detach occurs.  The connection 
    519        is no longer associated with the given connection record. 
    520 
    521        .. versionadded:: 1.1 
    522 
    523        """ 
    524 
    525    def close_detached(self, dbapi_connection): 
    526        """Called when a detached DBAPI connection is closed. 
    527 
    528        The event is emitted before the close occurs. 
    529 
    530        The close of a connection can fail; typically this is because 
    531        the connection is already closed.  If the close operation fails, 
    532        the connection is discarded. 
    533 
    534        .. versionadded:: 1.1 
    535 
    536        """ 
    537 
    538 
    539class ConnectionEvents(event.Events): 
    540    """Available events for :class:`.Connectable`, which includes 
    541    :class:`_engine.Connection` and :class:`_engine.Engine`. 
    542 
    543    The methods here define the name of an event as well as the names of 
    544    members that are passed to listener functions. 
    545 
    546    An event listener can be associated with any :class:`.Connectable` 
    547    class or instance, such as an :class:`_engine.Engine`, e.g.:: 
    548 
    549        from sqlalchemy import event, create_engine 
    550 
    551        def before_cursor_execute(conn, cursor, statement, parameters, context, 
    552                                                        executemany): 
    553            log.info("Received statement: %s", statement) 
    554 
    555        engine = create_engine('postgresql://scott:tiger@localhost/test') 
    556        event.listen(engine, "before_cursor_execute", before_cursor_execute) 
    557 
    558    or with a specific :class:`_engine.Connection`:: 
    559 
    560        with engine.begin() as conn: 
    561            @event.listens_for(conn, 'before_cursor_execute') 
    562            def before_cursor_execute(conn, cursor, statement, parameters, 
    563                                            context, executemany): 
    564                log.info("Received statement: %s", statement) 
    565 
    566    When the methods are called with a `statement` parameter, such as in 
    567    :meth:`.after_cursor_execute`, :meth:`.before_cursor_execute` and 
    568    :meth:`.dbapi_error`, the statement is the exact SQL string that was 
    569    prepared for transmission to the DBAPI ``cursor`` in the connection's 
    570    :class:`.Dialect`. 
    571 
    572    The :meth:`.before_execute` and :meth:`.before_cursor_execute` 
    573    events can also be established with the ``retval=True`` flag, which 
    574    allows modification of the statement and parameters to be sent 
    575    to the database.  The :meth:`.before_cursor_execute` event is 
    576    particularly useful here to add ad-hoc string transformations, such 
    577    as comments, to all executions:: 
    578 
    579        from sqlalchemy.engine import Engine 
    580        from sqlalchemy import event 
    581 
    582        @event.listens_for(Engine, "before_cursor_execute", retval=True) 
    583        def comment_sql_calls(conn, cursor, statement, parameters, 
    584                                            context, executemany): 
    585            statement = statement + " -- some comment" 
    586            return statement, parameters 
    587 
    588    .. note:: :class:`_events.ConnectionEvents` can be established on any 
    589       combination of :class:`_engine.Engine`, :class:`_engine.Connection`, 
    590       as well 
    591       as instances of each of those classes.  Events across all 
    592       four scopes will fire off for a given instance of 
    593       :class:`_engine.Connection`.  However, for performance reasons, the 
    594       :class:`_engine.Connection` object determines at instantiation time 
    595       whether or not its parent :class:`_engine.Engine` has event listeners 
    596       established.   Event listeners added to the :class:`_engine.Engine` 
    597       class or to an instance of :class:`_engine.Engine` 
    598       *after* the instantiation 
    599       of a dependent :class:`_engine.Connection` instance will usually 
    600       *not* be available on that :class:`_engine.Connection` instance. 
    601       The newly 
    602       added listeners will instead take effect for 
    603       :class:`_engine.Connection` 
    604       instances created subsequent to those event listeners being 
    605       established on the parent :class:`_engine.Engine` class or instance. 
    606 
    607    :param retval=False: Applies to the :meth:`.before_execute` and 
    608      :meth:`.before_cursor_execute` events only.  When True, the 
    609      user-defined event function must have a return value, which 
    610      is a tuple of parameters that replace the given statement 
    611      and parameters.  See those methods for a description of 
    612      specific return arguments. 
    613 
    614    """ 
    615 
    616    _target_class_doc = "SomeEngine" 
    617    _dispatch_target = Connectable 
    618 
    619    @classmethod 
    620    def _listen(cls, event_key, retval=False): 
    621        target, identifier, fn = ( 
    622            event_key.dispatch_target, 
    623            event_key.identifier, 
    624            event_key._listen_fn, 
    625        ) 
    626 
    627        target._has_events = True 
    628 
    629        if not retval: 
    630            if identifier == "before_execute": 
    631                orig_fn = fn 
    632 
    633                def wrap_before_execute( 
    634                    conn, clauseelement, multiparams, params 
    635                ): 
    636                    orig_fn(conn, clauseelement, multiparams, params) 
    637                    return clauseelement, multiparams, params 
    638 
    639                fn = wrap_before_execute 
    640            elif identifier == "before_cursor_execute": 
    641                orig_fn = fn 
    642 
    643                def wrap_before_cursor_execute( 
    644                    conn, cursor, statement, parameters, context, executemany 
    645                ): 
    646                    orig_fn( 
    647                        conn, 
    648                        cursor, 
    649                        statement, 
    650                        parameters, 
    651                        context, 
    652                        executemany, 
    653                    ) 
    654                    return statement, parameters 
    655 
    656                fn = wrap_before_cursor_execute 
    657        elif retval and identifier not in ( 
    658            "before_execute", 
    659            "before_cursor_execute", 
    660            "handle_error", 
    661        ): 
    662            raise exc.ArgumentError( 
    663                "Only the 'before_execute', " 
    664                "'before_cursor_execute' and 'handle_error' engine " 
    665                "event listeners accept the 'retval=True' " 
    666                "argument." 
    667            ) 
    668        event_key.with_wrapper(fn).base_listen() 
    669 
    670    def before_execute(self, conn, clauseelement, multiparams, params): 
    671        """Intercept high level execute() events, receiving uncompiled 
    672        SQL constructs and other objects prior to rendering into SQL. 
    673 
    674        This event is good for debugging SQL compilation issues as well 
    675        as early manipulation of the parameters being sent to the database, 
    676        as the parameter lists will be in a consistent format here. 
    677 
    678        This event can be optionally established with the ``retval=True`` 
    679        flag.  The ``clauseelement``, ``multiparams``, and ``params`` 
    680        arguments should be returned as a three-tuple in this case:: 
    681 
    682            @event.listens_for(Engine, "before_execute", retval=True) 
    683            def before_execute(conn, clauseelement, multiparams, params): 
    684                # do something with clauseelement, multiparams, params 
    685                return clauseelement, multiparams, params 
    686 
    687        :param conn: :class:`_engine.Connection` object 
    688        :param clauseelement: SQL expression construct, :class:`.Compiled` 
    689         instance, or string statement passed to 
    690         :meth:`_engine.Connection.execute`. 
    691        :param multiparams: Multiple parameter sets, a list of dictionaries. 
    692        :param params: Single parameter set, a single dictionary. 
    693 
    694        .. seealso:: 
    695 
    696            :meth:`.before_cursor_execute` 
    697 
    698        """ 
    699 
    700    def after_execute(self, conn, clauseelement, multiparams, params, result): 
    701        """Intercept high level execute() events after execute. 
    702 
    703 
    704        :param conn: :class:`_engine.Connection` object 
    705        :param clauseelement: SQL expression construct, :class:`.Compiled` 
    706         instance, or string statement passed to 
    707         :meth:`_engine.Connection.execute`. 
    708        :param multiparams: Multiple parameter sets, a list of dictionaries. 
    709        :param params: Single parameter set, a single dictionary. 
    710        :param result: :class:`_engine.ResultProxy` generated by the execution 
    711                      . 
    712 
    713        """ 
    714 
    715    def before_cursor_execute( 
    716        self, conn, cursor, statement, parameters, context, executemany 
    717    ): 
    718        """Intercept low-level cursor execute() events before execution, 
    719        receiving the string SQL statement and DBAPI-specific parameter list to 
    720        be invoked against a cursor. 
    721 
    722        This event is a good choice for logging as well as late modifications 
    723        to the SQL string.  It's less ideal for parameter modifications except 
    724        for those which are specific to a target backend. 
    725 
    726        This event can be optionally established with the ``retval=True`` 
    727        flag.  The ``statement`` and ``parameters`` arguments should be 
    728        returned as a two-tuple in this case:: 
    729 
    730            @event.listens_for(Engine, "before_cursor_execute", retval=True) 
    731            def before_cursor_execute(conn, cursor, statement, 
    732                            parameters, context, executemany): 
    733                # do something with statement, parameters 
    734                return statement, parameters 
    735 
    736        See the example at :class:`_events.ConnectionEvents`. 
    737 
    738        :param conn: :class:`_engine.Connection` object 
    739        :param cursor: DBAPI cursor object 
    740        :param statement: string SQL statement, as to be passed to the DBAPI 
    741        :param parameters: Dictionary, tuple, or list of parameters being 
    742         passed to the ``execute()`` or ``executemany()`` method of the 
    743         DBAPI ``cursor``.  In some cases may be ``None``. 
    744        :param context: :class:`.ExecutionContext` object in use.  May 
    745         be ``None``. 
    746        :param executemany: boolean, if ``True``, this is an ``executemany()`` 
    747         call, if ``False``, this is an ``execute()`` call. 
    748 
    749        .. seealso:: 
    750 
    751            :meth:`.before_execute` 
    752 
    753            :meth:`.after_cursor_execute` 
    754 
    755        """ 
    756 
    757    def after_cursor_execute( 
    758        self, conn, cursor, statement, parameters, context, executemany 
    759    ): 
    760        """Intercept low-level cursor execute() events after execution. 
    761 
    762        :param conn: :class:`_engine.Connection` object 
    763        :param cursor: DBAPI cursor object.  Will have results pending 
    764         if the statement was a SELECT, but these should not be consumed 
    765         as they will be needed by the :class:`_engine.ResultProxy`. 
    766        :param statement: string SQL statement, as passed to the DBAPI 
    767        :param parameters: Dictionary, tuple, or list of parameters being 
    768         passed to the ``execute()`` or ``executemany()`` method of the 
    769         DBAPI ``cursor``.  In some cases may be ``None``. 
    770        :param context: :class:`.ExecutionContext` object in use.  May 
    771         be ``None``. 
    772        :param executemany: boolean, if ``True``, this is an ``executemany()`` 
    773         call, if ``False``, this is an ``execute()`` call. 
    774 
    775        """ 
    776 
    777    @util.deprecated( 
    778        "0.9", 
    779        "The :meth:`_events.ConnectionEvents.dbapi_error` " 
    780        "event is deprecated and will be removed in a future release. " 
    781        "Please refer to the :meth:`_events.ConnectionEvents.handle_error` " 
    782        "event.", 
    783    ) 
    784    def dbapi_error( 
    785        self, conn, cursor, statement, parameters, context, exception 
    786    ): 
    787        """Intercept a raw DBAPI error. 
    788 
    789        This event is called with the DBAPI exception instance 
    790        received from the DBAPI itself, *before* SQLAlchemy wraps the 
    791        exception with it's own exception wrappers, and before any 
    792        other operations are performed on the DBAPI cursor; the 
    793        existing transaction remains in effect as well as any state 
    794        on the cursor. 
    795 
    796        The use case here is to inject low-level exception handling 
    797        into an :class:`_engine.Engine`, typically for logging and 
    798        debugging purposes. 
    799 
    800        .. warning:: 
    801 
    802            Code should **not** modify 
    803            any state or throw any exceptions here as this will 
    804            interfere with SQLAlchemy's cleanup and error handling 
    805            routines.  For exception modification, please refer to the 
    806            new :meth:`_events.ConnectionEvents.handle_error` event. 
    807 
    808        Subsequent to this hook, SQLAlchemy may attempt any 
    809        number of operations on the connection/cursor, including 
    810        closing the cursor, rolling back of the transaction in the 
    811        case of connectionless execution, and disposing of the entire 
    812        connection pool if a "disconnect" was detected.   The 
    813        exception is then wrapped in a SQLAlchemy DBAPI exception 
    814        wrapper and re-thrown. 
    815 
    816        :param conn: :class:`_engine.Connection` object 
    817        :param cursor: DBAPI cursor object 
    818        :param statement: string SQL statement, as passed to the DBAPI 
    819        :param parameters: Dictionary, tuple, or list of parameters being 
    820         passed to the ``execute()`` or ``executemany()`` method of the 
    821         DBAPI ``cursor``.  In some cases may be ``None``. 
    822        :param context: :class:`.ExecutionContext` object in use.  May 
    823         be ``None``. 
    824        :param exception: The **unwrapped** exception emitted directly from the 
    825         DBAPI.  The class here is specific to the DBAPI module in use. 
    826 
    827        """ 
    828 
    829    def handle_error(self, exception_context): 
    830        r"""Intercept all exceptions processed by the 
    831        :class:`_engine.Connection`. 
    832 
    833        This includes all exceptions emitted by the DBAPI as well as 
    834        within SQLAlchemy's statement invocation process, including 
    835        encoding errors and other statement validation errors.  Other areas 
    836        in which the event is invoked include transaction begin and end, 
    837        result row fetching, cursor creation. 
    838 
    839        Note that :meth:`.handle_error` may support new kinds of exceptions 
    840        and new calling scenarios at *any time*.  Code which uses this 
    841        event must expect new calling patterns to be present in minor 
    842        releases. 
    843 
    844        To support the wide variety of members that correspond to an exception, 
    845        as well as to allow extensibility of the event without backwards 
    846        incompatibility, the sole argument received is an instance of 
    847        :class:`.ExceptionContext`.   This object contains data members 
    848        representing detail about the exception. 
    849 
    850        Use cases supported by this hook include: 
    851 
    852        * read-only, low-level exception handling for logging and 
    853          debugging purposes 
    854        * exception re-writing 
    855        * Establishing or disabling whether a connection or the owning 
    856          connection pool is invalidated or expired in response to a 
    857          specific exception. [1]_. 
    858 
    859        The hook is called while the cursor from the failed operation 
    860        (if any) is still open and accessible.   Special cleanup operations 
    861        can be called on this cursor; SQLAlchemy will attempt to close 
    862        this cursor subsequent to this hook being invoked.  If the connection 
    863        is in "autocommit" mode, the transaction also remains open within 
    864        the scope of this hook; the rollback of the per-statement transaction 
    865        also occurs after the hook is called. 
    866 
    867        .. note:: 
    868 
    869            .. [1] The pool "pre_ping" handler enabled using the 
    870                :paramref:`_sa.create_engine.pool_pre_ping` parameter does 
    871                **not** consult this event before deciding if the "ping" 
    872                returned false, as opposed to receiving an unhandled error. 
    873                For this use case, the :ref:`legacy recipe based on 
    874                engine_connect() may be used 
    875                <pool_disconnects_pessimistic_custom>`.  A future API allow 
    876                more comprehensive customization of the "disconnect" 
    877                detection mechanism across all functions. 
    878 
    879        A handler function has two options for replacing 
    880        the SQLAlchemy-constructed exception into one that is user 
    881        defined.   It can either raise this new exception directly, in 
    882        which case all further event listeners are bypassed and the 
    883        exception will be raised, after appropriate cleanup as taken 
    884        place:: 
    885 
    886            @event.listens_for(Engine, "handle_error") 
    887            def handle_exception(context): 
    888                if isinstance(context.original_exception, 
    889                    psycopg2.OperationalError) and \ 
    890                    "failed" in str(context.original_exception): 
    891                    raise MySpecialException("failed operation") 
    892 
    893        .. warning::  Because the 
    894           :meth:`_events.ConnectionEvents.handle_error` 
    895           event specifically provides for exceptions to be re-thrown as 
    896           the ultimate exception raised by the failed statement, 
    897           **stack traces will be misleading** if the user-defined event 
    898           handler itself fails and throws an unexpected exception; 
    899           the stack trace may not illustrate the actual code line that 
    900           failed!  It is advised to code carefully here and use 
    901           logging and/or inline debugging if unexpected exceptions are 
    902           occurring. 
    903 
    904        Alternatively, a "chained" style of event handling can be 
    905        used, by configuring the handler with the ``retval=True`` 
    906        modifier and returning the new exception instance from the 
    907        function.  In this case, event handling will continue onto the 
    908        next handler.   The "chained" exception is available using 
    909        :attr:`.ExceptionContext.chained_exception`:: 
    910 
    911            @event.listens_for(Engine, "handle_error", retval=True) 
    912            def handle_exception(context): 
    913                if context.chained_exception is not None and \ 
    914                    "special" in context.chained_exception.message: 
    915                    return MySpecialException("failed", 
    916                        cause=context.chained_exception) 
    917 
    918        Handlers that return ``None`` may be used within the chain; when 
    919        a handler returns ``None``, the previous exception instance, 
    920        if any, is maintained as the current exception that is passed onto the 
    921        next handler. 
    922 
    923        When a custom exception is raised or returned, SQLAlchemy raises 
    924        this new exception as-is, it is not wrapped by any SQLAlchemy 
    925        object.  If the exception is not a subclass of 
    926        :class:`sqlalchemy.exc.StatementError`, 
    927        certain features may not be available; currently this includes 
    928        the ORM's feature of adding a detail hint about "autoflush" to 
    929        exceptions raised within the autoflush process. 
    930 
    931        :param context: an :class:`.ExceptionContext` object.  See this 
    932         class for details on all available members. 
    933 
    934        .. versionadded:: 0.9.7 Added the 
    935            :meth:`_events.ConnectionEvents.handle_error` hook. 
    936 
    937        .. versionchanged:: 1.1 The :meth:`.handle_error` event will now 
    938           receive all exceptions that inherit from ``BaseException``, 
    939           including ``SystemExit`` and ``KeyboardInterrupt``.  The setting for 
    940           :attr:`.ExceptionContext.is_disconnect` is ``True`` in this case and 
    941           the default for 
    942           :attr:`.ExceptionContext.invalidate_pool_on_disconnect` is 
    943           ``False``. 
    944 
    945        .. versionchanged:: 1.0.0 The :meth:`.handle_error` event is now 
    946           invoked when an :class:`_engine.Engine` fails during the initial 
    947           call to :meth:`_engine.Engine.connect`, as well as when a 
    948           :class:`_engine.Connection` object encounters an error during a 
    949           reconnect operation. 
    950 
    951        .. versionchanged:: 1.0.0 The :meth:`.handle_error` event is 
    952           not fired off when a dialect makes use of the 
    953           ``skip_user_error_events`` execution option.   This is used 
    954           by dialects which intend to catch SQLAlchemy-specific exceptions 
    955           within specific operations, such as when the MySQL dialect detects 
    956           a table not present within the ``has_table()`` dialect method. 
    957           Prior to 1.0.0, code which implements :meth:`.handle_error` needs 
    958           to ensure that exceptions thrown in these scenarios are re-raised 
    959           without modification. 
    960 
    961        """ 
    962 
    963    def engine_connect(self, conn, branch): 
    964        """Intercept the creation of a new :class:`_engine.Connection`. 
    965 
    966        This event is called typically as the direct result of calling 
    967        the :meth:`_engine.Engine.connect` method. 
    968 
    969        It differs from the :meth:`_events.PoolEvents.connect` method, which 
    970        refers to the actual connection to a database at the DBAPI level; 
    971        a DBAPI connection may be pooled and reused for many operations. 
    972        In contrast, this event refers only to the production of a higher level 
    973        :class:`_engine.Connection` wrapper around such a DBAPI connection. 
    974 
    975        It also differs from the :meth:`_events.PoolEvents.checkout` event 
    976        in that it is specific to the :class:`_engine.Connection` object, 
    977        not the 
    978        DBAPI connection that :meth:`_events.PoolEvents.checkout` deals with, 
    979        although 
    980        this DBAPI connection is available here via the 
    981        :attr:`_engine.Connection.connection` attribute. 
    982        But note there can in fact 
    983        be multiple :meth:`_events.PoolEvents.checkout` 
    984        events within the lifespan 
    985        of a single :class:`_engine.Connection` object, if that 
    986        :class:`_engine.Connection` 
    987        is invalidated and re-established.  There can also be multiple 
    988        :class:`_engine.Connection` 
    989        objects generated for the same already-checked-out 
    990        DBAPI connection, in the case that a "branch" of a 
    991        :class:`_engine.Connection` 
    992        is produced. 
    993 
    994        :param conn: :class:`_engine.Connection` object. 
    995        :param branch: if True, this is a "branch" of an existing 
    996         :class:`_engine.Connection`.  A branch is generated within the course 
    997         of a statement execution to invoke supplemental statements, most 
    998         typically to pre-execute a SELECT of a default value for the purposes 
    999         of an INSERT statement. 
    1000 
    1001        .. versionadded:: 0.9.0 
    1002 
    1003        .. seealso:: 
    1004 
    1005            :ref:`pool_disconnects_pessimistic` - illustrates how to use 
    1006            :meth:`_events.ConnectionEvents.engine_connect` 
    1007            to transparently ensure pooled connections are connected to the 
    1008            database. 
    1009 
    1010            :meth:`_events.PoolEvents.checkout` 
    1011            the lower-level pool checkout event 
    1012            for an individual DBAPI connection 
    1013 
    1014            :meth:`_events.ConnectionEvents.set_connection_execution_options` 
    1015            - a copy 
    1016            of a :class:`_engine.Connection` is also made when the 
    1017            :meth:`_engine.Connection.execution_options` method is called. 
    1018 
    1019        """ 
    1020 
    1021    def set_connection_execution_options(self, conn, opts): 
    1022        """Intercept when the :meth:`_engine.Connection.execution_options` 
    1023        method is called. 
    1024 
    1025        This method is called after the new :class:`_engine.Connection` 
    1026        has been 
    1027        produced, with the newly updated execution options collection, but 
    1028        before the :class:`.Dialect` has acted upon any of those new options. 
    1029 
    1030        Note that this method is not called when a new 
    1031        :class:`_engine.Connection` 
    1032        is produced which is inheriting execution options from its parent 
    1033        :class:`_engine.Engine`; to intercept this condition, use the 
    1034        :meth:`_events.ConnectionEvents.engine_connect` event. 
    1035 
    1036        :param conn: The newly copied :class:`_engine.Connection` object 
    1037 
    1038        :param opts: dictionary of options that were passed to the 
    1039         :meth:`_engine.Connection.execution_options` method. 
    1040 
    1041        .. versionadded:: 0.9.0 
    1042 
    1043        .. seealso:: 
    1044 
    1045            :meth:`_events.ConnectionEvents.set_engine_execution_options` 
    1046            - event 
    1047            which is called when :meth:`_engine.Engine.execution_options` 
    1048            is called. 
    1049 
    1050 
    1051        """ 
    1052 
    1053    def set_engine_execution_options(self, engine, opts): 
    1054        """Intercept when the :meth:`_engine.Engine.execution_options` 
    1055        method is called. 
    1056 
    1057        The :meth:`_engine.Engine.execution_options` method produces a shallow 
    1058        copy of the :class:`_engine.Engine` which stores the new options. 
    1059        That new 
    1060        :class:`_engine.Engine` is passed here. 
    1061        A particular application of this 
    1062        method is to add a :meth:`_events.ConnectionEvents.engine_connect` 
    1063        event 
    1064        handler to the given :class:`_engine.Engine` 
    1065        which will perform some per- 
    1066        :class:`_engine.Connection` task specific to these execution options. 
    1067 
    1068        :param conn: The newly copied :class:`_engine.Engine` object 
    1069 
    1070        :param opts: dictionary of options that were passed to the 
    1071         :meth:`_engine.Connection.execution_options` method. 
    1072 
    1073        .. versionadded:: 0.9.0 
    1074 
    1075        .. seealso:: 
    1076 
    1077            :meth:`_events.ConnectionEvents.set_connection_execution_options` 
    1078            - event 
    1079            which is called when :meth:`_engine.Connection.execution_options` 
    1080            is 
    1081            called. 
    1082 
    1083        """ 
    1084 
    1085    def engine_disposed(self, engine): 
    1086        """Intercept when the :meth:`_engine.Engine.dispose` method is called. 
    1087 
    1088        The :meth:`_engine.Engine.dispose` method instructs the engine to 
    1089        "dispose" of it's connection pool (e.g. :class:`_pool.Pool`), and 
    1090        replaces it with a new one.  Disposing of the old pool has the 
    1091        effect that existing checked-in connections are closed.  The new 
    1092        pool does not establish any new connections until it is first used. 
    1093 
    1094        This event can be used to indicate that resources related to the 
    1095        :class:`_engine.Engine` should also be cleaned up, 
    1096        keeping in mind that the 
    1097        :class:`_engine.Engine` 
    1098        can still be used for new requests in which case 
    1099        it re-acquires connection resources. 
    1100 
    1101        .. versionadded:: 1.0.5 
    1102 
    1103        """ 
    1104 
    1105    def begin(self, conn): 
    1106        """Intercept begin() events. 
    1107 
    1108        :param conn: :class:`_engine.Connection` object 
    1109 
    1110        """ 
    1111 
    1112    def rollback(self, conn): 
    1113        """Intercept rollback() events, as initiated by a 
    1114        :class:`.Transaction`. 
    1115 
    1116        Note that the :class:`_pool.Pool` also "auto-rolls back" 
    1117        a DBAPI connection upon checkin, if the ``reset_on_return`` 
    1118        flag is set to its default value of ``'rollback'``. 
    1119        To intercept this 
    1120        rollback, use the :meth:`_events.PoolEvents.reset` hook. 
    1121 
    1122        :param conn: :class:`_engine.Connection` object 
    1123 
    1124        .. seealso:: 
    1125 
    1126            :meth:`_events.PoolEvents.reset` 
    1127 
    1128        """ 
    1129 
    1130    def commit(self, conn): 
    1131        """Intercept commit() events, as initiated by a 
    1132        :class:`.Transaction`. 
    1133 
    1134        Note that the :class:`_pool.Pool` may also "auto-commit" 
    1135        a DBAPI connection upon checkin, if the ``reset_on_return`` 
    1136        flag is set to the value ``'commit'``.  To intercept this 
    1137        commit, use the :meth:`_events.PoolEvents.reset` hook. 
    1138 
    1139        :param conn: :class:`_engine.Connection` object 
    1140        """ 
    1141 
    1142    def savepoint(self, conn, name): 
    1143        """Intercept savepoint() events. 
    1144 
    1145        :param conn: :class:`_engine.Connection` object 
    1146        :param name: specified name used for the savepoint. 
    1147 
    1148        """ 
    1149 
    1150    def rollback_savepoint(self, conn, name, context): 
    1151        """Intercept rollback_savepoint() events. 
    1152 
    1153        :param conn: :class:`_engine.Connection` object 
    1154        :param name: specified name used for the savepoint. 
    1155        :param context: :class:`.ExecutionContext` in use.  May be ``None``. 
    1156 
    1157        """ 
    1158 
    1159    def release_savepoint(self, conn, name, context): 
    1160        """Intercept release_savepoint() events. 
    1161 
    1162        :param conn: :class:`_engine.Connection` object 
    1163        :param name: specified name used for the savepoint. 
    1164        :param context: :class:`.ExecutionContext` in use.  May be ``None``. 
    1165 
    1166        """ 
    1167 
    1168    def begin_twophase(self, conn, xid): 
    1169        """Intercept begin_twophase() events. 
    1170 
    1171        :param conn: :class:`_engine.Connection` object 
    1172        :param xid: two-phase XID identifier 
    1173 
    1174        """ 
    1175 
    1176    def prepare_twophase(self, conn, xid): 
    1177        """Intercept prepare_twophase() events. 
    1178 
    1179        :param conn: :class:`_engine.Connection` object 
    1180        :param xid: two-phase XID identifier 
    1181        """ 
    1182 
    1183    def rollback_twophase(self, conn, xid, is_prepared): 
    1184        """Intercept rollback_twophase() events. 
    1185 
    1186        :param conn: :class:`_engine.Connection` object 
    1187        :param xid: two-phase XID identifier 
    1188        :param is_prepared: boolean, indicates if 
    1189         :meth:`.TwoPhaseTransaction.prepare` was called. 
    1190 
    1191        """ 
    1192 
    1193    def commit_twophase(self, conn, xid, is_prepared): 
    1194        """Intercept commit_twophase() events. 
    1195 
    1196        :param conn: :class:`_engine.Connection` object 
    1197        :param xid: two-phase XID identifier 
    1198        :param is_prepared: boolean, indicates if 
    1199         :meth:`.TwoPhaseTransaction.prepare` was called. 
    1200 
    1201        """ 
    1202 
    1203 
    1204class DialectEvents(event.Events): 
    1205    """event interface for execution-replacement functions. 
    1206 
    1207    These events allow direct instrumentation and replacement 
    1208    of key dialect functions which interact with the DBAPI. 
    1209 
    1210    .. note:: 
    1211 
    1212        :class:`.DialectEvents` hooks should be considered **semi-public** 
    1213        and experimental. 
    1214        These hooks are not for general use and are only for those situations 
    1215        where intricate re-statement of DBAPI mechanics must be injected onto 
    1216        an existing dialect.  For general-use statement-interception events, 
    1217        please use the :class:`_events.ConnectionEvents` interface. 
    1218 
    1219    .. seealso:: 
    1220 
    1221        :meth:`_events.ConnectionEvents.before_cursor_execute` 
    1222 
    1223        :meth:`_events.ConnectionEvents.before_execute` 
    1224 
    1225        :meth:`_events.ConnectionEvents.after_cursor_execute` 
    1226 
    1227        :meth:`_events.ConnectionEvents.after_execute` 
    1228 
    1229 
    1230    .. versionadded:: 0.9.4 
    1231 
    1232    """ 
    1233 
    1234    _target_class_doc = "SomeEngine" 
    1235    _dispatch_target = Dialect 
    1236 
    1237    @classmethod 
    1238    def _listen(cls, event_key, retval=False): 
    1239        target = event_key.dispatch_target 
    1240 
    1241        target._has_events = True 
    1242        event_key.base_listen() 
    1243 
    1244    @classmethod 
    1245    def _accept_with(cls, target): 
    1246        if isinstance(target, type): 
    1247            if issubclass(target, Engine): 
    1248                return Dialect 
    1249            elif issubclass(target, Dialect): 
    1250                return target 
    1251        elif isinstance(target, Engine): 
    1252            return target.dialect 
    1253        else: 
    1254            return target 
    1255 
    1256    def do_connect(self, dialect, conn_rec, cargs, cparams): 
    1257        """Receive connection arguments before a connection is made. 
    1258 
    1259        Return a DBAPI connection to halt further events from invoking; 
    1260        the returned connection will be used. 
    1261 
    1262        Alternatively, the event can manipulate the cargs and/or cparams 
    1263        collections; cargs will always be a Python list that can be mutated 
    1264        in-place and cparams a Python dictionary.  Return None to 
    1265        allow control to pass to the next event handler and ultimately 
    1266        to allow the dialect to connect normally, given the updated 
    1267        arguments. 
    1268 
    1269        .. versionadded:: 1.0.3 
    1270 
    1271        .. seealso:: 
    1272 
    1273            :ref:`custom_dbapi_args` 
    1274 
    1275        """ 
    1276 
    1277    def do_executemany(self, cursor, statement, parameters, context): 
    1278        """Receive a cursor to have executemany() called. 
    1279 
    1280        Return the value True to halt further events from invoking, 
    1281        and to indicate that the cursor execution has already taken 
    1282        place within the event handler. 
    1283 
    1284        """ 
    1285 
    1286    def do_execute_no_params(self, cursor, statement, context): 
    1287        """Receive a cursor to have execute() with no parameters called. 
    1288 
    1289        Return the value True to halt further events from invoking, 
    1290        and to indicate that the cursor execution has already taken 
    1291        place within the event handler. 
    1292 
    1293        """ 
    1294 
    1295    def do_execute(self, cursor, statement, parameters, context): 
    1296        """Receive a cursor to have execute() called. 
    1297 
    1298        Return the value True to halt further events from invoking, 
    1299        and to indicate that the cursor execution has already taken 
    1300        place within the event handler. 
    1301 
    1302        """ 
    1303 
    1304    def do_setinputsizes( 
    1305        self, inputsizes, cursor, statement, parameters, context 
    1306    ): 
    1307        """Receive the setinputsizes dictionary for possible modification. 
    1308 
    1309        This event is emitted in the case where the dialect makes use of the 
    1310        DBAPI ``cursor.setinputsizes()`` method which passes information about 
    1311        parameter binding for a particular statement.   The given 
    1312        ``inputsizes`` dictionary will contain :class:`.BindParameter` objects 
    1313        as keys, linked to DBAPI-specific type objects as values; for 
    1314        parameters that are not bound, they are added to the dictionary with 
    1315        ``None`` as the value, which means the parameter will not be included 
    1316        in the ultimate setinputsizes call.   The event may be used to inspect 
    1317        and/or log the datatypes that are being bound, as well as to modify the 
    1318        dictionary in place.  Parameters can be added, modified, or removed 
    1319        from this dictionary.   Callers will typically want to inspect the 
    1320        :attr:`.BindParameter.type` attribute of the given bind objects in 
    1321        order to make decisions about the DBAPI object. 
    1322 
    1323        After the event, the ``inputsizes`` dictionary is converted into 
    1324        an appropriate datastructure to be passed to ``cursor.setinputsizes``; 
    1325        either a list for a positional bound parameter execution style, 
    1326        or a dictionary of string parameter keys to DBAPI type objects for 
    1327        a named bound parameter execution style. 
    1328 
    1329        Most dialects **do not use** this method at all; the only built-in 
    1330        dialect which uses this hook is the cx_Oracle dialect.   The hook here 
    1331        is made available so as to allow customization of how datatypes are set 
    1332        up with the  cx_Oracle DBAPI. 
    1333 
    1334        .. versionadded:: 1.2.9 
    1335 
    1336        .. seealso:: 
    1337 
    1338            :ref:`cx_oracle_setinputsizes` 
    1339 
    1340        """ 
    1341        pass