diff options
author | Stephen Finucane <stephen@that.guru> | 2016-10-18 21:12:05 +0100 |
---|---|---|
committer | Stephen Finucane <stephen@that.guru> | 2017-03-01 22:17:05 +0000 |
commit | 75e33665bbf571ce747082f24afd9cf87892637d (patch) | |
tree | 619bd15de0ec78b198da08e13e6e624118f4e689 /patchwork/signals.py | |
parent | 1f78a747b7547136d4799cccec8d7263d64f0171 (diff) | |
download | patchwork-75e33665bbf571ce747082f24afd9cf87892637d.tar patchwork-75e33665bbf571ce747082f24afd9cf87892637d.tar.gz |
signals: Add callbacks for events
When models are modified, fire signal handlers to create the relevant
events.
Signed-off-by: Stephen Finucane <stephen@that.guru>
Tested-by: Daniel Axtens <dja@axtens.net>
Diffstat (limited to 'patchwork/signals.py')
-rw-r--r-- | patchwork/signals.py | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/patchwork/signals.py b/patchwork/signals.py index 6f7f5ea..208685c 100644 --- a/patchwork/signals.py +++ b/patchwork/signals.py @@ -19,11 +19,17 @@ from datetime import datetime as dt +from django.db.models.signals import post_save from django.db.models.signals import pre_save from django.dispatch import receiver +from patchwork.models import Check +from patchwork.models import CoverLetter +from patchwork.models import Event from patchwork.models import Patch from patchwork.models import PatchChangeNotification +from patchwork.models import Series +from patchwork.models import SeriesPatch @receiver(pre_save, sender=Patch) @@ -61,3 +67,175 @@ def patch_change_callback(sender, instance, **kwargs): notification.last_modified = dt.now() notification.save() + + +@receiver(post_save, sender=CoverLetter) +def create_cover_created_event(sender, instance, created, **kwargs): + + def create_event(cover): + return Event.objects.create( + project=cover.project, + cover=cover, + category=Event.CATEGORY_COVER_CREATED) + + if not created: + return + + create_event(instance) + + +@receiver(post_save, sender=Patch) +def create_patch_created_event(sender, instance, created, **kwargs): + + def create_event(patch): + return Event.objects.create( + project=patch.project, + patch=patch, + category=Event.CATEGORY_PATCH_CREATED) + + if not created: + return + + create_event(instance) + + +@receiver(pre_save, sender=Patch) +def create_patch_state_changed_event(sender, instance, **kwargs): + + def create_event(patch, before, after): + return Event.objects.create( + project=patch.project, + patch=patch, + category=Event.CATEGORY_PATCH_STATE_CHANGED, + previous_state=before, + current_state=after) + + # only trigger on updated items + if not instance.pk: + return + + orig_patch = Patch.objects.get(pk=instance.pk) + + if orig_patch.state == instance.state: + return + + create_event(instance, orig_patch.state, instance.state) + + +@receiver(pre_save, sender=Patch) +def create_patch_delegated_event(sender, instance, **kwargs): + + def create_event(patch, before, after): + return Event.objects.create( + project=patch.project, + patch=patch, + category=Event.CATEGORY_PATCH_DELEGATED, + previous_delegate=before, + current_delegate=after) + + # only trigger on updated items + if not instance.pk: + return + + orig_patch = Patch.objects.get(pk=instance.pk) + + if orig_patch.delegate == instance.delegate: + return + + create_event(instance, orig_patch.delegate, instance.delegate) + + +@receiver(post_save, sender=SeriesPatch) +def create_patch_completed_event(sender, instance, created, **kwargs): + """Create patch completed event for patches with series.""" + + def create_event(patch, series): + return Event.objects.create( + project=patch.project, + patch=patch, + series=series, + category=Event.CATEGORY_PATCH_COMPLETED) + + if not created: + return + + # if dependencies not met, don't raise event. There's also no point raising + # events for successors since they'll have the same issue + predecessors = SeriesPatch.objects.filter( + series=instance.series, number__lt=instance.number) + if predecessors.count() != instance.number - 1: + return + + create_event(instance.patch, instance.series) + + # if this satisfies dependencies for successor patch, raise events for + # those + count = instance.number + 1 + for successor in SeriesPatch.objects.filter( + series=instance.series, number__gt=instance.number): + if successor.number != count: + break + + create_event(successor.patch, successor.series) + count += 1 + + +@receiver(post_save, sender=Check) +def create_check_created_event(sender, instance, created, **kwargs): + + def create_event(check): + # TODO(stephenfin): It might make sense to add a 'project' field to + # 'check' to prevent lookups here and in the REST API + return Event.objects.create( + project=check.patch.project, + patch=check.patch, + created_check=check, + category=Event.CATEGORY_CHECK_CREATED) + + if not created: + return + + create_event(instance) + + +@receiver(post_save, sender=Series) +def create_series_created_event(sender, instance, created, **kwargs): + + def create_event(series): + return Event.objects.create( + project=series.project, + series=series, + category=Event.CATEGORY_SERIES_CREATED) + + if not created: + return + + create_event(instance) + + +@receiver(post_save, sender=SeriesPatch) +def create_series_completed_event(sender, instance, created, **kwargs): + + # NOTE(stephenfin): We subscribe to the SeriesPatch.post_save signal + # instead of Series.m2m_changed to minimize the amount of times this is + # fired. The m2m_changed signal doesn't support a 'changed' parameter, + # which we could use to quick skip the signal when a patch is merely + # updated instead of added to the series. + + # NOTE(stephenfin): It's actually possible for this event to be fired + # multiple times for a given series. To trigger this case, you would need + # to send an additional patch to already exisiting series. This pattern + # exists in the wild ('PATCH 5/n'), so we probably want to retest a series + # in that case. + + def create_event(series): + return Event.objects.create( + project=series.project, + series=series, + category=Event.CATEGORY_SERIES_COMPLETED) + + if not created: + return + + if instance.series.received_all: + create_event(instance.series) |