summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/engine/base.py72
-rw-r--r--lib/sqlalchemy/engine/default.py2
-rw-r--r--lib/sqlalchemy/event.py171
-rw-r--r--lib/sqlalchemy/events.py229
4 files changed, 352 insertions, 122 deletions
diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py
index 83ed551af..bf3131994 100644
--- a/lib/sqlalchemy/engine/base.py
+++ b/lib/sqlalchemy/engine/base.py
@@ -63,7 +63,10 @@ class Connection(Connectable):
self.__invalid = False
if _dispatch:
self.dispatch = _dispatch
+ elif engine._has_events:
+ self.dispatch = self.dispatch._join(engine.dispatch)
self._has_events = _has_events or engine._has_events
+
self._echo = self.engine._should_log_info()
if _execution_options:
self._execution_options =\
@@ -429,7 +432,6 @@ class Connection(Connectable):
if self._has_events:
self.dispatch.begin(self)
- self.engine.dispatch.begin(self)
try:
self.engine.dialect.do_begin(self.connection)
@@ -440,7 +442,6 @@ class Connection(Connectable):
def _rollback_impl(self):
if self._has_events:
self.dispatch.rollback(self)
- self.engine.dispatch.rollback(self)
if self._still_open_and_connection_is_valid:
if self._echo:
@@ -457,7 +458,6 @@ class Connection(Connectable):
def _commit_impl(self):
if self._has_events:
self.dispatch.commit(self)
- self.engine.dispatch.commit(self)
if self._echo:
self.engine.logger.info("COMMIT")
@@ -471,7 +471,6 @@ class Connection(Connectable):
def _savepoint_impl(self, name=None):
if self._has_events:
self.dispatch.savepoint(self, name)
- self.engine.dispatch.savepoint(self, name)
if name is None:
self.__savepoint_seq += 1
@@ -483,7 +482,6 @@ class Connection(Connectable):
def _rollback_to_savepoint_impl(self, name, context):
if self._has_events:
self.dispatch.rollback_savepoint(self, name, context)
- self.engine.dispatch.rollback_savepoint(self, name, context)
if self._still_open_and_connection_is_valid:
self.engine.dialect.do_rollback_to_savepoint(self, name)
@@ -492,7 +490,6 @@ class Connection(Connectable):
def _release_savepoint_impl(self, name, context):
if self._has_events:
self.dispatch.release_savepoint(self, name, context)
- self.engine.dispatch.release_savepoint(self, name, context)
if self._still_open_and_connection_is_valid:
self.engine.dialect.do_release_savepoint(self, name)
@@ -501,7 +498,6 @@ class Connection(Connectable):
def _begin_twophase_impl(self, xid):
if self._has_events:
self.dispatch.begin_twophase(self, xid)
- self.engine.dispatch.begin_twophase(self, xid)
if self._still_open_and_connection_is_valid:
self.engine.dialect.do_begin_twophase(self, xid)
@@ -509,7 +505,6 @@ class Connection(Connectable):
def _prepare_twophase_impl(self, xid):
if self._has_events:
self.dispatch.prepare_twophase(self, xid)
- self.engine.dispatch.prepare_twophase(self, xid)
if self._still_open_and_connection_is_valid:
assert isinstance(self.__transaction, TwoPhaseTransaction)
@@ -518,7 +513,6 @@ class Connection(Connectable):
def _rollback_twophase_impl(self, xid, is_prepared):
if self._has_events:
self.dispatch.rollback_twophase(self, xid, is_prepared)
- self.engine.dispatch.rollback_twophase(self, xid, is_prepared)
if self._still_open_and_connection_is_valid:
assert isinstance(self.__transaction, TwoPhaseTransaction)
@@ -528,7 +522,6 @@ class Connection(Connectable):
def _commit_twophase_impl(self, xid, is_prepared):
if self._has_events:
self.dispatch.commit_twophase(self, xid, is_prepared)
- self.engine.dispatch.commit_twophase(self, xid, is_prepared)
if self._still_open_and_connection_is_valid:
assert isinstance(self.__transaction, TwoPhaseTransaction)
@@ -658,10 +651,7 @@ class Connection(Connectable):
"""Execute a schema.ColumnDefault object."""
if self._has_events:
- for fn in chain(
- self.dispatch.before_execute,
- self.engine.dispatch.before_execute
- ):
+ for fn in self.dispatch.before_execute:
default, multiparams, params = \
fn(self, default, multiparams, params)
@@ -685,8 +675,6 @@ class Connection(Connectable):
if self._has_events:
self.dispatch.after_execute(self,
default, multiparams, params, ret)
- self.engine.dispatch.after_execute(self,
- default, multiparams, params, ret)
return ret
@@ -694,10 +682,7 @@ class Connection(Connectable):
"""Execute a schema.DDL object."""
if self._has_events:
- for fn in chain(
- self.dispatch.before_execute,
- self.engine.dispatch.before_execute
- ):
+ for fn in self.dispatch.before_execute:
ddl, multiparams, params = \
fn(self, ddl, multiparams, params)
@@ -712,7 +697,7 @@ class Connection(Connectable):
compiled
)
if self._has_events:
- self.engine.dispatch.after_execute(self,
+ self.dispatch.after_execute(self,
ddl, multiparams, params, ret)
return ret
@@ -720,10 +705,7 @@ class Connection(Connectable):
"""Execute a sql.ClauseElement object."""
if self._has_events:
- for fn in chain(
- self.dispatch.before_execute,
- self.engine.dispatch.before_execute
- ):
+ for fn in self.dispatch.before_execute:
elem, multiparams, params = \
fn(self, elem, multiparams, params)
@@ -759,18 +741,13 @@ class Connection(Connectable):
if self._has_events:
self.dispatch.after_execute(self,
elem, multiparams, params, ret)
- self.engine.dispatch.after_execute(self,
- elem, multiparams, params, ret)
return ret
def _execute_compiled(self, compiled, multiparams, params):
"""Execute a sql.Compiled object."""
if self._has_events:
- for fn in chain(
- self.dispatch.before_execute,
- self.engine.dispatch.before_execute
- ):
+ for fn in self.dispatch.before_execute:
compiled, multiparams, params = \
fn(self, compiled, multiparams, params)
@@ -786,18 +763,13 @@ class Connection(Connectable):
if self._has_events:
self.dispatch.after_execute(self,
compiled, multiparams, params, ret)
- self.engine.dispatch.after_execute(self,
- compiled, multiparams, params, ret)
return ret
def _execute_text(self, statement, multiparams, params):
"""Execute a string SQL statement."""
if self._has_events:
- for fn in chain(
- self.dispatch.before_execute,
- self.engine.dispatch.before_execute
- ):
+ for fn in self.dispatch.before_execute:
statement, multiparams, params = \
fn(self, statement, multiparams, params)
@@ -813,8 +785,6 @@ class Connection(Connectable):
if self._has_events:
self.dispatch.after_execute(self,
statement, multiparams, params, ret)
- self.engine.dispatch.after_execute(self,
- statement, multiparams, params, ret)
return ret
def _execute_context(self, dialect, constructor,
@@ -847,10 +817,7 @@ class Connection(Connectable):
parameters = parameters[0]
if self._has_events:
- for fn in chain(
- self.dispatch.before_cursor_execute,
- self.engine.dispatch.before_cursor_execute
- ):
+ for fn in self.dispatch.before_cursor_execute:
statement, parameters = \
fn(self, cursor, statement, parameters,
context, context.executemany)
@@ -893,11 +860,6 @@ class Connection(Connectable):
parameters,
context,
context.executemany)
- self.engine.dispatch.after_cursor_execute(self, cursor,
- statement,
- parameters,
- context,
- context.executemany)
if context.compiled:
context.post_exec()
@@ -929,7 +891,7 @@ class Connection(Connectable):
return result
- def _cursor_execute(self, cursor, statement, parameters):
+ def _cursor_execute(self, cursor, statement, parameters, context=None):
"""Execute a statement + params on the given cursor.
Adds appropriate logging and exception handling.
@@ -940,6 +902,12 @@ class Connection(Connectable):
terminates at _execute_context().
"""
+ if self._has_events:
+ for fn in self.dispatch.before_cursor_execute:
+ statement, parameters = \
+ fn(self, cursor, statement, parameters,
+ context, context.executemany)
+
if self._echo:
self.engine.logger.info(statement)
self.engine.logger.info("%r", parameters)
@@ -1006,12 +974,6 @@ class Connection(Connectable):
parameters,
context,
e)
- self.engine.dispatch.dbapi_error(self,
- cursor,
- statement,
- parameters,
- context,
- e)
context.handle_dbapi_exception(e)
is_disconnect = isinstance(e, self.dialect.dbapi.Error) and \
diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py
index 8518cf0da..1c74dab43 100644
--- a/lib/sqlalchemy/engine/default.py
+++ b/lib/sqlalchemy/engine/default.py
@@ -597,7 +597,7 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
else:
default_params = {}
- conn._cursor_execute(self.cursor, stmt, default_params)
+ conn._cursor_execute(self.cursor, stmt, default_params, context=self)
r = self.cursor.fetchone()[0]
if type_ is not None:
# apply type post processors to the result
diff --git a/lib/sqlalchemy/event.py b/lib/sqlalchemy/event.py
index 8e9064cfc..ee4c0ad32 100644
--- a/lib/sqlalchemy/event.py
+++ b/lib/sqlalchemy/event.py
@@ -7,6 +7,7 @@
"""Base event API."""
from . import util, exc
+from itertools import chain
CANCEL = util.symbol('CANCEL')
NO_RETVAL = util.symbol('NO_RETVAL')
@@ -37,7 +38,7 @@ def listen(target, identifier, fn, *args, **kw):
tgt.dispatch._listen(tgt, identifier, fn, *args, **kw)
return
raise exc.InvalidRequestError("No such event '%s' for target '%s'" %
- (identifier,target))
+ (identifier, target))
def listens_for(target, identifier, *args, **kw):
"""Decorate a function as a listener for the given target + identifier.
@@ -69,7 +70,7 @@ def remove(target, identifier, fn):
"""
for evt_cls in _registrars[identifier]:
for tgt in evt_cls._accept_with(target):
- tgt.dispatch._remove(identifier, tgt, fn, *args, **kw)
+ tgt.dispatch._remove(identifier, tgt, fn)
return
_registrars = util.defaultdict(list)
@@ -112,6 +113,30 @@ class _Dispatch(object):
def __init__(self, _parent_cls):
self._parent_cls = _parent_cls
+ def _join(self, other):
+ """Create a 'join' of this :class:`._Dispatch` and another.
+
+ This new dispatcher will dispatch events to both
+ :class:`._Dispatch` objects.
+
+ Once constructed, the joined dispatch will respond to new events
+ added to this dispatcher, but may not be aware of events
+ added to the other dispatcher after creation of the join. This is
+ currently for performance reasons so that both dispatchers need
+ not be "evaluated" fully on each call.
+
+ """
+ if '_joined_dispatch_cls' not in self.__class__.__dict__:
+ cls = type(
+ "Joined%s" % self.__class__.__name__,
+ (_JoinedDispatcher, self.__class__), {}
+ )
+ for ls in _event_descriptors(self):
+ setattr(cls, ls.name, _JoinedDispatchDescriptor(ls.name))
+
+ self.__class__._joined_dispatch_cls = cls
+ return self._joined_dispatch_cls(self, other)
+
def __reduce__(self):
return _UnpickleDispatch(), (self._parent_cls, )
@@ -276,6 +301,7 @@ class _DispatchDescriptor(object):
obj.__dict__[self.__name__] = ret
return ret
+
class _EmptyListener(object):
"""Serves as a class-level interface to the events
served by a _DispatchDescriptor, when there are no
@@ -303,8 +329,9 @@ class _EmptyListener(object):
and returns it.
"""
- obj.__dict__[self.name] = result = _ListenerCollection(
- self.parent, obj._parent_cls)
+ result = _ListenerCollection(self.parent, obj._parent_cls)
+ if obj.__dict__[self.name] is self:
+ obj.__dict__[self.name] = result
return result
def _needs_modify(self, *args, **kw):
@@ -324,14 +351,47 @@ class _EmptyListener(object):
def __iter__(self):
return iter(self.parent_listeners)
- def __getitem__(self, index):
- return (self.parent_listeners)[index]
+ def __nonzero__(self):
+ return False
+
+class _CompoundListener(object):
+ _exec_once = False
+
+ def exec_once(self, *args, **kw):
+ """Execute this event, but only if it has not been
+ executed already for this collection."""
+
+ if not self._exec_once:
+ self(*args, **kw)
+ self._exec_once = True
+
+ # I'm not entirely thrilled about the overhead here,
+ # but this allows class-level listeners to be added
+ # at any point.
+ #
+ # In the absense of instance-level listeners,
+ # we stay with the _EmptyListener object when called
+ # at the instance level.
+
+ def __call__(self, *args, **kw):
+ """Execute this event."""
+
+ for fn in self.parent_listeners:
+ fn(*args, **kw)
+ for fn in self.listeners:
+ fn(*args, **kw)
+
+ def __len__(self):
+ return len(self.parent_listeners) + len(self.listeners)
+
+ def __iter__(self):
+ return chain(self.parent_listeners, self.listeners)
def __nonzero__(self):
- return bool(self.listeners)
+ return bool(self.listeners or self.parent_listeners)
-class _ListenerCollection(object):
+class _ListenerCollection(_CompoundListener):
"""Instance-level attributes on instances of :class:`._Dispatch`.
Represents a collection of listeners.
@@ -341,8 +401,6 @@ class _ListenerCollection(object):
"""
- _exec_once = False
-
def __init__(self, parent, target_cls):
if target_cls not in parent._clslevel:
parent.update_subclass(target_cls)
@@ -360,42 +418,6 @@ class _ListenerCollection(object):
"""
return self
- def exec_once(self, *args, **kw):
- """Execute this event, but only if it has not been
- executed already for this collection."""
-
- if not self._exec_once:
- self(*args, **kw)
- self._exec_once = True
-
- def __call__(self, *args, **kw):
- """Execute this event."""
-
- for fn in self.parent_listeners:
- fn(*args, **kw)
- for fn in self.listeners:
- fn(*args, **kw)
-
- # I'm not entirely thrilled about the overhead here,
- # but this allows class-level listeners to be added
- # at any point.
- #
- # In the absense of instance-level listeners,
- # we stay with the _EmptyListener object when called
- # at the instance level.
-
- def __len__(self):
- return len(self.parent_listeners + self.listeners)
-
- def __iter__(self):
- return iter(self.parent_listeners + self.listeners)
-
- def __getitem__(self, index):
- return (self.parent_listeners + self.listeners)[index]
-
- def __nonzero__(self):
- return bool(self.listeners or self.parent_listeners)
-
def _update(self, other, only_propagate=True):
"""Populate from the listeners in another :class:`_Dispatch`
object."""
@@ -430,6 +452,62 @@ class _ListenerCollection(object):
self.listeners[:] = []
self.propagate.clear()
+
+class _JoinedDispatcher(object):
+ """Represent a connection between two _Dispatch objects."""
+
+ def __init__(self, local, parent):
+ self.local = local
+ self.parent = parent
+ self._parent_cls = local._parent_cls
+
+
+class _JoinedDispatchDescriptor(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __get__(self, obj, cls):
+ if obj is None:
+ return self
+ else:
+ obj.__dict__[self.name] = ret = _JoinedListener(
+ obj.parent, self.name,
+ getattr(obj.local, self.name)
+ )
+ return ret
+
+class _JoinedListener(_CompoundListener):
+ _exec_once = False
+ def __init__(self, parent, name, local):
+ self.parent = parent
+ self.name = name
+ self.local = local
+ self.parent_listeners = self.local
+
+ # fix .listeners for the parent. This means
+ # new events added to the parent won't be picked
+ # up here. Alternatively, the listeners can
+ # be via @property to just return getattr(self.parent, self.name)
+ # each time. less performant.
+ self.listeners = list(getattr(self.parent, self.name))
+
+ def for_modify(self, obj):
+ self.local = self.parent_listeners = self.local.for_modify(obj)
+ return self
+
+ def insert(self, obj, target, propagate):
+ self.local.insert(obj, target, propagate)
+
+ def append(self, obj, target, propagate):
+ self.local.append(obj, target, propagate)
+
+ def remove(self, obj, target):
+ self.local.remove(obj, target)
+
+ def clear(self):
+ raise NotImplementedError()
+
+
class dispatcher(object):
"""Descriptor used by target classes to
deliver the _Dispatch class at the class level
@@ -446,3 +524,4 @@ class dispatcher(object):
return self.dispatch_cls
obj.__dict__['dispatch'] = disp = self.dispatch_cls(cls)
return disp
+
diff --git a/lib/sqlalchemy/events.py b/lib/sqlalchemy/events.py
index 10717ee50..61392ea62 100644
--- a/lib/sqlalchemy/events.py
+++ b/lib/sqlalchemy/events.py
@@ -341,18 +341,56 @@ class ConnectionEvents(event.Events):
The methods here define the name of an event as well as the names of
members that are passed to listener functions.
- An event listener can be associated with any :class:`.Connectable`,
- such as an :class:`.Engine`, e.g.::
+ An event listener can be associated with any :class:`.Connectable`
+ class or instance, such as an :class:`.Engine`, e.g.::
from sqlalchemy import event, create_engine
- def before_execute(conn, clauseelement, multiparams, params):
- log.info("Received statement: %s" % clauseelement)
+ def before_cursor_execute(conn, cursor, statement, parameters, context,
+ executemany):
+ log.info("Received statement: %s" % statement)
engine = create_engine('postgresql://scott:tiger@localhost/test')
- event.listen(engine, "before_execute", before_execute)
+ event.listen(engine, "before_cursor_execute", before_cursor_execute)
- Some events allow modifiers to the :func:`.event.listen` function.
+ or with a specific :class:`.Connection`::
+
+ with engine.begin() as conn:
+ @event.listens_for(conn, 'before_cursor_execute')
+ def before_cursor_execute(conn, cursor, statement, parameters,
+ context, executemany):
+ log.info("Received statement: %s" % statement)
+
+ The :meth:`.before_execute` and :meth:`.before_cursor_execute`
+ events can also be established with the ``retval=True`` flag, which
+ allows modification of the statement and parameters to be sent
+ to the database. The :meth:`.before_cursor_execute` event is
+ particularly useful here to add ad-hoc string transformations, such
+ as comments, to all executions::
+
+ from sqlalchemy.engine import Engine
+ from sqlalchemy import event
+
+ @event.listens_for(Engine, "before_cursor_execute", retval=True)
+ def comment_sql_calls(conn, cursor, statement, parameters,
+ context, executemany):
+ statement = statement + " -- some comment"
+ return statement, parameters
+
+ .. note:: :class:`.ConnectionEvents` can be established on any
+ combination of :class:`.Engine`, :class:`.Connection`, as well
+ as instances of each of those classes. Events across all
+ four scopes will fire off for a given instance of
+ :class:`.Connection`. However, for performance reasons, the
+ :class:`.Connection` object determines at instantiation time
+ whether or not its parent :class:`.Engine` has event listeners
+ established. Event listeners added to the :class:`.Engine`
+ class or to an instance of :class:`.Engine` *after* the instantiation
+ of a dependent :class:`.Connection` instance will usually
+ *not* be available on that :class:`.Connection` instance. The newly
+ added listeners will instead take effect for :class:`.Connection`
+ instances created subsequent to those event listeners being
+ established on the parent :class:`.Engine` class or instance.
:param retval=False: Applies to the :meth:`.before_execute` and
:meth:`.before_cursor_execute` events only. When True, the
@@ -400,18 +438,107 @@ class ConnectionEvents(event.Events):
event.Events._listen(target, identifier, fn)
def before_execute(self, conn, clauseelement, multiparams, params):
- """Intercept high level execute() events."""
+ """Intercept high level execute() events, receiving uncompiled
+ SQL constructs and other objects prior to rendering into SQL.
+
+ This event is good for debugging SQL compilation issues as well
+ as early manipulation of the parameters being sent to the database,
+ as the parameter lists will be in a consistent format here.
+
+ This event can be optionally established with the ``retval=True``
+ flag. The ``clauseelement``, ``multiparams``, and ``params``
+ arguments should be returned as a three-tuple in this case::
+
+ @event.listens_for(Engine, "before_execute", retval=True)
+ def before_execute(conn, conn, clauseelement, multiparams, params):
+ # do something with clauseelement, multiparams, params
+ return clauseelement, multiparams, params
+
+ :param conn: :class:`.Connection` object
+ :param clauseelement: SQL expression construct, :class:`.Compiled`
+ instance, or string statement passed to :meth:`.Connection.execute`.
+ :param multiparams: Multiple parameter sets, a list of dictionaries.
+ :param params: Single parameter set, a single dictionary.
+
+ See also:
+
+ :meth:`.before_cursor_execute`
+
+ """
def after_execute(self, conn, clauseelement, multiparams, params, result):
- """Intercept high level execute() events."""
+ """Intercept high level execute() events after execute.
+
+
+ :param conn: :class:`.Connection` object
+ :param clauseelement: SQL expression construct, :class:`.Compiled`
+ instance, or string statement passed to :meth:`.Connection.execute`.
+ :param multiparams: Multiple parameter sets, a list of dictionaries.
+ :param params: Single parameter set, a single dictionary.
+ :param result: :class:`.ResultProxy` generated by the execution.
+
+ """
def before_cursor_execute(self, conn, cursor, statement,
parameters, context, executemany):
- """Intercept low-level cursor execute() events."""
+ """Intercept low-level cursor execute() events before execution,
+ receiving the string
+ SQL statement and DBAPI-specific parameter list to be invoked
+ against a cursor.
+
+ This event is a good choice for logging as well as late modifications
+ to the SQL string. It's less ideal for parameter modifications except
+ for those which are specific to a target backend.
+
+ This event can be optionally established with the ``retval=True``
+ flag. The ``statement`` and ``parameters`` arguments should be
+ returned as a two-tuple in this case::
+
+ @event.listens_for(Engine, "before_cursor_execute", retval=True)
+ def before_cursor_execute(conn, cursor, statement,
+ parameters, context, executemany):
+ # do something with statement, parameters
+ return statement, parameters
+
+ See the example at :class:`.ConnectionEvents`.
+
+ :param conn: :class:`.Connection` object
+ :param cursor: DBAPI cursor object
+ :param statement: string SQL statement
+ :param parameters: Dictionary, tuple, or list of parameters being
+ passed to the ``execute()`` or ``executemany()`` method of the
+ DBAPI ``cursor``. In some cases may be ``None``.
+ :param context: :class:`.ExecutionContext` object in use. May
+ be ``None``.
+ :param executemany: boolean, if ``True``, this is an ``executemany()``
+ call, if ``False``, this is an ``execute()`` call.
+
+ See also:
+
+ :meth:`.before_execute`
+
+ :meth:`.after_cursor_execute`
+
+ """
def after_cursor_execute(self, conn, cursor, statement,
parameters, context, executemany):
- """Intercept low-level cursor execute() events."""
+ """Intercept low-level cursor execute() events after execution.
+
+ :param conn: :class:`.Connection` object
+ :param cursor: DBAPI cursor object. Will have results pending
+ if the statement was a SELECT, but these should not be consumed
+ as they will be needed by the :class:`.ResultProxy`.
+ :param statement: string SQL statement
+ :param parameters: Dictionary, tuple, or list of parameters being
+ passed to the ``execute()`` or ``executemany()`` method of the
+ DBAPI ``cursor``. In some cases may be ``None``.
+ :param context: :class:`.ExecutionContext` object in use. May
+ be ``None``.
+ :param executemany: boolean, if ``True``, this is an ``executemany()``
+ call, if ``False``, this is an ``execute()`` call.
+
+ """
def dbapi_error(self, conn, cursor, statement, parameters,
context, exception):
@@ -439,37 +566,99 @@ class ConnectionEvents(event.Events):
exception is then wrapped in a SQLAlchemy DBAPI exception
wrapper and re-thrown.
+ :param conn: :class:`.Connection` object
+ :param cursor: DBAPI cursor object
+ :param statement: string SQL statement
+ :param parameters: Dictionary, tuple, or list of parameters being
+ passed to the ``execute()`` or ``executemany()`` method of the
+ DBAPI ``cursor``. In some cases may be ``None``.
+ :param context: :class:`.ExecutionContext` object in use. May
+ be ``None``.
+ :param exception: The **unwrapped** exception emitted directly from the
+ DBAPI. The class here is specific to the DBAPI module in use.
+
.. versionadded:: 0.7.7
"""
def begin(self, conn):
- """Intercept begin() events."""
+ """Intercept begin() events.
+
+ :param conn: :class:`.Connection` object
+
+ """
def rollback(self, conn):
- """Intercept rollback() events."""
+ """Intercept rollback() events.
+
+ :param conn: :class:`.Connection` object
+
+ """
def commit(self, conn):
- """Intercept commit() events."""
+ """Intercept commit() events.
+
+ :param conn: :class:`.Connection` object
+ """
def savepoint(self, conn, name=None):
- """Intercept savepoint() events."""
+ """Intercept savepoint() events.
+
+ :param conn: :class:`.Connection` object
+ :param name: specified name used for the savepoint.
+
+ """
def rollback_savepoint(self, conn, name, context):
- """Intercept rollback_savepoint() events."""
+ """Intercept rollback_savepoint() events.
+
+ :param conn: :class:`.Connection` object
+ :param name: specified name used for the savepoint.
+ :param context: :class:`.ExecutionContext` in use. May be ``None``.
+
+ """
def release_savepoint(self, conn, name, context):
- """Intercept release_savepoint() events."""
+ """Intercept release_savepoint() events.
+
+ :param conn: :class:`.Connection` object
+ :param name: specified name used for the savepoint.
+ :param context: :class:`.ExecutionContext` in use. May be ``None``.
+
+ """
def begin_twophase(self, conn, xid):
- """Intercept begin_twophase() events."""
+ """Intercept begin_twophase() events.
+
+ :param conn: :class:`.Connection` object
+ :param xid: two-phase XID identifier
+
+ """
def prepare_twophase(self, conn, xid):
- """Intercept prepare_twophase() events."""
+ """Intercept prepare_twophase() events.
+
+ :param conn: :class:`.Connection` object
+ :param xid: two-phase XID identifier
+ """
def rollback_twophase(self, conn, xid, is_prepared):
- """Intercept rollback_twophase() events."""
+ """Intercept rollback_twophase() events.
+
+ :param conn: :class:`.Connection` object
+ :param xid: two-phase XID identifier
+ :param is_prepared: boolean, indicates if
+ :meth:`.TwoPhaseTransaction.prepare` was called.
+
+ """
def commit_twophase(self, conn, xid, is_prepared):
- """Intercept commit_twophase() events."""
+ """Intercept commit_twophase() events.
+
+ :param conn: :class:`.Connection` object
+ :param xid: two-phase XID identifier
+ :param is_prepared: boolean, indicates if
+ :meth:`.TwoPhaseTransaction.prepare` was called.
+
+ """