Opened 10 months ago

Closed 10 months ago

Last modified 9 months ago

#22657 closed Bug (worksforme)

Can't disconnect signal if connected using @receiver tag

Reported by: michalsicker@… Owned by: nobody
Component: Database layer (models, ORM) Version: 1.6
Severity: Normal Keywords: @receiver signal disconnect
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I got signal handler function hooked to pre_save signal using @receiver.

When I tried to disconnect that signal handler temporarily in TestCase, I couldn't achieve that. The lookup key generated in dispatcher (lookup_key = (_make_id(receiver), _make_id(sender))) in order to match function which should be disconnected has other value than it should have so the function can't be found in self.receivers and handler doesn't get disconnected.

That's probably because in self.receivers there is a lookup key generated based on "wrapper" function which had been taken to generate that lookup when registering handler, not the original one, that's why importing original function and passing it to .disconnect() doesn't work.

When signal connected without using @receiver but using pre_save.connect it works as expected.

Change History (3)

comment:1 Changed 10 months ago by timo

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Summary changed from Can't disconnect signal if connected using @reeiver tag to Can't disconnect signal if connected using @receiver tag

comment:2 follow-up: Changed 10 months ago by bmispelon

  • Resolution set to worksforme
  • Status changed from new to closed

Hi,

I've tried to reproduce your issue but couldn't manage to get the results you're describing.

I used an empty Foo model (no fields except for the auto-generated id one) and the following code:

from django.db.models.signals import pre_save
from django.dispatch import receiver

from bug22657.models import Foo

@receiver(pre_save)
def callback(sender, **kwargs):
    print('Hello!')

Foo.objects.create()  # Prints "Hello"
pre_save.disconnect(callback)
Foo.objects.create()  # Prints nothing

I've tried both master and the 1.6 branch and I get the same result in both cases.

Could you show us a piece of code that demonstrates the issue (and reopen this ticket when you do so)?

Thanks

comment:3 in reply to: ↑ 2 Changed 9 months ago by anonymous

Replying to bmispelon:

Hi,

I just reproduced the issue. It's related to parameter sender, when I don't provide that parameter, receiver is not disconnected. I know it works for you but maybe something else influence my results, i.e. it occurs in test case. Also the function is imported from different app. But now I'm 100% sure, i'll paste my results.

code part:

pre_save.disconnect(calculate_current_equity)
for s in Subscription.objects.all():

# simulate real world behaviour - closing transactions one by one in correct order
for st in s.subscription_transactions.order_by('mt_close_time'):

st.mt_open_price = QuoteGenerator.get_symbol_sl_value(st.symbol.name, st.type)
st.mt_close_price = QuoteGenerator.get_symbol_sl_value(st.symbol.name, st.type)
st.mt_profit = Decimal(randint(1000, 100000) / 100)
st.save()

result:

File "[...]/webapp/signals/models.py", line 149, in calculate_current_equity

raise CustomRuntimeError("Closed transaction saved again, although calculations already done.")

CustomRuntimeError: Closed transaction saved again, although calculations already done.

pre_save.disconnect(calculate_current_equity, SubscriptionTransaction)
for s in Subscription.objects.all():

# simulate real world behaviour - closing transactions one by one in correct order
for st in s.subscription_transactions.order_by('mt_close_time'):

st.mt_open_price = QuoteGenerator.get_symbol_sl_value(st.symbol.name, st.type)
st.mt_close_price = QuoteGenerator.get_symbol_sl_value(st.symbol.name, st.type)
st.mt_profit = Decimal(randint(1000, 100000) / 100)
st.save()

result:
test fails from different reasons.

I know it's lame "proof", but what else I can do? Pls try to disconnect receiver in test (and maybe from another app).

Regards,
Mike

Hi,

I've tried to reproduce your issue but couldn't manage to get the results you're describing.

I used an empty Foo model (no fields except for the auto-generated id one) and the following code:

from django.db.models.signals import pre_save
from django.dispatch import receiver

from bug22657.models import Foo

@receiver(pre_save)
def callback(sender, **kwargs):
    print('Hello!')

Foo.objects.create()  # Prints "Hello"
pre_save.disconnect(callback)
Foo.objects.create()  # Prints nothing

I've tried both master and the 1.6 branch and I get the same result in both cases.

Could you show us a piece of code that demonstrates the issue (and reopen this ticket when you do so)?

Thanks

Note: See TracTickets for help on using tickets.
Back to Top