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

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

112 statements  

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