Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/sqlalchemy/event/api.py: 92%
25 statements
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
1# event/api.py
2# Copyright (C) 2005-2022 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
8"""Public API functions for the event system.
10"""
11from __future__ import absolute_import
13from .base import _registrars
14from .registry import _EventKey
15from .. import exc
16from .. import util
19CANCEL = util.symbol("CANCEL")
20NO_RETVAL = util.symbol("NO_RETVAL")
23def _event_key(target, identifier, fn):
24 for evt_cls in _registrars[identifier]:
25 tgt = evt_cls._accept_with(target)
26 if tgt is not None:
27 return _EventKey(target, identifier, fn, tgt)
28 else:
29 raise exc.InvalidRequestError(
30 "No such event '%s' for target '%s'" % (identifier, target)
31 )
34def listen(target, identifier, fn, *args, **kw):
35 """Register a listener function for the given target.
37 The :func:`.listen` function is part of the primary interface for the
38 SQLAlchemy event system, documented at :ref:`event_toplevel`.
40 e.g.::
42 from sqlalchemy import event
43 from sqlalchemy.schema import UniqueConstraint
45 def unique_constraint_name(const, table):
46 const.name = "uq_%s_%s" % (
47 table.name,
48 list(const.columns)[0].name
49 )
50 event.listen(
51 UniqueConstraint,
52 "after_parent_attach",
53 unique_constraint_name)
55 :param bool insert: The default behavior for event handlers is to append
56 the decorated user defined function to an internal list of registered
57 event listeners upon discovery. If a user registers a function with
58 ``insert=True``, SQLAlchemy will insert (prepend) the function to the
59 internal list upon discovery. This feature is not typically used or
60 recommended by the SQLAlchemy maintainers, but is provided to ensure
61 certain user defined functions can run before others, such as when
62 :ref:`Changing the sql_mode in MySQL <mysql_sql_mode>`.
64 :param bool named: When using named argument passing, the names listed in
65 the function argument specification will be used as keys in the
66 dictionary.
67 See :ref:`event_named_argument_styles`.
69 :param bool once: Private/Internal API usage. Deprecated. This parameter
70 would provide that an event function would run only once per given
71 target. It does not however imply automatic de-registration of the
72 listener function; associating an arbitrarily high number of listeners
73 without explicitly removing them will cause memory to grow unbounded even
74 if ``once=True`` is specified.
76 :param bool propagate: The ``propagate`` kwarg is available when working
77 with ORM instrumentation and mapping events.
78 See :class:`_ormevent.MapperEvents` and
79 :meth:`_ormevent.MapperEvents.before_mapper_configured` for examples.
81 :param bool retval: This flag applies only to specific event listeners,
82 each of which includes documentation explaining when it should be used.
83 By default, no listener ever requires a return value.
84 However, some listeners do support special behaviors for return values,
85 and include in their documentation that the ``retval=True`` flag is
86 necessary for a return value to be processed.
88 Event listener suites that make use of :paramref:`_event.listen.retval`
89 include :class:`_events.ConnectionEvents` and
90 :class:`_ormevent.AttributeEvents`.
92 .. note::
94 The :func:`.listen` function cannot be called at the same time
95 that the target event is being run. This has implications
96 for thread safety, and also means an event cannot be added
97 from inside the listener function for itself. The list of
98 events to be run are present inside of a mutable collection
99 that can't be changed during iteration.
101 Event registration and removal is not intended to be a "high
102 velocity" operation; it is a configurational operation. For
103 systems that need to quickly associate and deassociate with
104 events at high scale, use a mutable structure that is handled
105 from inside of a single listener.
107 .. seealso::
109 :func:`.listens_for`
111 :func:`.remove`
113 """
115 _event_key(target, identifier, fn).listen(*args, **kw)
118def listens_for(target, identifier, *args, **kw):
119 """Decorate a function as a listener for the given target + identifier.
121 The :func:`.listens_for` decorator is part of the primary interface for the
122 SQLAlchemy event system, documented at :ref:`event_toplevel`.
124 This function generally shares the same kwargs as :func:`.listens`.
126 e.g.::
128 from sqlalchemy import event
129 from sqlalchemy.schema import UniqueConstraint
131 @event.listens_for(UniqueConstraint, "after_parent_attach")
132 def unique_constraint_name(const, table):
133 const.name = "uq_%s_%s" % (
134 table.name,
135 list(const.columns)[0].name
136 )
138 A given function can also be invoked for only the first invocation
139 of the event using the ``once`` argument::
141 @event.listens_for(Mapper, "before_configure", once=True)
142 def on_config():
143 do_config()
146 .. warning:: The ``once`` argument does not imply automatic de-registration
147 of the listener function after it has been invoked a first time; a
148 listener entry will remain associated with the target object.
149 Associating an arbitrarily high number of listeners without explicitly
150 removing them will cause memory to grow unbounded even if ``once=True``
151 is specified.
153 .. seealso::
155 :func:`.listen` - general description of event listening
157 """
159 def decorate(fn):
160 listen(target, identifier, fn, *args, **kw)
161 return fn
163 return decorate
166def remove(target, identifier, fn):
167 """Remove an event listener.
169 The arguments here should match exactly those which were sent to
170 :func:`.listen`; all the event registration which proceeded as a result
171 of this call will be reverted by calling :func:`.remove` with the same
172 arguments.
174 e.g.::
176 # if a function was registered like this...
177 @event.listens_for(SomeMappedClass, "before_insert", propagate=True)
178 def my_listener_function(*arg):
179 pass
181 # ... it's removed like this
182 event.remove(SomeMappedClass, "before_insert", my_listener_function)
184 Above, the listener function associated with ``SomeMappedClass`` was also
185 propagated to subclasses of ``SomeMappedClass``; the :func:`.remove`
186 function will revert all of these operations.
188 .. note::
190 The :func:`.remove` function cannot be called at the same time
191 that the target event is being run. This has implications
192 for thread safety, and also means an event cannot be removed
193 from inside the listener function for itself. The list of
194 events to be run are present inside of a mutable collection
195 that can't be changed during iteration.
197 Event registration and removal is not intended to be a "high
198 velocity" operation; it is a configurational operation. For
199 systems that need to quickly associate and deassociate with
200 events at high scale, use a mutable structure that is handled
201 from inside of a single listener.
203 .. versionchanged:: 1.0.0 - a ``collections.deque()`` object is now
204 used as the container for the list of events, which explicitly
205 disallows collection mutation while the collection is being
206 iterated.
208 .. seealso::
210 :func:`.listen`
212 """
213 _event_key(target, identifier, fn).remove()
216def contains(target, identifier, fn):
217 """Return True if the given target/ident/fn is set up to listen."""
219 return _event_key(target, identifier, fn).contains()