Index: django/core/signals.py
===================================================================
--- django/core/signals.py	(revision 7278)
+++ django/core/signals.py	(working copy)
@@ -1,3 +1,5 @@
-request_started = object()
-request_finished = object()
-got_request_exception = object()
+from django.dispatch.dispatcher import Signal
+
+request_started = Signal()
+request_finished = Signal()
+got_request_exception = Signal(argnames=["request"])
Index: django/db/models/signals.py
===================================================================
--- django/db/models/signals.py	(revision 7278)
+++ django/db/models/signals.py	(working copy)
@@ -1,12 +1,14 @@
-class_prepared = object()
+from django.dispatch.dispatcher import Signal
 
-pre_init= object()
-post_init = object()
+class_prepared = Signal(argnames=["class"])
 
-pre_save = object()
-post_save = object()
+pre_init = Signal(argnames=["instance", "args", "kwargs"])
+post_init = Signal(argnames=["instance"])
 
-pre_delete = object()
-post_delete = object()
+pre_save = Signal(argnames=["instance", "raw"])
+post_save = Signal(argnames=["instance", "raw", "created"])
 
-post_syncdb = object()
+pre_delete = Signal(argnames=["instance"])
+post_delete = Signal(argnames=["instance"])
+
+post_syncdb = Signal(argnames=["class", "app", "created_models", "verbosity", "interactive"])
Index: django/dispatch/dispatcher.py
===================================================================
--- django/dispatch/dispatcher.py	(revision 7278)
+++ django/dispatch/dispatcher.py	(working copy)
@@ -4,492 +4,284 @@
 providing the primary API and the core logic for the
 system.
 
-Module attributes of note:
-
-    Any -- Singleton used to signal either "Any Sender" or
-        "Any Signal".  See documentation of the _Any class.
-    Anonymous -- Singleton used to signal "Anonymous Sender"
-        See documentation of the _Anonymous class.
-
 Internal attributes:
     WEAKREF_TYPES -- tuple of types/classes which represent
         weak references to receivers, and thus must be de-
         referenced on retrieval to retrieve the callable
         object
-    connections -- { senderkey (id) : { signal : [receivers...]}}
-    senders -- { senderkey (id) : weakref(sender) }
-        used for cleaning up sender references on sender
-        deletion
-    sendersBack -- { receiverkey (id) : [senderkey (id)...] }
-        used for cleaning up receiver references on receiver
-        deletion, (considerably speeds up the cleanup process
-        vs. the original code.)
 """
-import types, weakref
-from django.dispatch import saferef, robustapply, errors
 
 __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
 __cvsid__ = "$Id: dispatcher.py,v 1.9 2005/09/17 04:55:57 mcfletch Exp $"
 __version__ = "$Revision: 1.9 $"[11:-2]
 
+import weakref
+from django.dispatch import saferef, errors
 
-class _Parameter:
-    """Used to represent default parameter values."""
-    def __repr__(self):
-        return self.__class__.__name__
-
-class _Any(_Parameter):
-    """Singleton used to signal either "Any Sender" or "Any Signal"
-
-    The Any object can be used with connect, disconnect,
-    send, or sendExact to signal that the parameter given
-    Any should react to all senders/signals, not just
-    a particular sender/signal.
-    """
-Any = _Any()
-
-class _Anonymous(_Parameter):
-    """Singleton used to signal "Anonymous Sender"
-
-    The Anonymous object is used to signal that the sender
-    of a message is not specified (as distinct from being
-    "any sender").  Registering callbacks for Anonymous
-    will only receive messages sent without senders.  Sending
-    with anonymous will only send messages to those receivers
-    registered for Any or Anonymous.
-
-    Note:
-        The default sender for connect is Any, while the
-        default sender for send is Anonymous.  This has
-        the effect that if you do not specify any senders
-        in either function then all messages are routed
-        as though there was a single sender (Anonymous)
-        being used everywhere.
-    """
-Anonymous = _Anonymous()
-
 WEAKREF_TYPES = (weakref.ReferenceType, saferef.BoundMethodWeakref)
 
-connections = {}
-senders = {}
-sendersBack = {}
-
-
-def connect(receiver, signal=Any, sender=Any, weak=True):
-    """Connect receiver to sender for signal
-
-    receiver -- a callable Python object which is to receive
-        messages/signals/events.  Receivers must be hashable
-        objects.
-
-        if weak is True, then receiver must be weak-referencable
-        (more precisely saferef.safeRef() must be able to create
-        a reference to the receiver).
+class Signal(object):
+    """Base class for all signals
     
-        Receivers are fairly flexible in their specification,
-        as the machinery in the robustApply module takes care
-        of most of the details regarding figuring out appropriate
-        subsets of the sent arguments to apply to a given
-        receiver.
-
-        Note:
-            if receiver is itself a weak reference (a callable),
-            it will be de-referenced by the system's machinery,
-            so *generally* weak references are not suitable as
-            receivers, though some use might be found for the
-            facility whereby a higher-level library passes in
-            pre-weakrefed receiver references.
-
-    signal -- the signal to which the receiver should respond
+    Internal attributes:
+        receivers -- { receriverkey (id) : (weakref(receiver),
+            acceptable_named_args, accepts_kwargs }
+        sendersBack -- { receiverkey (id) : [senderkey (id)...] }
+            used for cleaning up receiver references on receiver
+            deletion, (considerably speeds up the cleanup process
+            vs. the original code.)
+    """
     
-        if Any, receiver will receive any signal from the
-        indicated sender (which might also be Any, but is not
-        necessarily Any).
-        
-        Otherwise must be a hashable Python object other than
-        None (DispatcherError raised on None).
-        
-    sender -- the sender to which the receiver should respond
+    def __init__(self, argnames=[]):
+        """argnames -- A list of the arguments this signal can pass along in
+                       a send() call.
+        """
+        self.receivers = {}
+        self.sendersBack = {}
+        self.argnames = set(argnames)
+   
+    def connect(self, receiver, sender=None, weak=True):
+        """Connect receiver to sender for signal
     
-        if Any, receiver will receive the indicated signals
-        from any sender.
+        receiver -- a function or an instance method which is to
+            receive messages/signals/events.  Receivers must be
+            hashable objects.
+    
+            if weak is True, then receiver must be weak-referencable
+            (more precisely saferef.safeRef() must be able to create
+            a reference to the receiver).
         
-        if Anonymous, receiver will only receive indicated
-        signals from send/sendExact which do not specify a
-        sender, or specify Anonymous explicitly as the sender.
+            Receivers must be able to accept the named arguments
+            declared in argnames.
+    
+            Note:
+                if receiver is itself a weak reference (a callable),
+                it will be de-referenced by the system's machinery,
+                so *generally* weak references are not suitable as
+                receivers, though some use might be found for the
+                facility whereby a higher-level library passes in
+                pre-weakrefed receiver references.
+            
+        sender -- the sender to which the receiver should respond
+            Must either be of type Signal, or None to receive events
+            from any sender.
+            
+        weak -- whether to use weak references to the receiver
+            By default, the module will attempt to use weak
+            references to the receiver objects.  If this parameter
+            is false, then strong references will be used.
+    
+        returns None
+        """
+        receiverkey = id(receiver)
+        allowed_args = receiver.func_code.co_varnames
+        accepts_kwargs = receiver.func_code.co_flags & 8
 
-        Otherwise can be any python object.
-        
-    weak -- whether to use weak references to the receiver
-        By default, the module will attempt to use weak
-        references to the receiver objects.  If this parameter
-        is false, then strong references will be used.
+        if weak:
+            receiver = saferef.safeRef(receiver, onDelete=self._removeReceiver)
+            
+        senderkey = id(sender)
 
-    returns None, may raise DispatcherTypeError
-    """
-    if signal is None:
-        raise errors.DispatcherTypeError(
-            'Signal cannot be None (receiver=%r sender=%r)'%( receiver,sender)
-        )
-    if weak:
-        receiver = saferef.safeRef(receiver, onDelete=_removeReceiver)
-    senderkey = id(sender)
-
-    signals = connections.setdefault(senderkey, {})
-
-    # Keep track of senders for cleanup.
-    # Is Anonymous something we want to clean up?
-    if sender not in (None, Anonymous, Any):
-        def remove(object, senderkey=senderkey):
-            _removeSender(senderkey=senderkey)
-        # Skip objects that can not be weakly referenced, which means
-        # they won't be automatically cleaned up, but that's too bad.
         try:
-            weakSender = weakref.ref(sender, remove)
-            senders[senderkey] = weakSender
-        except:
+            current = self.sendersBack.get( receiverkey )
+            if current is None:
+                self.sendersBack[ receiverkey ] = current = []
+            if senderkey not in current:
+                current.append(senderkey)
+        except Exception, e:
             pass
+    
+        self.receivers[receiverkey] = (receiver, set(allowed_args), accepts_kwargs)
         
-    receiverID = id(receiver)
-    # get current set, remove any current references to
-    # this receiver in the set, including back-references
-    if signals.has_key(signal):
-        receivers = signals[signal]
-        _removeOldBackRefs(senderkey, signal, receiver, receivers)
-    else:
-        receivers = signals[signal] = []
-    try:
-        current = sendersBack.get( receiverID )
-        if current is None:
-            sendersBack[ receiverID ] = current = []
-        if senderkey not in current:
-            current.append(senderkey)
-    except:
-        pass
-
-    receivers.append(receiver)
-
-
-
-def disconnect(receiver, signal=Any, sender=Any, weak=True):
-    """Disconnect receiver from sender for signal
-
-    receiver -- the registered receiver to disconnect
-    signal -- the registered signal to disconnect
-    sender -- the registered sender to disconnect
-    weak -- the weakref state to disconnect
-
-    disconnect reverses the process of connect,
-    the semantics for the individual elements are
-    logically equivalent to a tuple of
-    (receiver, signal, sender, weak) used as a key
-    to be deleted from the internal routing tables.
-    (The actual process is slightly more complex
-    but the semantics are basically the same).
-
-    Note:
-        Using disconnect is not required to cleanup
-        routing when an object is deleted, the framework
-        will remove routes for deleted objects
-        automatically.  It's only necessary to disconnect
-        if you want to stop routing to a live object.
+    def disconnect(self, receiver, sender=None, weak=True):
+        """Disconnect receiver from sender for signal
+    
+        receiver -- the registered receiver to disconnect
+        sender -- the registered sender to disconnect
+        weak -- the weakref state to disconnect
+    
+        disconnect reverses the process of connect,
+        the semantics for the individual elements are
+        logically equivalent to a tuple of
+        (receiver, signal, sender, weak) used as a key
+        to be deleted from the internal routing tables.
+        (The actual process is slightly more complex
+        but the semantics are basically the same).
+    
+        Note:
+            Using disconnect is not required to cleanup
+            routing when an object is deleted, the framework
+            will remove routes for deleted objects
+            automatically.  It's only necessary to disconnect
+            if you want to stop routing to a live object.
+            
+        returns None, may raise DispatcherKeyError
+        """
+        receiverkey = id(receiver)
+        if weak:
+            receiver = saferef.safeRef(receiver)
         
-    returns None, may raise DispatcherTypeError or
-        DispatcherKeyError
-    """
-    if signal is None:
-        raise errors.DispatcherTypeError(
-            'Signal cannot be None (receiver=%r sender=%r)'%( receiver,sender)
-        )
-    if weak: receiver = saferef.safeRef(receiver)
-    senderkey = id(sender)
-    try:
-        signals = connections[senderkey]
-        receivers = signals[signal]
-    except KeyError:
-        raise errors.DispatcherKeyError(
-            """No receivers found for signal %r from sender %r""" %(
-                signal,
-                sender
-            )
-        )
-    try:
-        # also removes from receivers
-        _removeOldBackRefs(senderkey, signal, receiver, receivers)
-    except ValueError:
-        raise errors.DispatcherKeyError(
-            """No connection to receiver %s for signal %s from sender %s""" %(
-                receiver,
-                signal,
-                sender
-            )
-        )
-    _cleanupConnections(senderkey, signal)
-
-def getReceivers( sender = Any, signal = Any ):
-    """Get list of receivers from global tables
-
-    This utility function allows you to retrieve the
-    raw list of receivers from the connections table
-    for the given sender and signal pair.
-
-    Note:
-        there is no guarantee that this is the actual list
-        stored in the connections table, so the value
-        should be treated as a simple iterable/truth value
-        rather than, for instance a list to which you
-        might append new records.
-
-    Normally you would use liveReceivers( getReceivers( ...))
-    to retrieve the actual receiver objects as an iterable
-    object.
-    """
-    existing = connections.get(id(sender))
-    if existing is not None:
-        return existing.get(signal, [])
-    return []
-
-def liveReceivers(receivers):
-    """Filter sequence of receivers to get resolved, live receivers
-
-    This is a generator which will iterate over
-    the passed sequence, checking for weak references
-    and resolving them, then returning all live
-    receivers.
-    """
-    for receiver in receivers:
-        if isinstance( receiver, WEAKREF_TYPES):
-            # Dereference the weak reference.
-            receiver = receiver()
-            if receiver is not None:
-                yield receiver
-        else:
-            yield receiver
-
-
-
-def getAllReceivers( sender = Any, signal = Any ):
-    """Get list of all receivers from global tables
-
-    This gets all dereferenced receivers which should receive
-    the given signal from sender, each receiver should
-    be produced only once by the resulting generator
-    """
-    receivers = {}
-    # Get receivers that receive *this* signal from *this* sender.
-    # Add receivers that receive *any* signal from *this* sender.
-    # Add receivers that receive *this* signal from *any* sender.
-    # Add receivers that receive *any* signal from *any* sender.
-    l = []
-    i = id(sender)
-    if i in connections:
-        sender_receivers = connections[i]
-        if signal in sender_receivers:
-            l.extend(sender_receivers[signal])
-        if signal is not Any and Any in sender_receivers:
-            l.extend(sender_receivers[Any])
-
-    if sender is not Any:
-        i = id(Any)
-        if i in connections:
-            sender_receivers = connections[i]
-            if sender_receivers is not None:
-                if signal in sender_receivers:
-                    l.extend(sender_receivers[signal])
-                if signal is not Any and Any in sender_receivers:
-                    l.extend(sender_receivers[Any])
-
-    for receiver in l:
+        # remove the backref to the sender
         try:
-            if not receiver in receivers:
-                if isinstance(receiver, WEAKREF_TYPES):
-                    receiver = receiver()
-                    # this should only (rough guess) be possible if somehow, deref'ing
-                    # triggered a wipe.
-                    if receiver is None:
-                        continue
-                receivers[receiver] = 1
-                yield receiver
-        except TypeError:
-            # dead weakrefs raise TypeError on hash...
-            pass
+            senderkeys = self.sendersBack[receiverkey]
+            del senderkeys[senderkeys.index(id(sender))]
+        except (KeyError, ValueError):
+            return False
 
-def send(signal=Any, sender=Anonymous, *arguments, **named):
-    """Send signal from sender to all connected receivers.
+        # if there are no more backrefs left, clean up the receiver
+        try:
+            if not senderkeys:
+                del self.sendersBack[receiverkey]
+                del self.receivers[receiverkey]
+        except KeyError:
+            return False
+        
+    def send(self, sender=None, **named):
+        """Send signal from sender to all connected receivers.
+        
+        sender -- the sender of the signal
+            Can be any python object (normally one registered with
+            a connect if you actually want something to occur).
     
-    signal -- (hashable) signal value, see connect for details
-
-    sender -- the sender of the signal
+        named -- named arguments which will be passed to receivers.
+            These arguments must be a subset of the argument names
+            defined in argnames, or a DispatcherTypeError will be
+            raised.
     
-        if Any, only receivers registered for Any will receive
-        the message.
+        Return a list of tuple pairs [(receiver, response), ... ],
+        may raise DispatcherKeyError
+        
+        if any receiver raises an error, the error propagates back
+        through send, terminating the dispatch loop, so it is quite
+        possible to not have all receivers called if a raises an
+        error.
+        """
+        # enforce the API
+        for arg in named.keys():
+            if arg not in self.argnames:
+                raise errors.DispatcherTypeError, \
+                    "send got an unexpected keyword argument '%s'" % arg
 
-        if Anonymous, only receivers registered to receive
-        messages from Anonymous or Any will receive the message
-
-        Otherwise can be any python object (normally one
-        registered with a connect if you actually want
-        something to occur).
-
-    arguments -- positional arguments which will be passed to
-        *all* receivers. Note that this may raise TypeErrors
-        if the receivers do not allow the particular arguments.
-        Note also that arguments are applied before named
-        arguments, so they should be used with care.
-
-    named -- named arguments which will be filtered according
-        to the parameters of the receivers to only provide those
-        acceptable to the receiver.
-
-    Return a list of tuple pairs [(receiver, response), ... ]
-
-    if any receiver raises an error, the error propagates back
-    through send, terminating the dispatch loop, so it is quite
-    possible to not have all receivers called if a raises an
-    error.
-    """
-    # Call each receiver with whatever arguments it can accept.
-    # Return a list of tuple pairs [(receiver, response), ... ].
-    responses = []
-    for receiver in getAllReceivers(sender, signal):
-        response = robustapply.robustApply(
-            receiver,
-            signal=signal,
-            sender=sender,
-            *arguments,
-            **named
-        )
-        responses.append((receiver, response))
-    return responses
-
-
-def sendExact( signal=Any, sender=Anonymous, *arguments, **named ):
-    """Send signal only to those receivers registered for exact message
-
-    sendExact allows for avoiding Any/Anonymous registered
-    handlers, sending only to those receivers explicitly
-    registered for a particular signal on a particular
-    sender.
-    """
-    responses = []
-    for receiver in liveReceivers(getReceivers(sender, signal)):
-        response = robustapply.robustApply(
-            receiver,
-            signal=signal,
-            sender=sender,
-            *arguments,
-            **named
-        )
-        responses.append((receiver, response))
-    return responses
+        senderkey = id(sender)
+        none_senderkey = id(None)
+        
+        # Call each receiver.
+        # Return a list of tuple pairs [(receiver, response), ... ].
+        responses = []
+        for receiverkey, receiver in self.liveReceivers():
+            senderkeys = self.sendersBack[receiverkey]
+            if none_senderkey in senderkeys or senderkey in senderkeys:
+                response = self._callReceiver(
+                    receiver,
+                    receiverkey,
+                    sender=sender,
+                    signal=self,
+                    **named)
+                responses.append((receiver, response))
+        return responses
     
+    def sendRobust(self, sender, **named):
+        """Send signal from sender to all connected receivers catching errors
+        
+        sender -- the sender of the signal
+            Can be any python object (normally one registered with
+            a connect if you actually want something to occur).
+    
+        named -- named arguments which will be passed to receivers.
+            These arguments must be a subset of the argument names
+            defined in argnames, or a DispatcherTypeError will be
+            raised.
+    
+        Return a list of tuple pairs [(receiver, response), ... ],
+        may raise DispatcherKeyError
+    
+        if any receiver raises an error (specifically any subclass of Exception),
+        the error instance is returned as the result for that receiver.
+        """
+        # enforce the API
+        for arg in named.keys():
+            if arg not in self.argnames:
+                raise DispatcherTypeError, "send got an unexpected keyword argument '%s'" % arg
 
-def _removeReceiver(receiver):
-    """Remove receiver from connections."""
-    if not sendersBack:
-        # During module cleanup the mapping will be replaced with None
-        return False
-    backKey = id(receiver)
-    for senderkey in sendersBack.get(backKey,()):
-        try:
-            signals = connections[senderkey].keys()
-        except KeyError,err:
-            pass
-        else:
-            for signal in signals:
-                try:
-                    receivers = connections[senderkey][signal]
-                except KeyError:
-                    pass
-                else:
-                    try:
-                        receivers.remove( receiver )
-                    except Exception, err:
-                        pass
-                _cleanupConnections(senderkey, signal)
-    try:
-        del sendersBack[ backKey ]
-    except KeyError:
-        pass
-            
-def _cleanupConnections(senderkey, signal):
-    """Delete any empty signals for senderkey. Delete senderkey if empty."""
-    try:
-        receivers = connections[senderkey][signal]
-    except:
-        pass
-    else:
-        if not receivers:
-            # No more connected receivers. Therefore, remove the signal.
+        # Call each receiver with whatever arguments it can accept.
+        # Return a list of tuple pairs [(receiver, response), ... ].
+        responses = []
+        for receiverkey, receiver in self.liveReceivers():
             try:
-                signals = connections[senderkey]
-            except KeyError:
-                pass
+                response = self._callReceiver(
+                    receiver,
+                    receiverkey,
+                    sender=sender,
+                    signal=self,
+                    **named)
+            except Exception, err:
+                responses.append((receiver, err))
             else:
-                del signals[signal]
-                if not signals:
-                    # No more signal connections. Therefore, remove the sender.
-                    _removeSender(senderkey)
+                responses.append((receiver, response))
+        return responses
 
-def _removeSender(senderkey):
-    """Remove senderkey from connections."""
-    _removeBackrefs(senderkey)
+    def liveReceivers(self):
+        """Filter sequence of receivers to get resolved, live receivers
+    
+        This is a generator which will iterate over
+        the passed sequence, checking for weak references
+        and resolving them, then returning all live
+        receivers.
+        """
+        for (receiverkey, receiver) in self.receivers.items():
+            receiver = receiver[0]
+            if isinstance(receiver, WEAKREF_TYPES):
+                # Dereference the weak reference.
+                receiver = receiver()
+                if receiver is not None:
+                    yield receiverkey, receiver
+            else:
+                yield receiverkey, receiver
 
-    connections.pop(senderkey, None)
-    senders.pop(senderkey, None)
-
-
-def _removeBackrefs( senderkey):
-    """Remove all back-references to this senderkey"""
-    for receiver_list in connections.pop(senderkey, {}).values():
-        for receiver in receiver_list:
-            _killBackref( receiver, senderkey )
-
-
-def _removeOldBackRefs(senderkey, signal, receiver, receivers):
-    """Kill old sendersBack references from receiver
-
-    This guards against multiple registration of the same
-    receiver for a given signal and sender leaking memory
-    as old back reference records build up.
-
-    Also removes old receiver instance from receivers
-    """
-    try:
-        index = receivers.index(receiver)
-        # need to scan back references here and remove senderkey
-    except ValueError:
-        return False
-    else:
-        oldReceiver = receivers[index]
-        del receivers[index]
-        found = 0
-        signals = connections.get(signal)
-        if signals is not None:
-            for sig,recs in connections.get(signal,{}).iteritems():
-                if sig != signal:
-                    for rec in recs:
-                        if rec is oldReceiver:
-                            found = 1
-                            break
-        if not found:
-            _killBackref( oldReceiver, senderkey )
-            return True
-        return False
+    def _callReceiver(self, receiver, receiverkey, **named):
+        receiver_info = self.receivers[receiverkey]
+        if not receiver_info[2]:
+            acceptable_args = receiver_info[1]
+            for arg in named.keys():
+                if arg not in acceptable_args:
+                    del named[arg]
+        return receiver(**named)
         
+    def _removeReceiver(self, receiver):
+        """Remove receiver from connections."""
+        if not self.sendersBack:
+            # TODO: Is this still true?
+            # During module cleanup the mapping will be replaced with None
+            return False
+        backKey = id(receiver)
         
-def _killBackref( receiver, senderkey ):
-    """Do the actual removal of back reference from receiver to senderkey"""
-    receiverkey = id(receiver)
-    receivers_list = sendersBack.get( receiverkey, () )
-    while senderkey in receivers_list:
         try:
-            receivers_list.remove( senderkey )
-        except:
-            break
-    if not receivers_list:
+            del self.sendersBack[backKey]
+        except KeyError:
+            pass
         try:
-            del sendersBack[ receiverkey ]
+            del self.receivers[backKey]
         except KeyError:
             pass
-    return True
+
+def connect(receiver, signal, sender=None, weak=True):
+    """For backward compatibility only. See Signal.connect()
+    """
+    return signal.connect(receiver, sender, weak)
+
+def disconnect(receiver, signal, sender=None, weak=True):
+    """For backward compatibility only. See Signal.disconnect()
+    """
+    signal.disconnect(receiver, sender, weak)
+
+def send(signal, sender=None, **named):
+    """For backward compatibility only. See Signal.send()
+    """
+    return signal.send(sender=sender, **named)
+
+def sendExact(signal, sender, **named ):
+    """This function is deprecated, as it now has the same
+    meaning as send.
+    """
+    return signal.send(sender=sender, **named)
+    
\ No newline at end of file
Index: django/dispatch/robust.py
===================================================================
--- django/dispatch/robust.py	(revision 7278)
+++ django/dispatch/robust.py	(working copy)
@@ -1,57 +1,7 @@
 """Module implementing error-catching version of send (sendRobust)"""
-from django.dispatch.dispatcher import Any, Anonymous, liveReceivers, getAllReceivers
-from django.dispatch.robustapply import robustApply
+from django.dispatch.dispatcher import Signal
 
-def sendRobust(
-    signal=Any, 
-    sender=Anonymous, 
-    *arguments, **named
-):
-    """Send signal from sender to all connected receivers catching errors
-    
-    signal -- (hashable) signal value, see connect for details
-
-    sender -- the sender of the signal
-    
-        if Any, only receivers registered for Any will receive
-        the message.
-
-        if Anonymous, only receivers registered to receive
-        messages from Anonymous or Any will receive the message
-
-        Otherwise can be any python object (normally one
-        registered with a connect if you actually want
-        something to occur).
-
-    arguments -- positional arguments which will be passed to
-        *all* receivers. Note that this may raise TypeErrors
-        if the receivers do not allow the particular arguments.
-        Note also that arguments are applied before named
-        arguments, so they should be used with care.
-
-    named -- named arguments which will be filtered according
-        to the parameters of the receivers to only provide those
-        acceptable to the receiver.
-
-    Return a list of tuple pairs [(receiver, response), ... ]
-
-    if any receiver raises an error (specifically any subclass of Exception),
-    the error instance is returned as the result for that receiver.
+def sendRobust(signal, sender, **named):
+    """For backward compatibility only. See Signal.sendRobust()
     """
-    # Call each receiver with whatever arguments it can accept.
-    # Return a list of tuple pairs [(receiver, response), ... ].
-    responses = []
-    for receiver in liveReceivers(getAllReceivers(sender, signal)):
-        try:
-            response = robustApply(
-                receiver,
-                signal=signal,
-                sender=sender,
-                *arguments,
-                **named
-            )
-        except Exception, err:
-            responses.append((receiver, err))
-        else:
-            responses.append((receiver, response))
-    return responses
+    return signal.sendRobust(sender=sender, **named)
Index: django/dispatch/saferef.py
===================================================================
--- django/dispatch/saferef.py	(revision 7278)
+++ django/dispatch/saferef.py	(working copy)
@@ -3,7 +3,8 @@
 from django.utils.functional import curry
 
 def safeRef(target, onDelete = None):
-    """Return a *safe* weak reference to a callable target
+    """Return a tuple of a *safe* weak reference to a callable
+    target and the id of that object.
 
     target -- the object to be weakly referenced, if it's a
         bound method reference, will create a BoundMethodWeakref,
@@ -23,6 +24,7 @@
                 onDelete=onDelete
             )
             return reference
+    # If a weakref is created using 
     if callable(onDelete):
         return weakref.ref(target, onDelete)
     else:
@@ -234,5 +236,4 @@
         return BoundMethodWeakref(target=target, onDelete=onDelete)
     else:
         # no luck, use the alternative implementation:
-        return BoundNonDescriptorMethodWeakref(target=target, onDelete=onDelete)
-
+        return BoundNonDescriptorMethodWeakref(target=target, onDelete=onDelete)
\ No newline at end of file
Index: django/test/signals.py
===================================================================
--- django/test/signals.py	(revision 7278)
+++ django/test/signals.py	(working copy)
@@ -1 +1,3 @@
-template_rendered = object()
\ No newline at end of file
+from django.dispatch.dispatcher import Signal
+
+template_rendered = Signal(argnames=["template", "context"])
\ No newline at end of file
Index: tests/regressiontests/dispatch/tests/__init__.py
===================================================================
--- tests/regressiontests/dispatch/tests/__init__.py	(revision 7274)
+++ tests/regressiontests/dispatch/tests/__init__.py	(working copy)
@@ -2,6 +2,4 @@
 Unit-tests for the dispatch project
 """
 
-from test_dispatcher import *
-from test_robustapply import *
 from test_saferef import *
