Skip to content

Instantly share code, notes, and snippets.

@voldmar
Last active November 1, 2024 11:13
Show Gist options
  • Save voldmar/1264102 to your computer and use it in GitHub Desktop.
Save voldmar/1264102 to your computer and use it in GitHub Desktop.
Show all signals receivers in Django project (fixed for Django 4 by @MahrezBH)
# coding:utf-8
import gc
import inspect
import weakref
from django.core.management.base import BaseCommand, CommandError
from django.dispatch import Signal
REF_TYPES = (weakref.ReferenceType,)
PROJECT_NAME = "TO-BE-COMPLETED"
FORMATS = {
'vim': '{path}:{line}:{name}',
'human': '{name} in line {line} of {path}',
}
class Command(BaseCommand):
help = 'Show all signals receivers from the project'
def add_arguments(self, parser):
parser.add_argument(
'--format',
dest='line_format',
default='human',
choices=FORMATS.keys(),
help='Line format (available choices: {0})'.format(', '.join(FORMATS)),
)
parser.add_argument(
'--scope',
dest='scope',
default='all',
choices=['all', 'project'],
help='Specify "all" to show all signals or "project" to show only project-specific signals',
)
def handle(self, *args, **options):
line_format = options['line_format']
scope = options['scope']
msg = FORMATS.get(line_format)
if not msg:
raise CommandError('Format must be one of {0}'.format(
', '.join(FORMATS.keys())))
seen_receivers = set()
for signal in [obj for obj in gc.get_objects() if isinstance(obj, Signal)]:
for _, receiver in signal.receivers:
if isinstance(receiver, REF_TYPES):
receiver = receiver()
if receiver and receiver not in seen_receivers:
source_file = inspect.getsourcefile(receiver)
# Filter signals based on scope
if scope == 'all' or (source_file and PROJECT_NAME in source_file):
seen_receivers.add(receiver)
self.stdout.write(
msg.format(
name=receiver.__name__,
line=inspect.getsourcelines(receiver)[1],
path=source_file,
)
)
@runekaagaard
Copy link

I made a fork here https://gist.github.com/runekaagaard/2eecf0a8367959dc634b7866694daf2c that lists only model signals by model and signal type. Tested with django 1.7.

@voldmar
Copy link
Author

voldmar commented Feb 14, 2017

@runekaagaard Oh, thank you! I haven’t used Django for a while and haven’t seen comments. Thanks a lot for you fork

@emorozov
Copy link

emorozov commented May 9, 2020

What's the license for this file? Is it public domain?

@voldmar
Copy link
Author

voldmar commented May 10, 2020

@emorozov sure, I think it should be public domain

@MahrezBH
Copy link

Thanks; i updated it to using in Django 4:

# coding:utf-8

import gc
import inspect
import weakref

from django.core.management.base import BaseCommand, CommandError
from django.dispatch import Signal

REF_TYPES = (weakref.ReferenceType,)
PROJECT_NAME = "TO-BE-COMPLETED"

FORMATS = {
    'vim': '{path}:{line}:{name}',
    'human': '{name} in line {line} of {path}',
}


class Command(BaseCommand):
    help = 'Show all signals receivers from the project'

    def add_arguments(self, parser):
        parser.add_argument(
            '--format',
            dest='line_format',
            default='human',
            choices=FORMATS.keys(),
            help='Line format (available choices: {0})'.format(', '.join(FORMATS)),
        )
        parser.add_argument(
            '--scope',
            dest='scope',
            default='all',
            choices=['all', 'project'],
            help='Specify "all" to show all signals or "project" to show only project-specific signals',
        )

    def handle(self, *args, **options):
        line_format = options['line_format']
        scope = options['scope']
        msg = FORMATS.get(line_format)

        if not msg:
            raise CommandError('Format must be one of {0}'.format(
                ', '.join(FORMATS.keys())))

        seen_receivers = set()
        for signal in [obj for obj in gc.get_objects() if isinstance(obj, Signal)]:
            for _, receiver in signal.receivers:
                if isinstance(receiver, REF_TYPES):
                    receiver = receiver()
                if receiver and receiver not in seen_receivers:
                    source_file = inspect.getsourcefile(receiver)
                    # Filter signals based on scope
                    if scope == 'all' or (source_file and PROJECT_NAME in source_file):
                        seen_receivers.add(receiver)
                        self.stdout.write(
                            msg.format(
                                name=receiver.__name__,
                                line=inspect.getsourcelines(receiver)[1],
                                path=source_file,
                            )
                        )

@voldmar
Copy link
Author

voldmar commented Nov 1, 2024

@MahrezBH Thanks mate, appreciate it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment