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

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

85 statements  

1# sqlalchemy/interfaces.py 

2# Copyright (C) 2007-2021 the SQLAlchemy authors and contributors 

3# <see AUTHORS file> 

4# Copyright (C) 2007 Jason Kirtland jek@discorporate.us 

5# 

6# This module is part of SQLAlchemy and is released under 

7# the MIT License: http://www.opensource.org/licenses/mit-license.php 

8 

9"""Deprecated core event interfaces. 

10 

11 

12.. deprecated:: 0.7 

13 As of SQLAlchemy 0.7, the new event system described in 

14 :ref:`event_toplevel` replaces the extension/proxy/listener system, 

15 providing a consistent interface to all events without the need for 

16 subclassing. 

17 

18""" 

19 

20from . import event 

21from . import util 

22 

23 

24class PoolListener(object): 

25 """Hooks into the lifecycle of connections in a :class:`_pool.Pool`. 

26 

27 .. deprecated:: 0.7 

28 

29 :class:`.PoolListener` is deprecated and will be removed in a future 

30 release. Please refer to :func:`.event.listen` in conjunction with 

31 the :class:`_events.PoolEvents` listener interface. 

32 

33 Usage:: 

34 

35 class MyListener(PoolListener): 

36 def connect(self, dbapi_con, con_record): 

37 '''perform connect operations''' 

38 # etc. 

39 

40 # create a new pool with a listener 

41 p = QueuePool(..., listeners=[MyListener()]) 

42 

43 # add a listener after the fact 

44 p.add_listener(MyListener()) 

45 

46 # usage with create_engine() 

47 e = create_engine("url://", listeners=[MyListener()]) 

48 

49 All of the standard connection :class:`~sqlalchemy.pool.Pool` types can 

50 accept event listeners for key connection lifecycle events: 

51 creation, pool check-out and check-in. There are no events fired 

52 when a connection closes. 

53 

54 For any given DB-API connection, there will be one ``connect`` 

55 event, `n` number of ``checkout`` events, and either `n` or `n - 1` 

56 ``checkin`` events. (If a ``Connection`` is detached from its 

57 pool via the ``detach()`` method, it won't be checked back in.) 

58 

59 These are low-level events for low-level objects: raw Python 

60 DB-API connections, without the conveniences of the SQLAlchemy 

61 ``Connection`` wrapper, ``Dialect`` services or ``ClauseElement`` 

62 execution. If you execute SQL through the connection, explicitly 

63 closing all cursors and other resources is recommended. 

64 

65 Events also receive a ``_ConnectionRecord``, a long-lived internal 

66 ``Pool`` object that basically represents a "slot" in the 

67 connection pool. ``_ConnectionRecord`` objects have one public 

68 attribute of note: ``info``, a dictionary whose contents are 

69 scoped to the lifetime of the DB-API connection managed by the 

70 record. You can use this shared storage area however you like. 

71 

72 There is no need to subclass ``PoolListener`` to handle events. 

73 Any class that implements one or more of these methods can be used 

74 as a pool listener. The ``Pool`` will inspect the methods 

75 provided by a listener object and add the listener to one or more 

76 internal event queues based on its capabilities. In terms of 

77 efficiency and function call overhead, you're much better off only 

78 providing implementations for the hooks you'll be using. 

79 

80 """ 

81 

82 @classmethod 

83 def _adapt_listener(cls, self, listener): 

84 """Adapt a :class:`.PoolListener` to individual 

85 :class:`event.Dispatch` events. 

86 

87 """ 

88 

89 methods = ["connect", "first_connect", "checkout", "checkin"] 

90 listener = util.as_interface(listener, methods=methods) 

91 

92 for meth in methods: 

93 me_meth = getattr(PoolListener, meth) 

94 ls_meth = getattr(listener, meth, None) 

95 

96 if ls_meth is not None and not util.methods_equivalent( 

97 me_meth, ls_meth 

98 ): 

99 util.warn_deprecated( 

100 "PoolListener.%s is deprecated. The " 

101 "PoolListener class will be removed in a future " 

102 "release. Please transition to the @event interface, " 

103 "using @event.listens_for(Engine, '%s')." % (meth, meth) 

104 ) 

105 

106 if hasattr(listener, "connect"): 

107 event.listen(self, "connect", listener.connect) 

108 if hasattr(listener, "first_connect"): 

109 event.listen(self, "first_connect", listener.first_connect) 

110 if hasattr(listener, "checkout"): 

111 event.listen(self, "checkout", listener.checkout) 

112 if hasattr(listener, "checkin"): 

113 event.listen(self, "checkin", listener.checkin) 

114 

115 def connect(self, dbapi_con, con_record): 

116 """Called once for each new DB-API connection or Pool's ``creator()``. 

117 

118 dbapi_con 

119 A newly connected raw DB-API connection (not a SQLAlchemy 

120 ``Connection`` wrapper). 

121 

122 con_record 

123 The ``_ConnectionRecord`` that persistently manages the connection 

124 

125 """ 

126 

127 def first_connect(self, dbapi_con, con_record): 

128 """Called exactly once for the first DB-API connection. 

129 

130 dbapi_con 

131 A newly connected raw DB-API connection (not a SQLAlchemy 

132 ``Connection`` wrapper). 

133 

134 con_record 

135 The ``_ConnectionRecord`` that persistently manages the connection 

136 

137 """ 

138 

139 def checkout(self, dbapi_con, con_record, con_proxy): 

140 """Called when a connection is retrieved from the Pool. 

141 

142 dbapi_con 

143 A raw DB-API connection 

144 

145 con_record 

146 The ``_ConnectionRecord`` that persistently manages the connection 

147 

148 con_proxy 

149 The ``_ConnectionFairy`` which manages the connection for the span of 

150 the current checkout. 

151 

152 If you raise an ``exc.DisconnectionError``, the current 

153 connection will be disposed and a fresh connection retrieved. 

154 Processing of all checkout listeners will abort and restart 

155 using the new connection. 

156 """ 

157 

158 def checkin(self, dbapi_con, con_record): 

159 """Called when a connection returns to the pool. 

160 

161 Note that the connection may be closed, and may be None if the 

162 connection has been invalidated. ``checkin`` will not be called 

163 for detached connections. (They do not return to the pool.) 

164 

165 dbapi_con 

166 A raw DB-API connection 

167 

168 con_record 

169 The ``_ConnectionRecord`` that persistently manages the connection 

170 

171 """ 

172 

173 

174class ConnectionProxy(object): 

175 """Allows interception of statement execution by Connections. 

176 

177 .. deprecated:: 0.7 

178 

179 :class:`.ConnectionProxy` is deprecated and will be removed in a future 

180 release. Please refer to :func:`.event.listen` in conjunction with 

181 the :class:`_events.ConnectionEvents` listener interface. 

182 

183 Either or both of the ``execute()`` and ``cursor_execute()`` 

184 may be implemented to intercept compiled statement and 

185 cursor level executions, e.g.:: 

186 

187 class MyProxy(ConnectionProxy): 

188 def execute(self, conn, execute, clauseelement, 

189 *multiparams, **params): 

190 print "compiled statement:", clauseelement 

191 return execute(clauseelement, *multiparams, **params) 

192 

193 def cursor_execute(self, execute, cursor, statement, 

194 parameters, context, executemany): 

195 print "raw statement:", statement 

196 return execute(cursor, statement, parameters, context) 

197 

198 The ``execute`` argument is a function that will fulfill the default 

199 execution behavior for the operation. The signature illustrated 

200 in the example should be used. 

201 

202 The proxy is installed into an :class:`~sqlalchemy.engine.Engine` via 

203 the ``proxy`` argument:: 

204 

205 e = create_engine('someurl://', proxy=MyProxy()) 

206 

207 """ 

208 

209 @classmethod 

210 def _adapt_listener(cls, self, listener): 

211 

212 methods = [ 

213 "execute", 

214 "cursor_execute", 

215 "begin", 

216 "rollback", 

217 "commit", 

218 "savepoint", 

219 "rollback_savepoint", 

220 "release_savepoint", 

221 "begin_twophase", 

222 "prepare_twophase", 

223 "rollback_twophase", 

224 "commit_twophase", 

225 ] 

226 for meth in methods: 

227 me_meth = getattr(ConnectionProxy, meth) 

228 ls_meth = getattr(listener, meth) 

229 

230 if not util.methods_equivalent(me_meth, ls_meth): 

231 util.warn_deprecated( 

232 "ConnectionProxy.%s is deprecated. The " 

233 "ConnectionProxy class will be removed in a future " 

234 "release. Please transition to the @event interface, " 

235 "using @event.listens_for(Engine, '%s')." % (meth, meth) 

236 ) 

237 

238 def adapt_execute(conn, clauseelement, multiparams, params): 

239 def execute_wrapper(clauseelement, *multiparams, **params): 

240 return clauseelement, multiparams, params 

241 

242 return listener.execute( 

243 conn, execute_wrapper, clauseelement, *multiparams, **params 

244 ) 

245 

246 event.listen(self, "before_execute", adapt_execute) 

247 

248 def adapt_cursor_execute( 

249 conn, cursor, statement, parameters, context, executemany 

250 ): 

251 def execute_wrapper(cursor, statement, parameters, context): 

252 return statement, parameters 

253 

254 return listener.cursor_execute( 

255 execute_wrapper, 

256 cursor, 

257 statement, 

258 parameters, 

259 context, 

260 executemany, 

261 ) 

262 

263 event.listen(self, "before_cursor_execute", adapt_cursor_execute) 

264 

265 def do_nothing_callback(*arg, **kw): 

266 pass 

267 

268 def adapt_listener(fn): 

269 def go(conn, *arg, **kw): 

270 fn(conn, do_nothing_callback, *arg, **kw) 

271 

272 return util.update_wrapper(go, fn) 

273 

274 event.listen(self, "begin", adapt_listener(listener.begin)) 

275 event.listen(self, "rollback", adapt_listener(listener.rollback)) 

276 event.listen(self, "commit", adapt_listener(listener.commit)) 

277 event.listen(self, "savepoint", adapt_listener(listener.savepoint)) 

278 event.listen( 

279 self, 

280 "rollback_savepoint", 

281 adapt_listener(listener.rollback_savepoint), 

282 ) 

283 event.listen( 

284 self, 

285 "release_savepoint", 

286 adapt_listener(listener.release_savepoint), 

287 ) 

288 event.listen( 

289 self, "begin_twophase", adapt_listener(listener.begin_twophase) 

290 ) 

291 event.listen( 

292 self, "prepare_twophase", adapt_listener(listener.prepare_twophase) 

293 ) 

294 event.listen( 

295 self, 

296 "rollback_twophase", 

297 adapt_listener(listener.rollback_twophase), 

298 ) 

299 event.listen( 

300 self, "commit_twophase", adapt_listener(listener.commit_twophase) 

301 ) 

302 

303 def execute(self, conn, execute, clauseelement, *multiparams, **params): 

304 """Intercept high level execute() events.""" 

305 

306 return execute(clauseelement, *multiparams, **params) 

307 

308 def cursor_execute( 

309 self, execute, cursor, statement, parameters, context, executemany 

310 ): 

311 """Intercept low-level cursor execute() events.""" 

312 

313 return execute(cursor, statement, parameters, context) 

314 

315 def begin(self, conn, begin): 

316 """Intercept begin() events.""" 

317 

318 return begin() 

319 

320 def rollback(self, conn, rollback): 

321 """Intercept rollback() events.""" 

322 

323 return rollback() 

324 

325 def commit(self, conn, commit): 

326 """Intercept commit() events.""" 

327 

328 return commit() 

329 

330 def savepoint(self, conn, savepoint, name=None): 

331 """Intercept savepoint() events.""" 

332 

333 return savepoint(name=name) 

334 

335 def rollback_savepoint(self, conn, rollback_savepoint, name, context): 

336 """Intercept rollback_savepoint() events.""" 

337 

338 return rollback_savepoint(name, context) 

339 

340 def release_savepoint(self, conn, release_savepoint, name, context): 

341 """Intercept release_savepoint() events.""" 

342 

343 return release_savepoint(name, context) 

344 

345 def begin_twophase(self, conn, begin_twophase, xid): 

346 """Intercept begin_twophase() events.""" 

347 

348 return begin_twophase(xid) 

349 

350 def prepare_twophase(self, conn, prepare_twophase, xid): 

351 """Intercept prepare_twophase() events.""" 

352 

353 return prepare_twophase(xid) 

354 

355 def rollback_twophase(self, conn, rollback_twophase, xid, is_prepared): 

356 """Intercept rollback_twophase() events.""" 

357 

358 return rollback_twophase(xid, is_prepared) 

359 

360 def commit_twophase(self, conn, commit_twophase, xid, is_prepared): 

361 """Intercept commit_twophase() events.""" 

362 

363 return commit_twophase(xid, is_prepared)