summaryrefslogtreecommitdiff
path: root/patchwork/signals.py
diff options
context:
space:
mode:
authorStephen Finucane <stephen@that.guru>2016-10-18 21:12:05 +0100
committerStephen Finucane <stephen@that.guru>2017-03-01 22:17:05 +0000
commit75e33665bbf571ce747082f24afd9cf87892637d (patch)
tree619bd15de0ec78b198da08e13e6e624118f4e689 /patchwork/signals.py
parent1f78a747b7547136d4799cccec8d7263d64f0171 (diff)
downloadpatchwork-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.py178
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)