for ls in other.descriptors:
getattr(self, ls.name).update(ls)
- #existing_listeners = getattr(self, ls.name).listeners
- #existing_listener_set = set(existing_listeners)
- #existing_listeners.extend([l for l
- # in ls.listeners
- # if l not in existing_listener_set])
class _EventMeta(type):
"""Intercept new Event subclasses and create
"""Called when an attribute is instrumented."""
class InstanceEvents(event.Events):
+ """Define events specific to object lifecycle.
+ Instance-level don't automatically propagate their associations
+ to subclasses.
+
+ """
@classmethod
def accept_with(cls, target):
from sqlalchemy.orm.instrumentation import ClassManager, manager_of_class
@classmethod
def listen(cls, fn, identifier, target, raw=False):
if not raw:
- fn = _to_instance(fn)
+ orig_fn = fn
+ def wrap(state, *arg, **kw):
+ return orig_fn(state.obj(), *arg, **kw)
+ fn = wrap
event.Events.listen(fn, identifier, target)
-
+
@classmethod
def remove(cls, fn, identifier, target):
raise NotImplementedError("Removal of instance events not yet implemented")
event.Events.listen(fn, identifier, target)
if propagate:
+
+ raise NotImplementedError()
+
# TODO: for removal, need to implement
# packaging this info for operation in reverse.
if impl is not target:
event.Events.listen(fn, identifier, impl)
- def configure_listener(class_, key, inst):
- event.Events.listen(fn, identifier, inst)
- event.listen(configure_listener, 'on_attribute_instrument', class_)
@classmethod
def remove(cls, fn, identifier, target):
"""
-@util.decorator
-def _to_instance(fn, state, *arg, **kw):
- """Marshall the :class:`.InstanceState` argument to an instance."""
-
- return fn(state.obj(), *arg, **kw)
-
if key in self.mutable_attributes:
self.mutable_attributes.remove(key)
for cls in self.class_.__subclasses__():
- manager = self._subclass_manager(cls)
- manager.uninstrument_attribute(key, True)
+ manager = manager_of_class(cls)
+ if manager:
+ manager.uninstrument_attribute(key, True)
def unregister(self):
"""remove all instrumentation established by this ClassManager."""
return
event.listen(_event_on_init, 'on_init', manager, raw=True)
- event.listen(_event_on_init_failure, 'on_init_failure', manager, raw=True)
event.listen(_event_on_resurrect, 'on_resurrect', manager, raw=True)
for key, method in util.iterate_attributes(self.class_):
def _event_on_init(state, args, kwargs):
"""Trigger mapper compilation and run init_instance hooks."""
- instrumenting_mapper = state.manager.info[_INSTRUMENTOR]
- # compile() always compiles all mappers
- instrumenting_mapper.compile()
-
-def _event_on_init_failure(state, args, kwargs):
- """Run init_failed hooks."""
-
- instrumenting_mapper = state.manager.info[_INSTRUMENTOR]
+ instrumenting_mapper = state.manager.info.get(_INSTRUMENTOR)
+ if instrumenting_mapper:
+ # compile() always compiles all mappers
+ instrumenting_mapper.compile()
def _event_on_resurrect(state):
# re-populate the primary key elements
# of the dict based on the mapping.
- instrumenting_mapper = state.manager.info[_INSTRUMENTOR]
- for col, val in zip(instrumenting_mapper.primary_key, state.key[1]):
- instrumenting_mapper._set_state_attr_by_column(
- state, state.dict, col, val)
+ instrumenting_mapper = state.manager.info.get(_INSTRUMENTOR)
+ if instrumenting_mapper:
+ for col, val in zip(instrumenting_mapper.primary_key, state.key[1]):
+ instrumenting_mapper._set_state_attr_by_column(
+ state, state.dict, col, val)
def _sort_states(states):