32 | | def connect(self, receiver, sender=None, weak=True, dispatch_uid=None): |
33 | | """Connect receiver to sender for signal |
34 | | |
35 | | receiver -- a function or an instance method which is to |
36 | | receive signals. Receivers must be |
37 | | hashable objects. |
| 32 | def connect(self, *args, **kwargs): |
| 33 | """Decorate a receiver, connecting it to sender for signal.""" |
| 34 | if args: |
| 35 | self._connect(*args, **kwargs) |
| 36 | # Return the receiver, if being used for decoration. |
| 37 | return args[0] |
| 38 | def connection_wrapper(receiver): |
| 39 | self._connect(receiver, **kwargs) |
| 40 | return receiver |
| 41 | return connection_wrapper |
39 | | if weak is True, then receiver must be weak-referencable |
40 | | (more precisely saferef.safeRef() must be able to create |
41 | | a reference to the receiver). |
42 | | |
43 | | Receivers must be able to accept keyword arguments. |
44 | | |
45 | | If receivers have a dispatch_uid attribute, the receiver will |
46 | | not be added if another receiver already exists with that |
47 | | dispatch_uid. |
48 | | |
49 | | sender -- the sender to which the receiver should respond |
50 | | Must either be of type Signal, or None to receive events |
51 | | from any sender. |
52 | | |
53 | | weak -- whether to use weak references to the receiver |
54 | | By default, the module will attempt to use weak |
55 | | references to the receiver objects. If this parameter |
56 | | is false, then strong references will be used. |
57 | | |
58 | | dispatch_uid -- an identifier used to uniquely identify a particular |
59 | | instance of a receiver. This will usually be a string, though it |
60 | | may be anything hashable. |
61 | | |
62 | | returns None |
63 | | """ |
64 | | from django.conf import settings |
65 | | |
66 | | # If DEBUG is on, check that we got a good receiver |
67 | | if settings.DEBUG: |
68 | | import inspect |
69 | | assert callable(receiver), "Signal receivers must be callable." |
70 | | |
71 | | # Check for **kwargs |
72 | | # Not all callables are inspectable with getargspec, so we'll |
73 | | # try a couple different ways but in the end fall back on assuming |
74 | | # it is -- we don't want to prevent registration of valid but weird |
75 | | # callables. |
76 | | try: |
77 | | argspec = inspect.getargspec(receiver) |
78 | | except TypeError: |
79 | | try: |
80 | | argspec = inspect.getargspec(receiver.__call__) |
81 | | except (TypeError, AttributeError): |
82 | | argspec = None |
83 | | if argspec: |
84 | | assert argspec[2] is not None, \ |
85 | | "Signal receivers must accept keyword arguments (**kwargs)." |
86 | | |
87 | | if dispatch_uid: |
88 | | lookup_key = (dispatch_uid, _make_id(sender)) |
89 | | else: |
90 | | lookup_key = (_make_id(receiver), _make_id(sender)) |
91 | | |
92 | | if weak: |
93 | | receiver = saferef.safeRef(receiver, onDelete=self._remove_receiver) |
94 | | |
95 | | for r_key, _ in self.receivers: |
96 | | if r_key == lookup_key: |
97 | | break |
98 | | else: |
99 | | self.receivers.append((lookup_key, receiver)) |
100 | | |
| 127 | def _connect(self, receiver, sender=None, weak=True, dispatch_uid=None): |
| 128 | """Connect receiver to sender for signal |
| 129 | |
| 130 | receiver -- a function or an instance method which is to |
| 131 | receive signals. Receivers must be |
| 132 | hashable objects. |
| 133 | |
| 134 | if weak is True, then receiver must be weak-referencable |
| 135 | (more precisely saferef.safeRef() must be able to create |
| 136 | a reference to the receiver). |
| 137 | |
| 138 | Receivers must be able to accept keyword arguments. |
| 139 | |
| 140 | If receivers have a dispatch_uid attribute, the receiver will |
| 141 | not be added if another receiver already exists with that |
| 142 | dispatch_uid. |
| 143 | |
| 144 | sender -- the sender to which the receiver should respond |
| 145 | Must either be of type Signal, or None to receive events |
| 146 | from any sender. |
| 147 | |
| 148 | weak -- whether to use weak references to the receiver |
| 149 | By default, the module will attempt to use weak |
| 150 | references to the receiver objects. If this parameter |
| 151 | is false, then strong references will be used. |
| 152 | |
| 153 | dispatch_uid -- an identifier used to uniquely identify a particular |
| 154 | instance of a receiver. This will usually be a string, though it |
| 155 | may be anything hashable. |
| 156 | |
| 157 | returns None |
| 158 | """ |
| 159 | from django.conf import settings |
| 160 | |
| 161 | # If DEBUG is on, check that we got a good receiver |
| 162 | if settings.DEBUG: |
| 163 | import inspect |
| 164 | assert callable(receiver), "Signal receivers must be callable." |
| 165 | |
| 166 | # Check for **kwargs |
| 167 | # Not all callables are inspectable with getargspec, so we'll |
| 168 | # try a couple different ways but in the end fall back on assuming |
| 169 | # it is -- we don't want to prevent registration of valid but weird |
| 170 | # callables. |
| 171 | try: |
| 172 | argspec = inspect.getargspec(receiver) |
| 173 | except TypeError: |
| 174 | try: |
| 175 | argspec = inspect.getargspec(receiver.__call__) |
| 176 | except (TypeError, AttributeError): |
| 177 | argspec = None |
| 178 | if argspec: |
| 179 | assert argspec[2] is not None, \ |
| 180 | "Signal receivers must accept keyword arguments (**kwargs)." |
| 181 | |
| 182 | if dispatch_uid: |
| 183 | lookup_key = (dispatch_uid, _make_id(sender)) |
| 184 | else: |
| 185 | lookup_key = (_make_id(receiver), _make_id(sender)) |
| 186 | |
| 187 | if weak: |
| 188 | receiver = saferef.safeRef(receiver, onDelete=self._remove_receiver) |
| 189 | |
| 190 | for r_key, _ in self.receivers: |
| 191 | if r_key == lookup_key: |
| 192 | break |
| 193 | else: |
| 194 | self.receivers.append((lookup_key, receiver)) |
| 195 | |