Skip to content

Commit

Permalink
EventRef to the rescue of typos and manual data migrations!
Browse files Browse the repository at this point in the history
  • Loading branch information
fopina committed Jan 21, 2023
1 parent a396f40 commit 8f82d0f
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 6 deletions.
10 changes: 10 additions & 0 deletions notifications/apps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.apps import AppConfig
from django.conf import settings
from django.db.models.signals import post_migrate

# IMPORT do not use "app_settings.py strategy" as that is not compatible with @override_settings (unittests)
# this strategy is
Expand All @@ -19,3 +20,12 @@ def ready(self):
_k = 'NOTIFICATIONS_%s' % k
if not hasattr(settings, _k):
setattr(settings, _k, v)

post_migrate.connect(create_events, sender=self)


def create_events(sender, **kwargs):
from .models import EventRef, Event

for ref in EventRef.get_references():
Event.objects.update_or_create(name=ref.name, defaults={'description': ref.description})
27 changes: 27 additions & 0 deletions notifications/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,33 @@
from django.template.defaultfilters import truncatechars


class EventRef:
"""
EventRef is not a model but instead a reference to current (or future, if not yet migrated) Event.
This allows hardcoded events to be statically referenced and automatically provisioned
(instead of requiring a data-only migration or the event to be manually added before code is used)
"""

__refs = []

def __init__(self, name, description):
self.__class__.__refs.append(self)
self.name = name
self.description = description

def __repr__(self) -> str:
# to be able to use EventRef directly in Event.name queries
return self.name

def get_event(self) -> 'Event':
Event.objects.get(name=self)

@classmethod
def get_references(cls):
# return a copy of the references
return cls.__refs[:]


class Event(models.Model):
name = models.CharField(max_length=50, primary_key=True)
description = models.TextField(blank=True)
Expand Down
2 changes: 1 addition & 1 deletion testapp/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
pytest==6.2.5
pytest-cov==2.12.1
pytest-django==4.4.0
black==20.8b1
black==22.12.0
8 changes: 3 additions & 5 deletions testapp/testapp/management/commands/brute_notify.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.core.management import call_command

from notifications import utils, models, blocks
from testapp.models import TEST_EVENT


class Command(BaseCommand):
Expand All @@ -20,10 +21,7 @@ def add_arguments(self, parser):
)

def handle(self, *args, **options):
# force create event
e, _ = models.Event.objects.get_or_create(name='testit')
e.subscription_set.update_or_create(
event=e,
TEST_EVENT.get_event().subscription_set.update_or_create(
defaults={
'target': options['target'],
'service': models.Subscription.Service.MAIL if options['mail'] else models.Subscription.Service.SLACK,
Expand Down Expand Up @@ -61,7 +59,7 @@ def handle(self, *args, **options):
x = utils.notify(e.name, nblocks)
self.stdout.write(f'{x} notifications created')
call_command('notification_sender', run_once=True)
return

if options['spam']:
x = 0
for y in range(options['spam']):
Expand Down
3 changes: 3 additions & 0 deletions testapp/testapp/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from notifications.models import EventRef

TEST_EVENT = EventRef('testit', 'event for testing purposes (with brute_notify command)')

0 comments on commit 8f82d0f

Please sign in to comment.