From 18472ffb5eb7169a84375c08e6fb1ac0a023bac5 Mon Sep 17 00:00:00 2001 From: Wes Okes Date: Mon, 21 Dec 2020 11:41:13 -0500 Subject: [PATCH 1/9] bulk convert to emails --- entity_emailer/interface.py | 30 ++++++++++++++++++++++++++++++ entity_emailer/models.py | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/entity_emailer/interface.py b/entity_emailer/interface.py index aae5baf..b0a071e 100644 --- a/entity_emailer/interface.py +++ b/entity_emailer/interface.py @@ -120,3 +120,33 @@ def convert_events_to_emails(): # Create the emails Email.objects.create_email(event=event, from_address=from_address, recipients=targets) + + @staticmethod + def bulk_convert_events_to_emails(): + """ + Converts unseen events to emails and marks them as seen. Uses the create_emails method to bulk create + emails and recipient relationships + """ + + # Get the email medium + email_medium = get_medium() + + # Get the default from email + default_from_email = get_from_email_address() + + email_params_list = [] + + # Find any unseen events and create unsent email objects + for event, targets in email_medium.events_targets(seen=False, mark_seen=True): + + # Check the event's context for a from_address, otherwise fallback to default + from_address = event.context.get('from_address') or default_from_email + + email_params_list.append(dict( + event=event, + from_address=from_address, + recipients=targets + )) + + # Bulk create the emails + Email.objects.create_emails(email_params_list) diff --git a/entity_emailer/models.py b/entity_emailer/models.py index f4290b2..c61a593 100644 --- a/entity_emailer/models.py +++ b/entity_emailer/models.py @@ -1,6 +1,6 @@ from datetime import datetime -from django.db import models +from django.db import models, transaction from entity.models import Entity from entity_event.models import Event import uuid @@ -26,6 +26,41 @@ def create_email(self, recipients=None, **kwargs): email.save() return email + @transaction.atomic + def create_emails(self, email_params_list): + """ + :param email_params_list: A list of dicts containing the keys for the create_email method + :return: list of Email objects that were created + """ + emails_to_create = [] + recipient_entities_per_email = [] + + # Build the emails to create and keep track of recipients + for kwargs in email_params_list: + scheduled = kwargs.pop('scheduled', datetime.utcnow()) + recipients = kwargs.pop('recipients', []) + emails_to_create.append(Email(scheduled=scheduled, **kwargs)) + recipient_entities_per_email.append(recipients) + + # Bulk create the emails + emails = Email.objects.bulk_create(emails_to_create) + + # Build list of recipient through relationships to create + recipients_to_create = [] + for i, recipient_entities in enumerate(recipient_entities_per_email): + for recipient_entity in recipient_entities: + recipients_to_create.append( + Email.recipients.through( + email_id=emails[i].id, + entity_id=recipient_entity.id, + ) + ) + + # Bulk create the recipient relationships + Email.recipients.through.objects.bulk_create(recipients_to_create) + + return emails + class Email(models.Model): """Save an Email object and it is sent automagically! From 886845936a3cb038fe44cdab6ba65a9a7f968ee3 Mon Sep 17 00:00:00 2001 From: Wes Okes Date: Mon, 21 Dec 2020 11:42:09 -0500 Subject: [PATCH 2/9] version bump --- entity_emailer/version.py | 2 +- release_notes.rst | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/entity_emailer/version.py b/entity_emailer/version.py index 7b344ec..58d478a 100644 --- a/entity_emailer/version.py +++ b/entity_emailer/version.py @@ -1 +1 @@ -__version__ = '1.1.2' +__version__ = '1.2.0' diff --git a/release_notes.rst b/release_notes.rst index 671679f..5e061b3 100644 --- a/release_notes.rst +++ b/release_notes.rst @@ -1,6 +1,10 @@ Release Notes ============= +v1.2.0 +------ +* Added bulk interface for converting to emails + v1.1.2 ------ * Handle email render exceptions From 9e60f6593cb7044b5c616c1c2dad8a7da9b7ebea Mon Sep 17 00:00:00 2001 From: Wes Okes Date: Mon, 21 Dec 2020 17:07:39 -0500 Subject: [PATCH 3/9] do not restruct django version --- requirements/requirements-testing.txt | 14 +++++++------- requirements/requirements.txt | 2 +- setup.py | 5 +++-- tox.ini | 14 +++++++------- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/requirements/requirements-testing.txt b/requirements/requirements-testing.txt index 2608f0b..7909091 100644 --- a/requirements/requirements-testing.txt +++ b/requirements/requirements-testing.txt @@ -1,7 +1,7 @@ -coverage -django-dynamic-fixture<=2.0.0 -django-nose -flake8 -freezegun -mock -psycopg2 +coverage==4.5.1 +django-dynamic-fixture==2.0.0 +django-nose==1.4.5 +flake8==3.5.0 +freezegun==0.3.12 +mock==2.0.0 +psycopg2==2.7.7 diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 9bbaff2..080f9ec 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,5 +1,5 @@ beautifulsoup4>=4.3.2 -Django>=2.0,<3.0 +Django>=2.2 django-db-mutex>=1.2.0 django-entity>=4.2.0 django-entity-event>=1.2.0 diff --git a/setup.py b/setup.py index 02c32d2..bee6cea 100644 --- a/setup.py +++ b/setup.py @@ -48,13 +48,14 @@ def get_requirements(requirements_file): 'Programming Language :: Python', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Framework :: Django', - 'Framework :: Django :: 2.0', - 'Framework :: Django :: 2.1', 'Framework :: Django :: 2.2', + 'Framework :: Django :: 3.0', + 'Framework :: Django :: 3.1', ], license='MIT', install_requires=get_requirements('requirements.txt'), diff --git a/tox.ini b/tox.ini index 0d8bf3a..a401e28 100644 --- a/tox.ini +++ b/tox.ini @@ -1,18 +1,18 @@ [tox] envlist = flake8 - py{36}-django20 - py{36,37}-django21 py{36,37}-django22 + py{36,37,38}-django30 + py{36,37,38}-django31 py{36,37}-djangomaster [testenv] setenv = DB = postgres deps = - django20: Django>=2.0,<2.1 - django21: Django>=2.1,<2.2 - django22: Django>=2.2,<2.3 + django22: Django>=2.2,<3.0 + django30: Django>=3.0,<3.1 + django31: Django>=3.1,<3.2 djangomaster: https://github.com/django/django/archive/master.tar.gz -rrequirements/requirements-testing.txt commands = @@ -25,7 +25,7 @@ commands = flake8 entity_emailer [travis:env] DJANGO = - 2.0: django20 - 2.1: django21 2.2: django22 + 3.0: django30 + 3.1: django31 master: djangomaster From 3af11d16ebac14f518b0635259cce6b5c3469dd3 Mon Sep 17 00:00:00 2001 From: Wes Okes Date: Mon, 21 Dec 2020 17:08:02 -0500 Subject: [PATCH 4/9] update notes --- release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/release_notes.rst b/release_notes.rst index 5e061b3..955ed12 100644 --- a/release_notes.rst +++ b/release_notes.rst @@ -4,6 +4,8 @@ Release Notes v1.2.0 ------ * Added bulk interface for converting to emails +* Add support for python 3.8 +* Add support for django 3.0, 3.1 v1.1.2 ------ From 1afe480aa232e11c381f957f770392fd7ce36924 Mon Sep 17 00:00:00 2001 From: Wes Okes Date: Mon, 21 Dec 2020 17:29:44 -0500 Subject: [PATCH 5/9] update travis file --- .travis.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2f320dd..d60f764 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,21 +5,19 @@ sudo: false python: - "3.6" - "3.7" + - "3.8" env: matrix: - - DJANGO=2.0 - - DJANGO=2.1 - DJANGO=2.2 + - DJANGO=3.0 + - DJANGO=3.1 - DJANGO=master addons: postgresql: '9.6' matrix: - exclude: - - { python: "3.7", env: DJANGO=2.0 } - include: - { python: "3.6", env: TOXENV=flake8 } From 782f2a7584624455b382d7efd9adce907166bf06 Mon Sep 17 00:00:00 2001 From: Wes Okes Date: Tue, 22 Dec 2020 11:02:56 -0500 Subject: [PATCH 6/9] bump entity --- entity_emailer/version.py | 2 +- release_notes.rst | 2 +- requirements/requirements.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/entity_emailer/version.py b/entity_emailer/version.py index 58d478a..afced14 100644 --- a/entity_emailer/version.py +++ b/entity_emailer/version.py @@ -1 +1 @@ -__version__ = '1.2.0' +__version__ = '2.0.0' diff --git a/release_notes.rst b/release_notes.rst index 955ed12..82ad1e7 100644 --- a/release_notes.rst +++ b/release_notes.rst @@ -1,7 +1,7 @@ Release Notes ============= -v1.2.0 +v2.0.0 ------ * Added bulk interface for converting to emails * Add support for python 3.8 diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 080f9ec..5cdf46a 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,6 +1,6 @@ beautifulsoup4>=4.3.2 Django>=2.2 django-db-mutex>=1.2.0 -django-entity>=4.2.0 +django-entity>=5.0.0 django-entity-event>=1.2.0 ambition-django-uuidfield>=0.5.0 From 1f9e62b4dca41e8bc186cae15d121a64d8a12deb Mon Sep 17 00:00:00 2001 From: Wes Okes Date: Tue, 22 Dec 2020 11:13:11 -0500 Subject: [PATCH 7/9] add test using bulk interface --- entity_emailer/tests/interface_tests.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/entity_emailer/tests/interface_tests.py b/entity_emailer/tests/interface_tests.py index d5bd1bd..79a4ff2 100644 --- a/entity_emailer/tests/interface_tests.py +++ b/entity_emailer/tests/interface_tests.py @@ -294,6 +294,30 @@ def test_multiple_events_only_following_false(self): self.assertEquals(email.subject, '') self.assertEquals(email.scheduled, datetime(2013, 1, 2)) + @freeze_time('2013-1-2') + def test_bulk_multiple_events_only_following_false(self): + source = G(Source) + e = G(Entity) + other_e = G(Entity) + + G(Subscription, entity=e, source=source, medium=self.email_medium, only_following=False) + G(Subscription, entity=other_e, source=source, medium=self.email_medium, only_following=False) + email_context = { + 'entity_emailer_template': 'template', + 'entity_emailer_subject': 'hi', + } + G(Event, source=source, context=email_context) + G(Event, source=source, context=email_context) + + EntityEmailerInterface.bulk_convert_events_to_emails() + + self.assertEquals(Email.objects.count(), 2) + for email in Email.objects.all(): + self.assertEquals(set(email.recipients.all()), set([e, other_e])) + self.assertEquals(email.event.context, email_context) + self.assertEquals(email.subject, '') + self.assertEquals(email.scheduled, datetime(2013, 1, 2)) + @freeze_time('2013-1-2') def test_multiple_events_only_following_true(self): source = G(Source) From 1600355cec8a8ceb57a83e9c450795d4e669502c Mon Sep 17 00:00:00 2001 From: Wes Okes Date: Tue, 29 Dec 2020 03:38:28 -0500 Subject: [PATCH 8/9] versions --- requirements/requirements-testing.txt | 4 ++-- requirements/requirements.txt | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/requirements/requirements-testing.txt b/requirements/requirements-testing.txt index 7909091..1dd1fa8 100644 --- a/requirements/requirements-testing.txt +++ b/requirements/requirements-testing.txt @@ -1,7 +1,7 @@ coverage==4.5.1 -django-dynamic-fixture==2.0.0 +django-dynamic-fixture django-nose==1.4.5 flake8==3.5.0 freezegun==0.3.12 mock==2.0.0 -psycopg2==2.7.7 +psycopg2>=2.7.7 diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 5cdf46a..c9f24ba 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,6 +1,8 @@ -beautifulsoup4>=4.3.2 Django>=2.2 -django-db-mutex>=1.2.0 + +django-db-mutex>=2.0.0 django-entity>=5.0.0 -django-entity-event>=1.2.0 +django-entity-event>=2.0.0 ambition-django-uuidfield>=0.5.0 + +beautifulsoup4>=4.3.2 From 641baf65ffc0b1a1a0f80d274d757d0f36f9cbbd Mon Sep 17 00:00:00 2001 From: Wes Okes Date: Tue, 29 Dec 2020 03:42:35 -0500 Subject: [PATCH 9/9] remove 38 --- .travis.yml | 1 - release_notes.rst | 1 - tox.ini | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index d60f764..50a7367 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ sudo: false python: - "3.6" - "3.7" - - "3.8" env: matrix: diff --git a/release_notes.rst b/release_notes.rst index 82ad1e7..30d5525 100644 --- a/release_notes.rst +++ b/release_notes.rst @@ -4,7 +4,6 @@ Release Notes v2.0.0 ------ * Added bulk interface for converting to emails -* Add support for python 3.8 * Add support for django 3.0, 3.1 v1.1.2 diff --git a/tox.ini b/tox.ini index a401e28..eb5cd8c 100644 --- a/tox.ini +++ b/tox.ini @@ -2,8 +2,8 @@ envlist = flake8 py{36,37}-django22 - py{36,37,38}-django30 - py{36,37,38}-django31 + py{36,37}-django30 + py{36,37}-django31 py{36,37}-djangomaster [testenv]