]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- reorganize events into cls->dispatch, which is an instance of _Dispatch.
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 10 Aug 2010 04:19:50 +0000 (00:19 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 10 Aug 2010 04:19:50 +0000 (00:19 -0400)
cut down on extraneous stuff, cleanup
The Event class never gets instantiated and its methods stay the same
so that sphinx can get to it.

lib/sqlalchemy/event.py
lib/sqlalchemy/orm/attributes.py
lib/sqlalchemy/orm/state.py
test/engine/test_pool.py

index bfa617a25b8a9de0fcbb665778172186744133cb..21f05a1c9540e5555dc4bd8b8c1f25d34e579088 100644 (file)
@@ -16,26 +16,17 @@ def listen(fn, identifier, target, *args, **kw):
     
     for evt_cls in _registrars[identifier]:
         for tgt in evt_cls.accept_with(target):
-            
-            tgt.dispatch.events.listen(fn, identifier, tgt, *args, **kw)
+            tgt.dispatch.listen(fn, identifier, tgt, *args, **kw)
             break
     
-class _DispatchMeta(type):
-    def __init__(cls, classname, bases, dict_):
-        
-        dispatch_base = getattr(cls, 'dispatch', Dispatch)
-        cls.dispatch = dispatch_cls = type("%sDispatch" % classname, (dispatch_base, ), {})
-        dispatch_cls.events = cls
-        for k in dict_:
-            if k.startswith('on_'):
-                setattr(dispatch_cls, k, EventDescriptor(dict_[k]))
-                _registrars[k].append(cls)
-        return type.__init__(cls, classname, bases, dict_)
-
 _registrars = util.defaultdict(list)
 
-class Dispatch(object):
-
+class _Dispatch(object):
+    """Mirror the event listening definitions of an Events class with 
+    listener collections.
+    
+    """
+    
     def __init__(self, parent_cls):
         self.parent_cls = parent_cls
     
@@ -49,9 +40,33 @@ class Dispatch(object):
         for ls in other.descriptors:
             getattr(self, ls.name).listeners.extend(ls.listeners)
 
+class _EventMeta(type):
+    """Intercept new Event subclasses and create 
+    associated _Dispatch classes."""
+    
+    def __init__(cls, classname, bases, dict_):
+        _create_dispatcher_class(cls, classname, bases, dict_)
+        return type.__init__(cls, classname, bases, dict_)
+        
+def _create_dispatcher_class(cls, classname, bases, dict_):
+    # there's all kinds of ways to do this,
+    # i.e. make a Dispatch class that shares the 'listen' method
+    # of the Event class, this is the straight monkeypatch.
+    dispatch_base = getattr(cls, 'dispatch', _Dispatch)
+    cls.dispatch = dispatch_cls = type("%sDispatch" % classname, 
+                                        (dispatch_base, ), {})
+    dispatch_cls.listen = cls.listen
+
+    for k in dict_:
+        if k.startswith('on_'):
+            setattr(dispatch_cls, k, _DispatchDescriptor(dict_[k]))
+            _registrars[k].append(cls)
 
 class Events(object):
-    __metaclass__ = _DispatchMeta
+    """Define event listening functions for a particular target type."""
+    
+    
+    __metaclass__ = _EventMeta
     
     @classmethod
     def accept_with(cls, target):
@@ -69,46 +84,12 @@ class Events(object):
     @classmethod
     def listen(cls, fn, identifier, target):
         getattr(target.dispatch, identifier).append(fn, target)
-        
 
 
-class _ExecEvent(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
-    
-    def exec_until_return(self, *args, **kw):
-        """Execute listeners for this event until
-        one returns a non-None value.
-        
-        Returns the value, or None.
-        """
-        
-        if self:
-            for fn in self:
-                r = fn(*args, **kw)
-                if r is not None:
-                    return r
-        return None
-        
-    def __call__(self, *args, **kw):
-        """Execute this event."""
-        
-        if self:
-            for fn in self:
-                fn(*args, **kw)
     
-class EventDescriptor(object):
-    """Represent an event type associated with a :class:`Events` class
-    as well as class-level listeners.
+class _DispatchDescriptor(object):
+    """Class-level attributes on _Dispatch classes."""
     
-    """
     def __init__(self, fn):
         self.__name__ = fn.__name__
         self.__doc__ = fn.__doc__
@@ -117,23 +98,58 @@ class EventDescriptor(object):
     def append(self, obj, target):
         assert isinstance(target, type), \
                 "Class-level Event targets must be classes."
+                
         for cls in [target] + target.__subclasses__():
             self._clslevel[cls].append(obj)
     
     def __get__(self, obj, cls):
         if obj is None:
             return self
-        obj.__dict__[self.__name__] = result = Listeners(self, obj.parent_cls)
+        obj.__dict__[self.__name__] = result = \
+                            _ListenerCollection(self, obj.parent_cls)
         return result
 
-class Listeners(_ExecEvent):
+class _ListenerCollection(object):
     """Represent a collection of listeners linked
-    to an instance of :class:`Events`."""
+    to an instance of _Dispatch.
+    
+    """
+
+    _exec_once = False
     
     def __init__(self, parent, target_cls):
         self.parent_listeners = parent._clslevel[target_cls]
         self.name = parent.__name__
         self.listeners = []
+
+    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 exec_until_return(self, *args, **kw):
+        """Execute listeners for this event until
+        one returns a non-None value.
+
+        Returns the value, or None.
+        """
+
+        if self:
+            for fn in self:
+                r = fn(*args, **kw)
+                if r is not None:
+                    return r
+        return None
+
+    def __call__(self, *args, **kw):
+        """Execute this event."""
+
+        if self:
+            for fn in self:
+                fn(*args, **kw)
     
     # I'm not entirely thrilled about the overhead here,
     # but this allows class-level listeners to be added
@@ -156,9 +172,16 @@ class Listeners(_ExecEvent):
             self.listeners.append(obj)
 
 class dispatcher(object):
+    """Descriptor used by target classes to 
+    deliver the _Dispatch class at the class level
+    and produce new _Dispatch instances for target
+    instances.
+    
+    """
     def __init__(self, events):
         self.dispatch_cls = events.dispatch
         
+        
     def __get__(self, obj, cls):
         if obj is None:
             return self.dispatch_cls
index 9d454a7b283da11a21188bb38bf48d692b21631d..729968940b14bc5cc2485ad6169990b0767d642a 100644 (file)
@@ -129,7 +129,7 @@ class QueryableAttribute(interfaces.PropComparator):
         @classmethod
         def listen(cls, fn, identifier, target, active_history=False):
             if active_history:
-                target.events.active_history = True
+                target.active_history = True
             event.Events.listen(fn, identifier, target)
             
         def on_append(self, state, value, initiator):
@@ -154,8 +154,8 @@ class QueryableAttribute(interfaces.PropComparator):
             set.
 
             """
-
-    events = event.dispatcher(events)
+    dispatch = event.dispatcher(events)
+    
 
     def get_history(self, instance, **kwargs):
         return self.impl.get_history(instance_state(instance),
@@ -289,7 +289,7 @@ class AttributeImpl(object):
     """internal implementation for instrumented attributes."""
 
     def __init__(self, class_, key,
-                    callable_, events, trackparent=False, extension=None,
+                    callable_, dispatch, trackparent=False, extension=None,
                     compare_function=None, active_history=False, 
                     parent_token=None, expire_missing=True,
                     **kwargs):
@@ -307,9 +307,6 @@ class AttributeImpl(object):
           collection attribute when it's first accessed, if not present
           already.
 
-        events
-          The :class:`Events` object used to track events.
-          
         trackparent
           if True, attempt to track if an instance has a parent attached
           to it via this attribute.
@@ -342,7 +339,8 @@ class AttributeImpl(object):
         self.class_ = class_
         self.key = key
         self.callable_ = callable_
-        self.events = events
+        self.active_history = False
+        self.dispatch = dispatch
         self.trackparent = trackparent
         self.parent_token = parent_token or self
         if compare_function is None:
@@ -358,7 +356,7 @@ class AttributeImpl(object):
             ext._adapt_listener(attr, ext)
             
         if active_history:
-            events.active_history = True
+            self.active_history = True
             
         self.expire_missing = expire_missing
 
@@ -495,12 +493,12 @@ class ScalarAttributeImpl(AttributeImpl):
     def delete(self, state, dict_):
 
         # TODO: catch key errors, convert to attributeerror?
-        if self.events.active_history:
+        if self.active_history:
             old = self.get(state, dict_)
         else:
             old = dict_.get(self.key, NO_VALUE)
 
-        if self.events.on_remove:
+        if self.dispatch.on_remove:
             self.fire_remove_event(state, dict_, old, None)
         state.modified_event(dict_, self, False, old)
         del dict_[self.key]
@@ -513,24 +511,24 @@ class ScalarAttributeImpl(AttributeImpl):
         if initiator is self:
             return
 
-        if self.events.active_history:
+        if self.active_history:
             old = self.get(state, dict_)
         else:
             old = dict_.get(self.key, NO_VALUE)
 
-        if self.events.on_set:
+        if self.dispatch.on_set:
             value = self.fire_replace_event(state, dict_, 
                                                 value, old, initiator)
         state.modified_event(dict_, self, False, old)
         dict_[self.key] = value
 
     def fire_replace_event(self, state, dict_, value, previous, initiator):
-        for fn in self.events.on_set:
+        for fn in self.dispatch.on_set:
             value = fn(state, value, previous, initiator or self)
         return value
 
     def fire_remove_event(self, state, dict_, value, initiator):
-        for fn in self.events.on_remove:
+        for fn in self.dispatch.on_remove:
             fn(state, value, initiator or self)
 
     @property
@@ -547,13 +545,13 @@ class MutableScalarAttributeImpl(ScalarAttributeImpl):
     uses_objects = False
     supports_population = True
 
-    def __init__(self, class_, key, callable_, events,
+    def __init__(self, class_, key, callable_, dispatch,
                     class_manager, copy_function=None,
                     compare_function=None, **kwargs):
         super(ScalarAttributeImpl, self).__init__(
                                             class_, 
                                             key, 
-                                            callable_, events,
+                                            callable_, dispatch,
                                             compare_function=compare_function, 
                                             **kwargs)
         class_manager.mutable_attributes.add(key)
@@ -592,7 +590,7 @@ class MutableScalarAttributeImpl(ScalarAttributeImpl):
         if initiator is self:
             return
 
-        if self.events.on_set:
+        if self.dispatch.on_set:
             old = self.get(state, dict_)
             value = self.fire_replace_event(state, dict_, 
                                             value, old, initiator)
@@ -614,13 +612,13 @@ class ScalarObjectAttributeImpl(ScalarAttributeImpl):
     uses_objects = True
     supports_population = True
 
-    def __init__(self, class_, key, callable_, events,
+    def __init__(self, class_, key, callable_, dispatch,
                     trackparent=False, extension=None, copy_function=None,
                     compare_function=None, **kwargs):
         super(ScalarObjectAttributeImpl, self).__init__(
                                             class_, 
                                             key,
-                                            callable_, events
+                                            callable_, dispatch
                                             trackparent=trackparent, 
                                             extension=extension,
                                             compare_function=compare_function, 
@@ -654,7 +652,7 @@ class ScalarObjectAttributeImpl(ScalarAttributeImpl):
         if initiator is self:
             return
 
-        if self.events.active_history:
+        if self.active_history:
             old = self.get(state, dict_)
         else:
             old = self.get(state, dict_, passive=PASSIVE_NO_FETCH)
@@ -666,7 +664,7 @@ class ScalarObjectAttributeImpl(ScalarAttributeImpl):
         if self.trackparent and value is not None:
             self.sethasparent(instance_state(value), False)
         
-        for fn in self.events.on_remove:
+        for fn in self.dispatch.on_remove:
             fn(state, value, initiator or self)
 
         state.modified_event(dict_, self, False, value)
@@ -678,7 +676,7 @@ class ScalarObjectAttributeImpl(ScalarAttributeImpl):
                 previous is not PASSIVE_NO_RESULT):
                 self.sethasparent(instance_state(previous), False)
 
-        for fn in self.events.on_set:
+        for fn in self.dispatch.on_set:
             value = fn(state, value, previous, initiator or self)
 
         state.modified_event(dict_, self, False, previous)
@@ -705,13 +703,13 @@ class CollectionAttributeImpl(AttributeImpl):
     uses_objects = True
     supports_population = True
 
-    def __init__(self, class_, key, callable_, events,
+    def __init__(self, class_, key, callable_, dispatch,
                     typecallable=None, trackparent=False, extension=None,
                     copy_function=None, compare_function=None, **kwargs):
         super(CollectionAttributeImpl, self).__init__(
                                             class_, 
                                             key, 
-                                            callable_, events,
+                                            callable_, dispatch,
                                             trackparent=trackparent,
                                             extension=extension,
                                             compare_function=compare_function, 
@@ -733,7 +731,7 @@ class CollectionAttributeImpl(AttributeImpl):
             return History.from_attribute(self, state, current)
 
     def fire_append_event(self, state, dict_, value, initiator):
-        for fn in self.events.on_append:
+        for fn in self.dispatch.on_append:
             value = fn(state, value, initiator or self)
 
         state.modified_event(dict_, self, True, 
@@ -752,7 +750,7 @@ class CollectionAttributeImpl(AttributeImpl):
         if self.trackparent and value is not None:
             self.sethasparent(instance_state(value), False)
 
-        for fn in self.events.on_remove:
+        for fn in self.dispatch.on_remove:
             fn(state, value, initiator or self)
 
         state.modified_event(dict_, self, True, 
@@ -1006,7 +1004,7 @@ class ClassManager(dict):
         def on_resurrect(self, state, instance):
             """"""
             
-    events = event.dispatcher(events)
+    dispatch = event.dispatcher(events)
     
     @property
     def is_mapped(self):
@@ -1132,7 +1130,7 @@ class ClassManager(dict):
         
         self._uninstrument_init()
 
-        self.mapper = self.events = None
+        self.mapper = self.dispatch = None
         self.info.clear()
         
         for key in list(self):
@@ -1499,20 +1497,20 @@ def register_attribute_impl(class_, key,
     else:
         typecallable = kw.pop('typecallable', None)
 
-    events = manager[key].events
+    dispatch = manager[key].dispatch
     
     if impl_class:
         impl = impl_class(class_, key, typecallable, **kw)
     elif uselist:
-        impl = CollectionAttributeImpl(class_, key, callable_, events,
+        impl = CollectionAttributeImpl(class_, key, callable_, dispatch,
                                        typecallable=typecallable, **kw)
     elif useobject:
-        impl = ScalarObjectAttributeImpl(class_, key, callable_, events,**kw)
+        impl = ScalarObjectAttributeImpl(class_, key, callable_, dispatch,**kw)
     elif mutable_scalars:
-        impl = MutableScalarAttributeImpl(class_, key, callable_, events,
+        impl = MutableScalarAttributeImpl(class_, key, callable_, dispatch,
                                           class_manager=manager, **kw)
     else:
-        impl = ScalarAttributeImpl(class_, key, callable_, events, **kw)
+        impl = ScalarAttributeImpl(class_, key, callable_, dispatch, **kw)
 
     manager[key].impl = impl
     
index 159f60e717a1e08c7afa4dd8c575c122642b202d..a02f2dafdbc049bf832bc8b9ec08e2af8c34e795 100644 (file)
@@ -89,7 +89,7 @@ class InstanceState(object):
         self, instance, args = mixed[0], mixed[1], mixed[2:]
         manager = self.manager
 
-        manager.events.on_init(self, instance, args, kwargs)
+        manager.dispatch.on_init(self, instance, args, kwargs)
             
         # LESSTHANIDEAL:
         # adjust for the case where the InstanceState was created before
@@ -102,7 +102,7 @@ class InstanceState(object):
         try:
             return manager.original_init(*mixed[1:], **kwargs)
         except:
-            manager.events.on_init_failure(self, instance, args, kwargs)
+            manager.dispatch.on_init_failure(self, instance, args, kwargs)
             raise
 
     def get_history(self, key, **kwargs):
@@ -136,7 +136,7 @@ class InstanceState(object):
             return [x]
 
     def _run_on_load(self, instance):
-        self.manager.events.on_load(instance)
+        self.manager.dispatch.on_load(instance)
     
     def __getstate__(self):
         d = {'instance':self.obj()}
@@ -501,7 +501,7 @@ class MutableAttrInstanceState(InstanceState):
         obj.__dict__.update(self.mutable_dict)
 
         # re-establishes identity attributes from the key
-        self.manager.events.on_resurrect(self, obj)
+        self.manager.dispatch.on_resurrect(self, obj)
         
         # TODO: don't really think we should run this here.
         # resurrect is only meant to preserve the minimal state needed to
index e09b7a04fe8e49dcf72094c9e6fde05224036a6c..29591f11e5d21f5665dcdb93212766647afff41e 100644 (file)
@@ -261,10 +261,10 @@ class PoolTest(PoolTestBase):
 
         def assert_listeners(p, total, conn, fconn, cout, cin):
             for instance in (p, p.recreate()):
-                self.assert_(len(instance.events.on_connect) == conn)
-                self.assert_(len(instance.events.on_first_connect) == fconn)
-                self.assert_(len(instance.events.on_checkout) == cout)
-                self.assert_(len(instance.events.on_checkin) == cin)
+                self.assert_(len(instance.dispatch.on_connect) == conn)
+                self.assert_(len(instance.dispatch.on_first_connect) == fconn)
+                self.assert_(len(instance.dispatch.on_checkout) == cout)
+                self.assert_(len(instance.dispatch.on_checkin) == cin)
 
         p = _pool()
         assert_listeners(p, 0, 0, 0, 0, 0)
@@ -392,9 +392,9 @@ class PoolTest(PoolTestBase):
 
             def assert_listeners(p, total, conn, cout, cin):
                 for instance in (p, p.recreate()):
-                    self.assert_(len(instance.events.on_connect) == conn)
-                    self.assert_(len(instance.events.on_checkout) == cout)
-                    self.assert_(len(instance.events.on_checkin) == cin)
+                    self.assert_(len(instance.dispatch.on_connect) == conn)
+                    self.assert_(len(instance.dispatch.on_checkout) == cout)
+                    self.assert_(len(instance.dispatch.on_checkin) == cin)
 
             p = _pool()
             assert_listeners(p, 0, 0, 0, 0)