o 3a+@srddlZddlZddlZddlZddlmZddlmZedZ ddZ e dZ e Z GdddZd d ZdS) N)RemovedInDjango40Warning)func_accepts_kwargszdjango.dispatchcCs&t|drt|jt|jfSt|S)N__func__)hasattrid__self__r)targetr tsz!Signal.connect..N) django.confr configuredDEBUGcallabler ValueErrorr rrefr WeakMethodrfinalize_remove_receiverr_clear_dead_receiversanyrappendrclear)rreceiversenderweak dispatch_uidrr*receiver_objectr r"r connect8s, !  "zSignal.connectc Cs|r |t|f}nt|t|f}d}|j/|tt|jD]}|j|\}}||kr7d}|j|=nq"|jWd|S1sHwY|S)a Disconnect receiver from sender for signal. If weak references are used, disconnect need not be called. The receiver will be removed from dispatch automatically. Arguments: receiver The registered receiver to disconnect. May be none if dispatch_uid is specified. sender The registered sender to disconnect dispatch_uid the unique identifier of the receiver to disconnect FTN)r rr.rangelenrrr1) rr2r3r5r# disconnectedindexr r!r r r disconnectxs$    zSignal.disconnectcCst||Sr)bool_live_receivers)rr3r r r has_listenersszSignal.has_listenersc s6jr jtur gSfddDS)a Send signal from sender to all connected receivers. If any receiver raises an error, the error propagates back through send, terminating the dispatch loop. So it's possible that all receivers won't be called if an error is raised. Arguments: sender The sender of the signal. Either a specific object or None. named Named arguments which will be passed to receivers. Return a list of tuple pairs [(receiver, response), ... ]. cs$g|]}||ddfqS)signalr3r r )rr2namedrr3r r szSignal.send..)rrget NO_RECEIVERSr>)rr3rCr rBr sends z Signal.sendc Ks|jr |j|tur gSg}||D]9}z |d||d|}Wn#tyE}ztjd|j||d| ||fWYd}~qd}~ww| ||fq|S)ab Send signal from sender to all connected receivers catching errors. Arguments: 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. Return a list of tuple pairs [(receiver, response), ... ]. If any receiver raises an error (specifically any subclass of Exception), return the error instance as the result for that receiver. r@z-Error calling %s in Signal.send_robust() (%s))exc_infoNr ) rrrErFr> Exceptionloggererror __qualname__r0)rr3rC responsesr2responseerrr r r send_robusts$ zSignal.send_robustcCs&|jrd|_dd|jD|_dSdS)NFcSs.g|]}t|dtjr|ddus|qS)N) isinstancer ReferenceType)rrr r r rDsz0Signal._clear_dead_receivers..)rr)rr r r r.s  zSignal._clear_dead_receiverscCsd}|jr|js|j|}|turgS|dur\|j9|t|}g}|jD]\\}}}|t ks7||kr<| |q)|jrM|sHt|j|<n||j|<Wdn1sWwYg}|D]}t |t j ru|}|durt| |q`| |q`|S)z Filter sequence of receivers to get resolved, live receivers. This checks for weak references and resolves them, then returning only live receivers. N)rrrrErFrr.r rNONE_IDr0rRrrS)rr3r senderkey receiverkey r_senderkeyr2non_weak_receiversr r r r>s:         zSignal._live_receiverscCs d|_dS)NT)r)rr2r r r r-s zSignal._remove_receiver)NF)NTN)NNNr) __name__ __module__rL__doc__rr7r<r?rGrPr.r>r-r r r r r s   @ $( 'r c sfdd}|S)a~ A decorator for connecting receivers to signals. Used by passing in the signal (or list of signals) and keyword arguments to connect:: @receiver(post_save, sender=MyModel) def signal_receiver(sender, **kwargs): ... @receiver([post_save, post_delete], sender=MyModel) def signals_receiver(sender, **kwargs): ... csDtttfrD] }|j|fiq |Sj|fi|Sr)rRlisttupler7)funcskwargsrAr r _decorator(s zreceiver.._decoratorr )rArbrcr rar r2s r2)loggingrrrdjango.utils.deprecationrdjango.utils.inspectr getLoggerrJr rUobjectrFr r2r r r r s