unambiguous tracking of all object lifecycle state transitions
in terms of the :class:`.Session` itself, e.g. pending,
transient, persistent, detached. The state of the object
within each event is also defined.
fixes#2677
- Added a new session lifecycle state :term:`deleted`. This new state
represents an object that has been deleted from the :term:`persistent`
state and will move to the :term:`detached` state once the transaction
is committed. This resolves the long-standing issue that objects
which were deleted existed in a gray area between persistent and
detached. The :attr:`.InstanceState.persistent` accessor will
**no longer** report on a deleted object as persistent; the
:attr:`.InstanceState.deleted` accessor will instead be True for
these objects, until they become detached.
- The :paramref:`.Session.weak_identity_map` parameter is deprecated.
See the new recipe at :ref:`session_referencing_behavior` for
an event-based approach to maintaining strong identity map behavior.
references #3517
- ensure that kwargs can be modified in-place within InstanceEvents.init
and that these take effect for the __init__ method.
- improve documentation for these and related events, including
that kwargs can be modified in-place.
as a result of the bugfix for 🎫`3167`,
where attribute and validation events are no longer
called within the flush process. The mutable
extension was relying upon this behavior in the case where a column
level Python-side default were responsible for generating the new value
on INSERT or UPDATE, or when a value were fetched from the RETURNING
clause for "eager defaults" mode. The new value would not be subject
to any event when populated and the mutable extension could not
establish proper coercion or history listening. A new event
:meth:`.InstanceEvents.refresh_flush` is added which the mutable
extension now makes use of for this use case.
fixes#3427
- Added new event :meth:`.InstanceEvents.refresh_flush`, invoked
when an INSERT or UPDATE level default value fetched via RETURNING
or Python-side default is invoked within the flush process. This
is to provide a hook that is no longer present as a result of
🎫`3167`, where attribute and validation events are no longer
called within the flush process.
- Added a new semi-public method to :class:`.MutableBase`
:meth:`.MutableBase._get_listen_keys`. Overriding this method
is needed in the case where a :class:`.MutableBase` subclass needs
events to propagate for attribute keys other than the key to which
the mutable type is associated with, when intercepting the
:meth:`.InstanceEvents.refresh` or
:meth:`.InstanceEvents.refresh_flush` events. The current example of
this is composites using :class:`.MutableComposite`.
event where its invocation was moved to be after the class manager's
instrumentation of the class, which is the opposite of what the
documentation for the event explicitly states. The rationale for the
switch was due to Declarative taking the step of setting up
the full "instrumentation manager" for a class before it was mapped
for the purpose of the new ``@declared_attr`` features
described in :ref:`feature_3150`, but the change was also made
against the classical use of :func:`.mapper` for consistency.
However, SQLSoup relies upon the instrumentation event happening
before any instrumentation under classical mapping.
The behavior is reverted in the case of classical and declarative
mapping, the latter implemented by using a simple memoization
without using class manager.
fixes#3388
changes made to the :class:`.Query` object's collection of entities
to load within the event would render in the SQL, but would not
be reflected during the loading process.
fixes#3387
:meth:`.QueryEvents.before_compile` event allows the creation
of functions which may place additional modifications to
:class:`.Query` objects before the construction of the SELECT
statement. It is hoped that this event be made much more
useful via the advent of a new inspection system that will
allow for detailed modifications to be made against
:class:`.Query` objects in an automated fashion.
fixes#3317
as that of 🎫`3199`, when the ``named=True`` parameter
would be used. Some events would fail to register, and others
would not invoke the event arguments correctly, generally in the
case of when an event was "wrapped" for adaption in some other way.
The "named" mechanics have been rearranged to not interfere with
the argument signature expected by internal wrapper functions.
fixes#3197
if a load() or refresh() event changes history (which...why...but anyway)
the state of the object is the same; currently it seems that history
gets reset but on a refresh, the object still goes into session.dirty
- simplify what we store in partials
any speed improvements :(. code is in a much better place to be run into
C, however
- The ``proc()`` callable passed to the ``create_row_processor()``
method of custom :class:`.Bundle` classes now accepts only a single
"row" argument.
- Deprecated event hooks removed: ``populate_instance``,
``create_instance``, ``translate_row``, ``append_result``
- the getter() idea is somewhat restored; see ref #3175
mapper is implicitly combining one of its column-based attributes
with that of the parent, where those columns normally don't necessarily
share the same value. This is an extension of an existing check that
was added via 🎫`1892`; however this new check emits only a
warning, instead of an exception, to allow for applications that may
be relying upon the existing behavior.
fixes#3042
or :meth:`.MapperEvents.after_configured` events are applied to a
specific mapper or mapped class, as the events are only invoked
for the :class:`.Mapper` target at the general level.
is currently being supported in addition to nose, and will likely
be preferred to nose going forward. The nose plugin system used
by SQLAlchemy has been split out so that it works under pytest as
well. There are no plans to drop support for nose at the moment
and we hope that the test suite itself can continue to remain as
agnostic of testing platform as possible. See the file
README.unittests.rst for updated information on running tests
with pytest.
The test plugin system has also been enhanced to support running
tests against mutiple database URLs at once, by specifying the ``--db``
and/or ``--dburi`` flags multiple times. This does not run the entire test
suite for each database, but instead allows test cases that are specific
to certain backends make use of that backend as the test is run.
When using pytest as the test runner, the system will also run
specific test suites multiple times, once for each database, particularly
those tests within the "dialect suite". The plan is that the enhanced
system will also be used by Alembic, and allow Alembic to run
migration operation tests against multiple backends in one run, including
third-party backends not included within Alembic itself.
Third party dialects and extensions are also encouraged to standardize
on SQLAlchemy's test suite as a basis; see the file README.dialects.rst
for background on building out from SQLAlchemy's test platform.
to a base class such as a declarative base with the propagate=True
flag would fail to apply to existing mapped classes which also
used inheritance due to an assertion. Addtionally, repaired an
attribute error which could occur during removal of such an event,
depending on how it was first assigned. [ticket:2949]
provided via the :func:`.event.remove` function.
[ticket:2268]
- reorganization of event.py module into a package; with the addition of the
docstring work as well as the new registry for removal, there's a lot more code now.
the package separates concerns and provides a top-level doc for each subsection
of functionality
- the remove feature works by providing the EventKey object which associates
the user-provided arguments to listen() with a global, weak-referencing registry.
This registry stores a collection of _ListenerCollection and _DispatchDescriptor
objects associated with each set of arguments, as well as the wrapped function
which was applied to that collection. The EventKey can then be recreated for
a removal, all the _ListenerCollection and _DispatchDescriptor objects are located,
and the correct wrapped function is removed from each one.
with @_legacy_signature, will inspect incoming listener functions
to see if they match an older signature, will wrap into a newer sig
- add an event listen argument named=True, will send all args as
kw args so that event listeners can be written with **kw, any combination
of names
- add a doc system to events that writes out the various calling styles
for a given event, produces deprecation messages automatically.
a little concerned that it's a bit verbose but will look at it up
on RTD for awhile to get a feel.
- change the calling signature for bulk update/delete events - we have
the BulkUD object right there, and there's at least six or seven things
people might want to see, so just send the whole BulkUD in
[ticket:2775]
mapped classes allows that unmapped classes
can be specified for instance- and mapper-events.
The established events will be automatically
set up on subclasses of that class when the
propagate=True flag is passed, and the
events will be set up for that class itself
if and when it is ultimately mapped.
[ticket:2585]
- [bug] The instrumentation events class_instrument(),
class_uninstrument(), and attribute_instrument()
will now fire off only for descendant classes
of the class assigned to listen(). Previously,
an event listener would be assigned to listen
for all classes in all cases regardless of the
"target" argument passed. [ticket:2590]
become an externally usable package but still remains within the main sqlalchemy parent package.
in this system, we use kind of an ugly hack to get the noseplugin imported outside of the
"sqlalchemy" package, while still making it available within sqlalchemy for usage by
third party libraries.
and after_transaction_end
allows tracking of new SessionTransaction objects.
If the object is inspected, can be used to determine
when a session first becomes active and when
it deactivates.
emitted after the object is established
in Session.new or Session.identity_map
upon Session.add(), Session.merge(),
etc., so that the object is represented
in these collections when the event
is called. [ticket:2464]
which would primarily show up as
events not being registered with
sessionmaker() instances created
after the event was associated
with the Session class. [ticket:2424]
event fires unconditionally whenever rollback()
is called, regardless of if an actual DBAPI
level rollback occurred. This event
is specifically designed to allow operations
with the Session to proceed after a rollback
when the Session.is_active is True.
[ticket:2241]
- SessionTransaction is mentioned in public docs, many
more docstrings for events etc. otherwise
access to the cls/self.tables/classes registries
- express orm/_base.py ORMTest in terms of engine/_base.py TablesTest,
factor out common steps into TablesTest, remove AltEngineTest as a
separate class. will further consolidate these base classes
load() event with one too few arguments.
[ticket:2053]
- Added logic which prevents the generation of
events from a MapperExtension or SessionExtension
from generating do-nothing events for all the methods
not overridden. [ticket:2052]
the commit in the case of autocommit=True. This allows
autocommit=True to work appropriately with
expire_on_commit=True, and also allows post-flush session
hooks to operate in the same transactional context
as when autocommit=False. [ticket:2041]