Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/SQLAlchemy-1.3.25.dev0-py3.11-linux-x86_64.egg/sqlalchemy/event/api.py: 85%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

26 statements  

1# event/api.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"""Public API functions for the event system. 

9 

10""" 

11from __future__ import absolute_import 

12 

13from .base import _registrars 

14from .registry import _EventKey 

15from .. import exc 

16from .. import util 

17 

18 

19CANCEL = util.symbol("CANCEL") 

20NO_RETVAL = util.symbol("NO_RETVAL") 

21 

22 

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 ) 

32 

33 

34def listen(target, identifier, fn, *args, **kw): 

35 """Register a listener function for the given target. 

36 

37 The :func:`.listen` function is part of the primary interface for the 

38 SQLAlchemy event system, documented at :ref:`event_toplevel`. 

39 

40 e.g.:: 

41 

42 from sqlalchemy import event 

43 from sqlalchemy.schema import UniqueConstraint 

44 

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) 

54 

55 

56 A given function can also be invoked for only the first invocation 

57 of the event using the ``once`` argument:: 

58 

59 def on_config(): 

60 do_config() 

61 

62 event.listen(Mapper, "before_configure", on_config, once=True) 

63 

64 .. versionadded:: 0.9.4 Added ``once=True`` to :func:`.event.listen` 

65 and :func:`.event.listens_for`. 

66 

67 .. warning:: The ``once`` argument does not imply automatic de-registration 

68 of the listener function after it has been invoked a first time; a 

69 listener entry will remain associated with the target object. 

70 Associating an arbitrarily high number of listeners without explicitly 

71 removing them will cause memory to grow unbounded even if ``once=True`` 

72 is specified. 

73 

74 .. note:: 

75 

76 The :func:`.listen` function cannot be called at the same time 

77 that the target event is being run. This has implications 

78 for thread safety, and also means an event cannot be added 

79 from inside the listener function for itself. The list of 

80 events to be run are present inside of a mutable collection 

81 that can't be changed during iteration. 

82 

83 Event registration and removal is not intended to be a "high 

84 velocity" operation; it is a configurational operation. For 

85 systems that need to quickly associate and deassociate with 

86 events at high scale, use a mutable structure that is handled 

87 from inside of a single listener. 

88 

89 .. versionchanged:: 1.0.0 - a ``collections.deque()`` object is now 

90 used as the container for the list of events, which explicitly 

91 disallows collection mutation while the collection is being 

92 iterated. 

93 

94 .. seealso:: 

95 

96 :func:`.listens_for` 

97 

98 :func:`.remove` 

99 

100 """ 

101 

102 _event_key(target, identifier, fn).listen(*args, **kw) 

103 

104 

105def listens_for(target, identifier, *args, **kw): 

106 """Decorate a function as a listener for the given target + identifier. 

107 

108 The :func:`.listens_for` decorator is part of the primary interface for the 

109 SQLAlchemy event system, documented at :ref:`event_toplevel`. 

110 

111 e.g.:: 

112 

113 from sqlalchemy import event 

114 from sqlalchemy.schema import UniqueConstraint 

115 

116 @event.listens_for(UniqueConstraint, "after_parent_attach") 

117 def unique_constraint_name(const, table): 

118 const.name = "uq_%s_%s" % ( 

119 table.name, 

120 list(const.columns)[0].name 

121 ) 

122 

123 A given function can also be invoked for only the first invocation 

124 of the event using the ``once`` argument:: 

125 

126 @event.listens_for(Mapper, "before_configure", once=True) 

127 def on_config(): 

128 do_config() 

129 

130 

131 .. versionadded:: 0.9.4 Added ``once=True`` to :func:`.event.listen` 

132 and :func:`.event.listens_for`. 

133 

134 .. warning:: The ``once`` argument does not imply automatic de-registration 

135 of the listener function after it has been invoked a first time; a 

136 listener entry will remain associated with the target object. 

137 Associating an arbitrarily high number of listeners without explicitly 

138 removing them will cause memory to grow unbounded even if ``once=True`` 

139 is specified. 

140 

141 .. seealso:: 

142 

143 :func:`.listen` - general description of event listening 

144 

145 """ 

146 

147 def decorate(fn): 

148 listen(target, identifier, fn, *args, **kw) 

149 return fn 

150 

151 return decorate 

152 

153 

154def remove(target, identifier, fn): 

155 """Remove an event listener. 

156 

157 The arguments here should match exactly those which were sent to 

158 :func:`.listen`; all the event registration which proceeded as a result 

159 of this call will be reverted by calling :func:`.remove` with the same 

160 arguments. 

161 

162 e.g.:: 

163 

164 # if a function was registered like this... 

165 @event.listens_for(SomeMappedClass, "before_insert", propagate=True) 

166 def my_listener_function(*arg): 

167 pass 

168 

169 # ... it's removed like this 

170 event.remove(SomeMappedClass, "before_insert", my_listener_function) 

171 

172 Above, the listener function associated with ``SomeMappedClass`` was also 

173 propagated to subclasses of ``SomeMappedClass``; the :func:`.remove` 

174 function will revert all of these operations. 

175 

176 .. versionadded:: 0.9.0 

177 

178 .. note:: 

179 

180 The :func:`.remove` function cannot be called at the same time 

181 that the target event is being run. This has implications 

182 for thread safety, and also means an event cannot be removed 

183 from inside the listener function for itself. The list of 

184 events to be run are present inside of a mutable collection 

185 that can't be changed during iteration. 

186 

187 Event registration and removal is not intended to be a "high 

188 velocity" operation; it is a configurational operation. For 

189 systems that need to quickly associate and deassociate with 

190 events at high scale, use a mutable structure that is handled 

191 from inside of a single listener. 

192 

193 .. versionchanged:: 1.0.0 - a ``collections.deque()`` object is now 

194 used as the container for the list of events, which explicitly 

195 disallows collection mutation while the collection is being 

196 iterated. 

197 

198 .. seealso:: 

199 

200 :func:`.listen` 

201 

202 """ 

203 _event_key(target, identifier, fn).remove() 

204 

205 

206def contains(target, identifier, fn): 

207 """Return True if the given target/ident/fn is set up to listen. 

208 

209 .. versionadded:: 0.9.0 

210 

211 """ 

212 

213 return _event_key(target, identifier, fn).contains()