Opened 5 years ago
Closed 5 years ago
#32594 closed Bug (fixed)
Signal.disconnect() returns None when passing sender as string
| Reported by: | Hugo Cachitas | Owned by: | Hugo Cachitas | 
|---|---|---|---|
| Component: | Documentation | Version: | 4.0 | 
| Severity: | Normal | Keywords: | signals | 
| Cc: | Alex Hill | Triage Stage: | Ready for checkin | 
| Has patch: | yes | Needs documentation: | no | 
| Needs tests: | no | Patch needs improvement: | no | 
| Easy pickings: | yes | UI/UX: | no | 
Description
According to the documentation on Signal.disconnect(receiver=None, sender=None, dispatch_uid=None)
The method returns True if a receiver was disconnected and False if not.
I am having this issue where disconnect() returns None when I specify the sender as a string model reference, i.e., passing sender="myapp.MyModel" instead of sender=MyModel.
The sender may be lazily specified as a string as documented in django.db.models.signals.ModelSignal.
To achieve this functionality, a _lazy_method is implemented where we can find that the return value is not properly set.
if isinstance(sender, str): apps = apps or Options.default_apps apps.lazy_model_operation(partial_method, make_model_tuple(sender)) else: return partial_method(sender)
I already have a failing test at tests/signals/tests.py:LazyModelRefTests that could use your input.
@isolate_apps('signals', kwarg_name='apps') def test_disconnect_return_value(self, apps): """ Signal.disconnect() return value should be consistent if we use the Model or its string reference. """ class Created(models.Model): pass def receiver(**kwargs): pass sender = Created signals.post_init.connect(receiver, sender=sender, apps=apps) self.assertTrue( signals.post_init.disconnect(receiver, sender=sender, apps=apps) ) self.assertFalse( signals.post_init.disconnect(receiver, sender=sender, apps=apps) ) sender = 'signals.Created' signals.post_init.connect(receiver, sender=sender, apps=apps) self.assertTrue( signals.post_init.disconnect(receiver, sender=sender, apps=apps) ) self.assertFalse( signals.post_init.disconnect(receiver, sender=sender, apps=apps) )
Change History (8)
comment:1 by , 5 years ago
comment:2 by , 5 years ago
| Has patch: | set | 
|---|
comment:3 by , 5 years ago
| Keywords: | signals added | 
|---|
comment:4 by , 5 years ago
| Cc: | added | 
|---|---|
| Triage Stage: | Unreviewed → Accepted | 
comment:6 by , 5 years ago
| Component: | Database layer (models, ORM) → Documentation | 
|---|---|
| Needs documentation: | set | 
| Patch needs improvement: | set | 
I think we should document the current behavior.
comment:7 by , 5 years ago
| Needs documentation: | unset | 
|---|---|
| Patch needs improvement: | unset | 
| Triage Stage: | Accepted → Ready for checkin | 
PR https://github.com/django/django/pull/14187
The solution involved touching the app registry.
Tests are passing, but I am not entirely sure of the implications the new intermediary returned values may have.