#9989 closed (fixed)
removal flaw in django.dispatch.Signal.disconnect
Reported by: | (removed) | Owned by: | nobody |
---|---|---|---|
Component: | Core (Other) | Version: | 1.0 |
Severity: | Keywords: | ||
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Eyeballing cleanup in signals, spotted a bit of whackyness trying to cleanse a list via enumerate usage; presume the author tried removing from the list directory (which blows up since that invalidates the listiter) and came up w/ this instead. Flaw with it is that enumerate continues to increase the index even if you change the list under it's feet- in other words, you skip the item immediately following a deletion. One reason list comps are usually better in this case (although dependant on # of items and deletions of course).
So... that should be using list.remove and catching ValueError where it doesn't exist. Quite a bit faster due to shifting comparison to cpy, and stopping the search after the first find.
Clarifying the latter, a quick read of Signal.connect shows it disallows redundant connections to the same 'key'; meaning that the enumerate code in place right now is daft for continuing it's search for more to wipe- essentially a mismatch between connect/disconnect (guessing it crept in when someone tweaking signal.connect to disallow redundant registrations).
basically convert
for idx, (r_key, _) in self.receivers: if r_key == lookup_key: del self.receives[idx]
into
try: self.receivers.remove(lookup_key) except ValueError: pass
'nuff said.
Change History (6)
comment:1 by , 16 years ago
milestone: | → 1.1 |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 16 years ago
Component: | Uncategorized → Core framework |
---|
comment:3 by , 16 years ago
comment:4 by , 16 years ago
Ah, that's why -- recievers is a list of ((to, from), receiver)
, not a dict. And since receiver
is a weakref we can't exactly reconstruct it. So I'm failure sure the way we're doing it is the only way we can; just need to move the enumerate outside of the loop, perhaps.
comment:5 by , 16 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
I'm not sure it's quite that straightforward: when I make this change, the signal disconnecting at the end of the signals doctest fail to get disconnected. To me that indicates more than just a semantic difference between the two ways of doing this.