101 lines
3.3 KiB
Python
101 lines
3.3 KiB
Python
|
import weakref
|
||
|
|
||
|
from django.core.signals import (
|
||
|
got_request_exception,
|
||
|
request_finished,
|
||
|
request_started,
|
||
|
setting_changed,
|
||
|
)
|
||
|
from django.db.backends.signals import connection_created
|
||
|
from django.db.models.signals import (
|
||
|
class_prepared,
|
||
|
m2m_changed,
|
||
|
post_delete,
|
||
|
post_init,
|
||
|
post_migrate,
|
||
|
post_save,
|
||
|
pre_delete,
|
||
|
pre_init,
|
||
|
pre_migrate,
|
||
|
pre_save,
|
||
|
)
|
||
|
from django.utils.module_loading import import_string
|
||
|
from django.utils.translation import gettext_lazy as _, ngettext
|
||
|
|
||
|
from debug_toolbar.panels import Panel
|
||
|
|
||
|
|
||
|
class SignalsPanel(Panel):
|
||
|
template = "debug_toolbar/panels/signals.html"
|
||
|
|
||
|
SIGNALS = {
|
||
|
"request_started": request_started,
|
||
|
"request_finished": request_finished,
|
||
|
"got_request_exception": got_request_exception,
|
||
|
"connection_created": connection_created,
|
||
|
"class_prepared": class_prepared,
|
||
|
"pre_init": pre_init,
|
||
|
"post_init": post_init,
|
||
|
"pre_save": pre_save,
|
||
|
"post_save": post_save,
|
||
|
"pre_delete": pre_delete,
|
||
|
"post_delete": post_delete,
|
||
|
"m2m_changed": m2m_changed,
|
||
|
"pre_migrate": pre_migrate,
|
||
|
"post_migrate": post_migrate,
|
||
|
"setting_changed": setting_changed,
|
||
|
}
|
||
|
|
||
|
def nav_subtitle(self):
|
||
|
signals = self.get_stats()["signals"]
|
||
|
num_receivers = sum(len(receivers) for name, receivers in signals)
|
||
|
num_signals = len(signals)
|
||
|
# here we have to handle a double count translation, hence the
|
||
|
# hard coding of one signal
|
||
|
if num_signals == 1:
|
||
|
return ngettext(
|
||
|
"%(num_receivers)d receiver of 1 signal",
|
||
|
"%(num_receivers)d receivers of 1 signal",
|
||
|
num_receivers,
|
||
|
) % {"num_receivers": num_receivers}
|
||
|
return ngettext(
|
||
|
"%(num_receivers)d receiver of %(num_signals)d signals",
|
||
|
"%(num_receivers)d receivers of %(num_signals)d signals",
|
||
|
num_receivers,
|
||
|
) % {"num_receivers": num_receivers, "num_signals": num_signals}
|
||
|
|
||
|
title = _("Signals")
|
||
|
|
||
|
@property
|
||
|
def signals(self):
|
||
|
signals = self.SIGNALS.copy()
|
||
|
for signal in self.toolbar.config["EXTRA_SIGNALS"]:
|
||
|
signal_name = signal.rsplit(".", 1)[-1]
|
||
|
signals[signal_name] = import_string(signal)
|
||
|
return signals
|
||
|
|
||
|
def generate_stats(self, request, response):
|
||
|
signals = []
|
||
|
for name, signal in sorted(self.signals.items()):
|
||
|
receivers = []
|
||
|
for receiver in signal.receivers:
|
||
|
receiver = receiver[1]
|
||
|
if isinstance(receiver, weakref.ReferenceType):
|
||
|
receiver = receiver()
|
||
|
if receiver is None:
|
||
|
continue
|
||
|
|
||
|
receiver = getattr(receiver, "__wraps__", receiver)
|
||
|
receiver_name = getattr(receiver, "__name__", str(receiver))
|
||
|
if getattr(receiver, "__self__", None) is not None:
|
||
|
receiver_class_name = getattr(
|
||
|
receiver.__self__, "__class__", type
|
||
|
).__name__
|
||
|
text = f"{receiver_class_name}.{receiver_name}"
|
||
|
else:
|
||
|
text = receiver_name
|
||
|
receivers.append(text)
|
||
|
signals.append((name, receivers))
|
||
|
|
||
|
self.record_stats({"signals": signals})
|