Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
events.py371 linesDownload Raw Back to pool
1# pool/events.py
2# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7from __future__ import annotations
8
9import typing
10from typing import Any
11from typing import Optional
12from typing import Type
13from typing import Union
14
15from .base import ConnectionPoolEntry
16from .base import Pool
17from .base import PoolProxiedConnection
18from .base import PoolResetState
19from .. import event
20from .. import util
21
22if typing.TYPE_CHECKING:
23    from ..engine import Engine
24    from ..engine.interfaces import DBAPIConnection
25
26
27class PoolEvents(event.Events[Pool]):
28    """Available events for :class:`_pool.Pool`.
29
30    The methods here define the name of an event as well
31    as the names of members that are passed to listener
32    functions.
33
34    e.g.::
35
36        from sqlalchemy import event
37
38        def my_on_checkout(dbapi_conn, connection_rec, connection_proxy):
39            "handle an on checkout event"
40
41        event.listen(Pool, 'checkout', my_on_checkout)
42
43    In addition to accepting the :class:`_pool.Pool` class and
44    :class:`_pool.Pool` instances, :class:`_events.PoolEvents` also accepts
45    :class:`_engine.Engine` objects and the :class:`_engine.Engine` class as
46    targets, which will be resolved to the ``.pool`` attribute of the
47    given engine or the :class:`_pool.Pool` class::
48
49        engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/test")
50
51        # will associate with engine.pool
52        event.listen(engine, 'checkout', my_on_checkout)
53
54    """  # noqa: E501
55
56    _target_class_doc = "SomeEngineOrPool"
57    _dispatch_target = Pool
58
59    @util.preload_module("sqlalchemy.engine")
60    @classmethod
61    def _accept_with(
62        cls,
63        target: Union[Pool, Type[Pool], Engine, Type[Engine]],
64        identifier: str,
65    ) -> Optional[Union[Pool, Type[Pool]]]:
66        if not typing.TYPE_CHECKING:
67            Engine = util.preloaded.engine.Engine
68
69        if isinstance(target, type):
70            if issubclass(target, Engine):
71                return Pool
72            else:
73                assert issubclass(target, Pool)
74                return target
75        elif isinstance(target, Engine):
76            return target.pool
77        elif isinstance(target, Pool):
78            return target
79        elif hasattr(target, "_no_async_engine_events"):
80            target._no_async_engine_events()
81        else:
82            return None
83
84    @classmethod
85    def _listen(
86        cls,
87        event_key: event._EventKey[Pool],
88        **kw: Any,
89    ) -> None:
90        target = event_key.dispatch_target
91
92        kw.setdefault("asyncio", target._is_asyncio)
93
94        event_key.base_listen(**kw)
95
96    def connect(
97        self,
98        dbapi_connection: DBAPIConnection,
99        connection_record: ConnectionPoolEntry,
100    ) -> None:
101        """Called at the moment a particular DBAPI connection is first
102        created for a given :class:`_pool.Pool`.
103
104        This event allows one to capture the point directly after which
105        the DBAPI module-level ``.connect()`` method has been used in order
106        to produce a new DBAPI connection.
107
108        :param dbapi_connection: a DBAPI connection.
109         The :attr:`.ConnectionPoolEntry.dbapi_connection` attribute.
110
111        :param connection_record: the :class:`.ConnectionPoolEntry` managing
112         the DBAPI connection.
113
114        """
115
116    def first_connect(
117        self,
118        dbapi_connection: DBAPIConnection,
119        connection_record: ConnectionPoolEntry,
120    ) -> None:
121        """Called exactly once for the first time a DBAPI connection is
122        checked out from a particular :class:`_pool.Pool`.
123
124        The rationale for :meth:`_events.PoolEvents.first_connect`
125        is to determine
126        information about a particular series of database connections based
127        on the settings used for all connections.  Since a particular
128        :class:`_pool.Pool`
129        refers to a single "creator" function (which in terms
130        of a :class:`_engine.Engine`
131        refers to the URL and connection options used),
132        it is typically valid to make observations about a single connection
133        that can be safely assumed to be valid about all subsequent
134        connections, such as the database version, the server and client
135        encoding settings, collation settings, and many others.
136
137        :param dbapi_connection: a DBAPI connection.
138         The :attr:`.ConnectionPoolEntry.dbapi_connection` attribute.
139
140        :param connection_record: the :class:`.ConnectionPoolEntry` managing
141         the DBAPI connection.
142
143        """
144
145    def checkout(
146        self,
147        dbapi_connection: DBAPIConnection,
148        connection_record: ConnectionPoolEntry,
149        connection_proxy: PoolProxiedConnection,
150    ) -> None:
151        """Called when a connection is retrieved from the Pool.
152
153        :param dbapi_connection: a DBAPI connection.
154         The :attr:`.ConnectionPoolEntry.dbapi_connection` attribute.
155
156        :param connection_record: the :class:`.ConnectionPoolEntry` managing
157         the DBAPI connection.
158
159        :param connection_proxy: the :class:`.PoolProxiedConnection` object
160          which will proxy the public interface of the DBAPI connection for the
161          lifespan of the checkout.
162
163        If you raise a :class:`~sqlalchemy.exc.DisconnectionError`, the current
164        connection will be disposed and a fresh connection retrieved.
165        Processing of all checkout listeners will abort and restart
166        using the new connection.
167
168        .. seealso:: :meth:`_events.ConnectionEvents.engine_connect`
169           - a similar event
170           which occurs upon creation of a new :class:`_engine.Connection`.
171
172        """
173
174    def checkin(
175        self,
176        dbapi_connection: Optional[DBAPIConnection],
177        connection_record: ConnectionPoolEntry,
178    ) -> None:
179        """Called when a connection returns to the pool.
180
181        Note that the connection may be closed, and may be None if the
182        connection has been invalidated.  ``checkin`` will not be called
183        for detached connections.  (They do not return to the pool.)
184
185        :param dbapi_connection: a DBAPI connection.
186         The :attr:`.ConnectionPoolEntry.dbapi_connection` attribute.
187
188        :param connection_record: the :class:`.ConnectionPoolEntry` managing
189         the DBAPI connection.
190
191        """
192
193    @event._legacy_signature(
194        "2.0",
195        ["dbapi_connection", "connection_record"],
196        lambda dbapi_connection, connection_record, reset_state: (
197            dbapi_connection,
198            connection_record,
199        ),
200    )
201    def reset(
202        self,
203        dbapi_connection: DBAPIConnection,
204        connection_record: ConnectionPoolEntry,
205        reset_state: PoolResetState,
206    ) -> None:
207        """Called before the "reset" action occurs for a pooled connection.
208
209        This event represents
210        when the ``rollback()`` method is called on the DBAPI connection
211        before it is returned to the pool or discarded.
212        A custom "reset" strategy may be implemented using this event hook,
213        which may also be combined with disabling the default "reset"
214        behavior using the :paramref:`_pool.Pool.reset_on_return` parameter.
215
216        The primary difference between the :meth:`_events.PoolEvents.reset` and
217        :meth:`_events.PoolEvents.checkin` events are that
218        :meth:`_events.PoolEvents.reset` is called not just for pooled
219        connections that are being returned to the pool, but also for
220        connections that were detached using the
221        :meth:`_engine.Connection.detach` method as well as asyncio connections
222        that are being discarded due to garbage collection taking place on
223        connections before the connection was checked in.
224
225        Note that the event **is not** invoked for connections that were
226        invalidated using :meth:`_engine.Connection.invalidate`.    These
227        events may be intercepted using the :meth:`.PoolEvents.soft_invalidate`
228        and :meth:`.PoolEvents.invalidate` event hooks, and all "connection
229        close" events may be intercepted using :meth:`.PoolEvents.close`.
230
231        The :meth:`_events.PoolEvents.reset` event is usually followed by the
232        :meth:`_events.PoolEvents.checkin` event, except in those
233        cases where the connection is discarded immediately after reset.
234
235        :param dbapi_connection: a DBAPI connection.
236         The :attr:`.ConnectionPoolEntry.dbapi_connection` attribute.
237
238        :param connection_record: the :class:`.ConnectionPoolEntry` managing
239         the DBAPI connection.
240
241        :param reset_state: :class:`.PoolResetState` instance which provides
242         information about the circumstances under which the connection
243         is being reset.
244
245         .. versionadded:: 2.0
246
247        .. seealso::
248
249            :ref:`pool_reset_on_return`
250
251            :meth:`_events.ConnectionEvents.rollback`
252
253            :meth:`_events.ConnectionEvents.commit`
254
255        """
256
257    def invalidate(
258        self,
259        dbapi_connection: DBAPIConnection,
260        connection_record: ConnectionPoolEntry,
261        exception: Optional[BaseException],
262    ) -> None:
263        """Called when a DBAPI connection is to be "invalidated".
264
265        This event is called any time the
266        :meth:`.ConnectionPoolEntry.invalidate` method is invoked, either from
267        API usage or via "auto-invalidation", without the ``soft`` flag.
268
269        The event occurs before a final attempt to call ``.close()`` on the
270        connection occurs.
271
272        :param dbapi_connection: a DBAPI connection.
273         The :attr:`.ConnectionPoolEntry.dbapi_connection` attribute.
274
275        :param connection_record: the :class:`.ConnectionPoolEntry` managing
276         the DBAPI connection.
277
278        :param exception: the exception object corresponding to the reason
279         for this invalidation, if any.  May be ``None``.
280
281        .. seealso::
282
283            :ref:`pool_connection_invalidation`
284
285        """
286
287    def soft_invalidate(
288        self,
289        dbapi_connection: DBAPIConnection,
290        connection_record: ConnectionPoolEntry,
291        exception: Optional[BaseException],
292    ) -> None:
293        """Called when a DBAPI connection is to be "soft invalidated".
294
295        This event is called any time the
296        :meth:`.ConnectionPoolEntry.invalidate`
297        method is invoked with the ``soft`` flag.
298
299        Soft invalidation refers to when the connection record that tracks
300        this connection will force a reconnect after the current connection
301        is checked in.   It does not actively close the dbapi_connection
302        at the point at which it is called.
303
304        :param dbapi_connection: a DBAPI connection.
305         The :attr:`.ConnectionPoolEntry.dbapi_connection` attribute.
306
307        :param connection_record: the :class:`.ConnectionPoolEntry` managing
308         the DBAPI connection.
309
310        :param exception: the exception object corresponding to the reason
311         for this invalidation, if any.  May be ``None``.
312
313        """
314
315    def close(
316        self,
317        dbapi_connection: DBAPIConnection,
318        connection_record: ConnectionPoolEntry,
319    ) -> None:
320        """Called when a DBAPI connection is closed.
321
322        The event is emitted before the close occurs.
323
324        The close of a connection can fail; typically this is because
325        the connection is already closed.  If the close operation fails,
326        the connection is discarded.
327
328        The :meth:`.close` event corresponds to a connection that's still
329        associated with the pool. To intercept close events for detached
330        connections use :meth:`.close_detached`.
331
332        :param dbapi_connection: a DBAPI connection.
333         The :attr:`.ConnectionPoolEntry.dbapi_connection` attribute.
334
335        :param connection_record: the :class:`.ConnectionPoolEntry` managing
336         the DBAPI connection.
337
338        """
339
340    def detach(
341        self,
342        dbapi_connection: DBAPIConnection,
343        connection_record: ConnectionPoolEntry,
344    ) -> None:
345        """Called when a DBAPI connection is "detached" from a pool.
346
347        This event is emitted after the detach occurs.  The connection
348        is no longer associated with the given connection record.
349
350        :param dbapi_connection: a DBAPI connection.
351         The :attr:`.ConnectionPoolEntry.dbapi_connection` attribute.
352
353        :param connection_record: the :class:`.ConnectionPoolEntry` managing
354         the DBAPI connection.
355
356        """
357
358    def close_detached(self, dbapi_connection: DBAPIConnection) -> None:
359        """Called when a detached DBAPI connection is closed.
360
361        The event is emitted before the close occurs.
362
363        The close of a connection can fail; typically this is because
364        the connection is already closed.  If the close operation fails,
365        the connection is discarded.
366
367        :param dbapi_connection: a DBAPI connection.
368         The :attr:`.ConnectionPoolEntry.dbapi_connection` attribute.
369
370        """
371 
codekingpro/portable-devtools · Team Ai