From daf897092ba8468d38760025dff2573e0da22322 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sun, 8 Mar 2020 11:27:52 +1100 Subject: [PATCH 01/31] docs: Fix simple typo, overidden -> overridden There is a small typo in README.rst. Should read `overridden` rather than `overidden`. --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 170cc4c..5c7f81c 100644 --- a/README.rst +++ b/README.rst @@ -356,7 +356,7 @@ Using django_templated_email in 3rd party applications If you would like to use django_templated_email to handle mail in a reusable application, you should note that: -* Your calls to **send_templated_mail** should set a value for **template_dir**, so you can keep copies of your app-specific templates local to your app (although the loader will find your email templates if you store them in */templates/templated_email*, if **TEMPLATED_EMAIL_TEMPLATE_DIR** has not been overidden) +* Your calls to **send_templated_mail** should set a value for **template_dir**, so you can keep copies of your app-specific templates local to your app (although the loader will find your email templates if you store them in */templates/templated_email*, if **TEMPLATED_EMAIL_TEMPLATE_DIR** has not been overridden) * If you do (and you should) set a value for **template_dir**, remember to include a trailing slash, i.e. *'my_app_email/'* * The deployed app may use a different backend which doesn't use the django templating backend, and as such make a note in your README warning developers that if they are using django_templated_email already, with a different backend, they will need to ensure their email provider can send all your templates (ideally enumerate those somewhere convenient) From 7f4b246a5c4c9365711a33f91ac947096bb434da Mon Sep 17 00:00:00 2001 From: lampslave Date: Fri, 1 May 2020 15:47:36 +0300 Subject: [PATCH 02/31] django 2.0-3.0 --- .travis.yml | 27 ++++++++++++++++----------- tox.ini | 18 +++++++++--------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index 23981f1..3ebf844 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,24 @@ language: python python: - - "3.5" + - "3.6" env: - - TOX_ENV=py27-flake8 - - TOX_ENV=py35-django110 - - TOX_ENV=py34-django110 - - TOX_ENV=py27-django110 - - TOX_ENV=py35-django19 - - TOX_ENV=py34-django19 - - TOX_ENV=py27-django19 - - TOX_ENV=py35-django18 - - TOX_ENV=py34-django18 - - TOX_ENV=py27-django18 + - TOX_ENV=py36-flake8 + - TOX_ENV=py34-django20 + - TOX_ENV=py35-django20 + - TOX_ENV=py36-django20 + - TOX_ENV=py37-django20 + - TOX_ENV=py35-django21 + - TOX_ENV=py36-django21 + - TOX_ENV=py37-django21 + - TOX_ENV=py35-django22 + - TOX_ENV=py36-django22 + - TOX_ENV=py37-django22 + - TOX_ENV=py38-django22 + - TOX_ENV=py36-django30 + - TOX_ENV=py37-django30 + - TOX_ENV=py38-django30 install: - pip install tox diff --git a/tox.ini b/tox.ini index f75f5dd..d4fc36b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,10 @@ [tox] envlist = - py27-{flake8}, - {py27,py34,py35,py36}-django18, - {py27,py34,py35,py36}-django{19}, - {py27,py34,py35,py36}-django{110} - {py27,py34,py35,py36}-django{111} + py36-{flake8}, + {py34,py35,py36,py37}-django{20} + {py35,py36,py37}-django{21} + {py35,py36,py37,py38}-django{22} + {py36,py37,py38}-django{30} [testenv] @@ -13,10 +13,10 @@ commands= deps= -rtox-requirements.txt pytest-cov - django18: Django==1.8.14 - django19: Django==1.9.9 - django110: Django==1.10 - django111: Django==1.11 + django20: Django==2.0 + django21: Django==2.1 + django22: Django==2.2 + django30: Django==3.0 [testenv:py27-flake8] commands = flake8 templated_email tests --ignore=E501 From 3c900c2b8c27f2373f8009810a585419dd39653a Mon Sep 17 00:00:00 2001 From: lampslave Date: Fri, 1 May 2020 15:55:48 +0300 Subject: [PATCH 03/31] use latest versions of tox-requirements --- tox-requirements.txt | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tox-requirements.txt b/tox-requirements.txt index fdd9d31..ab5bd33 100644 --- a/tox-requirements.txt +++ b/tox-requirements.txt @@ -1,10 +1,10 @@ -django-anymail==3.0 -django-pytest==0.2.0 -django-render-block==0.5 -html2text==2016.5.29 -mock==2.0.0 -pytest==4.1.0 -pytest-django==3.4.5 -pytest-pythonpath==0.7.3 -six==1.10.0 -tox==2.3.1 +django-anymail +django-pytest +django-render-block +html2text +mock +pytest +pytest-django +pytest-pythonpath +six +tox From 25b08512d09bc4b12afa52c1dd1f74e9aa4be975 Mon Sep 17 00:00:00 2001 From: lampslave Date: Fri, 1 May 2020 16:04:03 +0300 Subject: [PATCH 04/31] fix tests --- tests/backends/test_vanilla_django_backend.py | 170 +++++++++--------- tests/backends/utils.py | 8 +- tests/generic_views/test_views.py | 60 +++---- tests/test_inline_image.py | 2 +- tests/test_utils.py | 4 +- tests/test_views.py | 12 +- 6 files changed, 128 insertions(+), 128 deletions(-) diff --git a/tests/backends/test_vanilla_django_backend.py b/tests/backends/test_vanilla_django_backend.py index 5c702e3..de0eea1 100644 --- a/tests/backends/test_vanilla_django_backend.py +++ b/tests/backends/test_vanilla_django_backend.py @@ -72,43 +72,43 @@ def test_inexistent_base_email(self): try: self.backend._render_email('inexistent_base.email', {}) except TemplateDoesNotExist as e: - self.assertEquals(e.args[0], 'foo') + self.assertEqual(e.args[0], 'foo') def test_inexistent_template_email(self): try: self.backend._render_email('foo', {}) except TemplateDoesNotExist as e: - self.assertEquals(e.args[0], 'templated_email/foo.email') + self.assertEqual(e.args[0], 'templated_email/foo.email') def test_render_plain_email(self): response = self.backend._render_email( 'plain_template.email', self.context) - self.assertEquals(len(response.keys()), 2) - self.assertEquals(PLAIN_RESULT, response['plain']) - self.assertEquals(SUBJECT_RESULT, response['subject']) + self.assertEqual(len(response.keys()), 2) + self.assertEqual(PLAIN_RESULT, response['plain']) + self.assertEqual(SUBJECT_RESULT, response['subject']) def test_render_html_email(self): response = self.backend._render_email( 'html_template.email', self.context) - self.assertEquals(len(response.keys()), 2) + self.assertEqual(len(response.keys()), 2) self.assertHTMLEqual(HTML_RESULT, response['html']) - self.assertEquals(SUBJECT_RESULT, response['subject']) + self.assertEqual(SUBJECT_RESULT, response['subject']) def test_render_mixed_email(self): response = self.backend._render_email( 'mixed_template.email', self.context) - self.assertEquals(len(response.keys()), 3) + self.assertEqual(len(response.keys()), 3) self.assertHTMLEqual(HTML_RESULT, response['html']) - self.assertEquals(PLAIN_RESULT, response['plain']) - self.assertEquals(SUBJECT_RESULT, response['subject']) + self.assertEqual(PLAIN_RESULT, response['plain']) + self.assertEqual(SUBJECT_RESULT, response['subject']) def test_render_inheritance_email(self): response = self.backend._render_email( 'inheritance_template.email', self.context) - self.assertEquals(len(response.keys()), 3) + self.assertEqual(len(response.keys()), 3) self.assertHTMLEqual(INHERITANCE_RESULT, response['html']) - self.assertEquals(PLAIN_RESULT, response['plain']) - self.assertEquals('Another subject for vintasoftware', response['subject']) + self.assertEqual(PLAIN_RESULT, response['plain']) + self.assertEqual('Another subject for vintasoftware', response['subject']) @patch.object( template_backend_klass, '_render_email', @@ -120,12 +120,12 @@ def test_get_email_message(self, mock): from_email='from@example.com', cc=['cc@example.com'], bcc=['bcc@example.com'], to=['to@example.com']) self.assertTrue(isinstance(message, EmailMessage)) - self.assertEquals(message.body, PLAIN_RESULT) - self.assertEquals(message.subject, SUBJECT_RESULT) - self.assertEquals(message.to, ['to@example.com']) - self.assertEquals(message.cc, ['cc@example.com']) - self.assertEquals(message.bcc, ['bcc@example.com']) - self.assertEquals(message.from_email, 'from@example.com') + self.assertEqual(message.body, PLAIN_RESULT) + self.assertEqual(message.subject, SUBJECT_RESULT) + self.assertEqual(message.to, ['to@example.com']) + self.assertEqual(message.cc, ['cc@example.com']) + self.assertEqual(message.bcc, ['bcc@example.com']) + self.assertEqual(message.from_email, 'from@example.com') @patch.object( template_backend_klass, '_render_email', @@ -145,7 +145,7 @@ def test_get_email_message_with_create_link(self, mocked): self.assertEqual(len(second_call_context), 0) saved_email = SavedEmail.objects.get( uuid=uuid) - self.assertEquals(saved_email.content, HTML_RESULT) + self.assertEqual(saved_email.content, HTML_RESULT) @patch.object( template_backend_klass, '_render_email', @@ -188,12 +188,12 @@ def test_get_email_message_without_subject(self, mock): from_email='from@example.com', cc=['cc@example.com'], bcc=['bcc@example.com'], to=['to@example.com']) self.assertTrue(isinstance(message, EmailMessage)) - self.assertEquals(message.body, PLAIN_RESULT) - self.assertEquals(message.subject, 'foo') - self.assertEquals(message.to, ['to@example.com']) - self.assertEquals(message.cc, ['cc@example.com']) - self.assertEquals(message.bcc, ['bcc@example.com']) - self.assertEquals(message.from_email, 'from@example.com') + self.assertEqual(message.body, PLAIN_RESULT) + self.assertEqual(message.subject, 'foo') + self.assertEqual(message.to, ['to@example.com']) + self.assertEqual(message.cc, ['cc@example.com']) + self.assertEqual(message.bcc, ['bcc@example.com']) + self.assertEqual(message.from_email, 'from@example.com') @override_settings(TEMPLATED_EMAIL_DJANGO_SUBJECTS={'foo.email': 'foo\r\n'}) @@ -207,12 +207,12 @@ def test_get_email_message_without_subject_multiple_templates(self, mock): from_email='from@example.com', cc=['cc@example.com'], bcc=['bcc@example.com'], to=['to@example.com']) self.assertTrue(isinstance(message, EmailMessage)) - self.assertEquals(message.body, PLAIN_RESULT) - self.assertEquals(message.subject, 'foo') - self.assertEquals(message.to, ['to@example.com']) - self.assertEquals(message.cc, ['cc@example.com']) - self.assertEquals(message.bcc, ['bcc@example.com']) - self.assertEquals(message.from_email, 'from@example.com') + self.assertEqual(message.body, PLAIN_RESULT) + self.assertEqual(message.subject, 'foo') + self.assertEqual(message.to, ['to@example.com']) + self.assertEqual(message.cc, ['cc@example.com']) + self.assertEqual(message.bcc, ['bcc@example.com']) + self.assertEqual(message.from_email, 'from@example.com') @patch.object( template_backend_klass, '_render_email', @@ -225,13 +225,13 @@ def test_get_email_message_generated_plain_text(self, mock): bcc=['bcc@example.com'], to=['to@example.com']) self.assertTrue(isinstance(message, EmailMultiAlternatives)) self.assertHTMLEqual(message.alternatives[0][0], HTML_RESULT) - self.assertEquals(message.alternatives[0][1], 'text/html') - self.assertEquals(message.body, GENERATED_PLAIN_RESULT) - self.assertEquals(message.subject, SUBJECT_RESULT) - self.assertEquals(message.to, ['to@example.com']) - self.assertEquals(message.cc, ['cc@example.com']) - self.assertEquals(message.bcc, ['bcc@example.com']) - self.assertEquals(message.from_email, 'from@example.com') + self.assertEqual(message.alternatives[0][1], 'text/html') + self.assertEqual(message.body, GENERATED_PLAIN_RESULT) + self.assertEqual(message.subject, SUBJECT_RESULT) + self.assertEqual(message.to, ['to@example.com']) + self.assertEqual(message.cc, ['cc@example.com']) + self.assertEqual(message.bcc, ['bcc@example.com']) + self.assertEqual(message.from_email, 'from@example.com') @patch.object( template_backend_klass, '_render_email', @@ -240,43 +240,43 @@ def test_get_email_message_generated_plain_text(self, mock): @override_settings(TEMPLATED_EMAIL_PLAIN_FUNCTION=lambda x: 'hi') def test_get_email_message_custom_func_generated_plain_text(self, mock): message = self.backend.get_email_message('foo.email', {}) - self.assertEquals(message.body, 'hi') + self.assertEqual(message.body, 'hi') def test_get_multi_match_last_email_message_generated_plain_text(self): message = self.backend.get_email_message( ['multi-template.email', 'foo.email', ], {}, from_email='from@example.com', cc=['cc@example.com'], bcc=['bcc@example.com'], to=['to@example.com']) - self.assertEquals(message.body, MULTI_TEMPLATE_PLAIN_RESULT) - self.assertEquals(message.subject, MULTI_TEMPLATE_SUBJECT_RESULT) - self.assertEquals(message.to, ['to@example.com']) - self.assertEquals(message.cc, ['cc@example.com']) - self.assertEquals(message.bcc, ['bcc@example.com']) - self.assertEquals(message.from_email, 'from@example.com') + self.assertEqual(message.body, MULTI_TEMPLATE_PLAIN_RESULT) + self.assertEqual(message.subject, MULTI_TEMPLATE_SUBJECT_RESULT) + self.assertEqual(message.to, ['to@example.com']) + self.assertEqual(message.cc, ['cc@example.com']) + self.assertEqual(message.bcc, ['bcc@example.com']) + self.assertEqual(message.from_email, 'from@example.com') def test_get_multi_first_match_email_message_generated_plain_text(self): message = self.backend.get_email_message( ['foo.email', 'multi-template.email', ], {}, from_email='from@example.com', cc=['cc@example.com'], bcc=['bcc@example.com'], to=['to@example.com']) - self.assertEquals(message.body, MULTI_TEMPLATE_PLAIN_RESULT) - self.assertEquals(message.subject, MULTI_TEMPLATE_SUBJECT_RESULT) - self.assertEquals(message.to, ['to@example.com']) - self.assertEquals(message.cc, ['cc@example.com']) - self.assertEquals(message.bcc, ['bcc@example.com']) - self.assertEquals(message.from_email, 'from@example.com') + self.assertEqual(message.body, MULTI_TEMPLATE_PLAIN_RESULT) + self.assertEqual(message.subject, MULTI_TEMPLATE_SUBJECT_RESULT) + self.assertEqual(message.to, ['to@example.com']) + self.assertEqual(message.cc, ['cc@example.com']) + self.assertEqual(message.bcc, ['bcc@example.com']) + self.assertEqual(message.from_email, 'from@example.com') def test_get_multi_options_select_last_plain_only(self): message = self.backend.get_email_message( ['non-existing.email', 'also-non-existing.email', 'non-existing-without-suffix', 'foo.email', 'multi-template.email', ], {}, from_email='from@example.com', cc=['cc@example.com'], bcc=['bcc@example.com'], to=['to@example.com']) - self.assertEquals(message.body, MULTI_TEMPLATE_PLAIN_RESULT) - self.assertEquals(message.subject, MULTI_TEMPLATE_SUBJECT_RESULT) - self.assertEquals(message.to, ['to@example.com']) - self.assertEquals(message.cc, ['cc@example.com']) - self.assertEquals(message.bcc, ['bcc@example.com']) - self.assertEquals(message.from_email, 'from@example.com') + self.assertEqual(message.body, MULTI_TEMPLATE_PLAIN_RESULT) + self.assertEqual(message.subject, MULTI_TEMPLATE_SUBJECT_RESULT) + self.assertEqual(message.to, ['to@example.com']) + self.assertEqual(message.cc, ['cc@example.com']) + self.assertEqual(message.bcc, ['bcc@example.com']) + self.assertEqual(message.from_email, 'from@example.com') @patch.object( template_backend_klass, '_render_email', @@ -290,13 +290,13 @@ def test_get_email_message_with_plain_and_html(self, mock): bcc=['bcc@example.com'], to=['to@example.com']) self.assertTrue(isinstance(message, EmailMultiAlternatives)) self.assertHTMLEqual(message.alternatives[0][0], HTML_RESULT) - self.assertEquals(message.alternatives[0][1], 'text/html') - self.assertEquals(message.body, PLAIN_RESULT) - self.assertEquals(message.subject, SUBJECT_RESULT) - self.assertEquals(message.to, ['to@example.com']) - self.assertEquals(message.cc, ['cc@example.com']) - self.assertEquals(message.bcc, ['bcc@example.com']) - self.assertEquals(message.from_email, 'from@example.com') + self.assertEqual(message.alternatives[0][1], 'text/html') + self.assertEqual(message.body, PLAIN_RESULT) + self.assertEqual(message.subject, SUBJECT_RESULT) + self.assertEqual(message.to, ['to@example.com']) + self.assertEqual(message.cc, ['cc@example.com']) + self.assertEqual(message.bcc, ['bcc@example.com']) + self.assertEqual(message.from_email, 'from@example.com') @patch.object( template_backend_klass, '_render_email', @@ -335,12 +335,12 @@ def test_get_email_message_html_only(self, mock): bcc=['bcc@example.com'], to=['to@example.com']) self.assertTrue(isinstance(message, EmailMessage)) self.assertHTMLEqual(message.body, HTML_RESULT) - self.assertEquals(message.content_subtype, 'html') - self.assertEquals(message.subject, SUBJECT_RESULT) - self.assertEquals(message.to, ['to@example.com']) - self.assertEquals(message.cc, ['cc@example.com']) - self.assertEquals(message.bcc, ['bcc@example.com']) - self.assertEquals(message.from_email, 'from@example.com') + self.assertEqual(message.content_subtype, 'html') + self.assertEqual(message.subject, SUBJECT_RESULT) + self.assertEqual(message.to, ['to@example.com']) + self.assertEqual(message.cc, ['cc@example.com']) + self.assertEqual(message.bcc, ['bcc@example.com']) + self.assertEqual(message.from_email, 'from@example.com') @patch.object( template_backend_klass, '_render_email', @@ -351,17 +351,17 @@ def test_send(self, render_mock): ret = self.backend.send('mixed_template', 'from@example.com', ['to@example.com', 'to2@example.com'], {}, headers={'Message-Id': 'a_message_id'}) - self.assertEquals(ret, 'a_message_id') - self.assertEquals(len(mail.outbox), 1) + self.assertEqual(ret, 'a_message_id') + self.assertEqual(len(mail.outbox), 1) message = mail.outbox[0] - self.assertEquals(ret, message.extra_headers['Message-Id']) + self.assertEqual(ret, message.extra_headers['Message-Id']) self.assertTrue(isinstance(message, EmailMultiAlternatives)) self.assertHTMLEqual(message.alternatives[0][0], HTML_RESULT) - self.assertEquals(message.alternatives[0][1], 'text/html') - self.assertEquals(message.body, PLAIN_RESULT) - self.assertEquals(message.subject, SUBJECT_RESULT) - self.assertEquals(message.to, ['to@example.com', 'to2@example.com']) - self.assertEquals(message.from_email, 'from@example.com') + self.assertEqual(message.alternatives[0][1], 'text/html') + self.assertEqual(message.body, PLAIN_RESULT) + self.assertEqual(message.subject, SUBJECT_RESULT) + self.assertEqual(message.to, ['to@example.com', 'to2@example.com']) + self.assertEqual(message.from_email, 'from@example.com') @patch.object( template_backend_klass, 'get_email_message' @@ -425,7 +425,7 @@ def test_send_attachment_mime_base(self, render_mock): ['to@example.com', 'to2@example.com'], {}, attachments=[MIMEImage(TXT_FILE, 'text/plain')]) attachment = mail.outbox[0].attachments[0] - self.assertEquals(decode_b64_msg(attachment.get_payload()), + self.assertEqual(decode_b64_msg(attachment.get_payload()), TXT_FILE) @patch.object( @@ -438,7 +438,7 @@ def test_send_attachment_tripple(self, render_mock): ['to@example.com', 'to2@example.com'], {}, attachments=[('black_pixel.png', TXT_FILE, 'text/plain')]) attachment = mail.outbox[0].attachments[0] - self.assertEquals(('black_pixel.png', TXT_FILE, 'text/plain'), + self.assertEqual(('black_pixel.png', TXT_FILE, 'text/plain'), attachment) @patch.object( @@ -452,7 +452,7 @@ def test_get_email_message_attachment_mime_base(self, mock): bcc=['bcc@example.com'], to=['to@example.com'], attachments=[MIMEImage(TXT_FILE, 'text/plain')]) attachment = message.attachments[0] - self.assertEquals(decode_b64_msg(attachment.get_payload()), + self.assertEqual(decode_b64_msg(attachment.get_payload()), TXT_FILE) @patch.object( @@ -466,14 +466,14 @@ def test_get_email_message_attachment_tripple(self, mock): bcc=['bcc@example.com'], to=['to@example.com'], attachments=[('black_pixel.png', TXT_FILE, 'text/plain')]) attachment = message.attachments[0] - self.assertEquals(('black_pixel.png', TXT_FILE, 'text/plain'), + self.assertEqual(('black_pixel.png', TXT_FILE, 'text/plain'), attachment) def test_removal_of_legacy(self): try: self.backend._render_email('legacy', {}) except TemplateDoesNotExist as e: - self.assertEquals(e.args[0], 'templated_email/legacy.email') + self.assertEqual(e.args[0], 'templated_email/legacy.email') def test_host_inline_image_if_not_exist(self): inline_image = InlineImage('foo.jpg', b'bar') @@ -484,7 +484,7 @@ def test_host_inline_image_if_not_exist(self): self.assertEqual(filename, '/media/saved_url') self.storage_mock.save.assert_called_once() name, content = self.storage_mock.save.call_args[0] - self.assertEquals( + self.assertEqual( name, 'templated_email/37b51d194a7513e45b56f6524f2d51f2foo.jpg') self.assertTrue(isinstance(content, BytesIO)) diff --git a/tests/backends/utils.py b/tests/backends/utils.py index 313bc16..1f85ab2 100644 --- a/tests/backends/utils.py +++ b/tests/backends/utils.py @@ -6,17 +6,17 @@ class TempalteBackendBaseMixin(object): @override_settings(TEMPLATED_EMAIL_TEMPLATE_DIR='test_prefix') def test_uses_prefix_from_config(self): backend = self.template_backend_klass() - self.assertEquals(backend.template_prefix, 'test_prefix') + self.assertEqual(backend.template_prefix, 'test_prefix') @override_settings(TEMPLATED_EMAIL_FILE_EXTENSION='test_suffix') def test_uses_suffix_from_config(self): backend = self.template_backend_klass() - self.assertEquals(backend.template_suffix, 'test_suffix') + self.assertEqual(backend.template_suffix, 'test_suffix') def test_override_prefix_from_config(self): backend = self.template_backend_klass(template_prefix='test_prefix') - self.assertEquals(backend.template_prefix, 'test_prefix') + self.assertEqual(backend.template_prefix, 'test_prefix') def test_override_suffix_from_config(self): backend = self.template_backend_klass(template_suffix='test_suffix') - self.assertEquals(backend.template_suffix, 'test_suffix') + self.assertEqual(backend.template_suffix, 'test_suffix') diff --git a/tests/generic_views/test_views.py b/tests/generic_views/test_views.py index 56bd89b..3bfc5d1 100644 --- a/tests/generic_views/test_views.py +++ b/tests/generic_views/test_views.py @@ -24,11 +24,11 @@ def test_templated_email_get_template_names_raises_exception(self): def test_templated_email_get_template_names_with_template_name(self): self.mixin_object.templated_email_template_name = 'template_name' - self.assertEquals( + self.assertEqual( self.mixin_object.templated_email_get_template_names(valid=True), ['template_name'] ) - self.assertEquals( + self.assertEqual( self.mixin_object.templated_email_get_template_names(valid=False), ['template_name'] ) @@ -59,11 +59,11 @@ class FakeForm(object): form = FakeForm() kwargs = self.mixin_object.templated_email_get_send_email_kwargs( valid=True, form=form) - self.assertEquals(len(kwargs), 4) - self.assertEquals(kwargs['template_name'], ['template']) - self.assertEquals(kwargs['from_email'], None) - self.assertEquals(kwargs['recipient_list'], ['foo@example.com']) - self.assertEquals(kwargs['context'], {'form_data': 'foo'}) + self.assertEqual(len(kwargs), 4) + self.assertEqual(kwargs['template_name'], ['template']) + self.assertEqual(kwargs['from_email'], None) + self.assertEqual(kwargs['recipient_list'], ['foo@example.com']) + self.assertEqual(kwargs['context'], {'form_data': 'foo'}) @mock.patch.object(TemplatedEmailFormViewMixin, 'templated_email_get_template_names', @@ -80,11 +80,11 @@ class FakeForm(object): form = FakeForm() kwargs = self.mixin_object.templated_email_get_send_email_kwargs( valid=False, form=form) - self.assertEquals(len(kwargs), 4) - self.assertEquals(kwargs['template_name'], ['template']) - self.assertEquals(kwargs['from_email'], None) - self.assertEquals(kwargs['recipient_list'], ['foo@example.com']) - self.assertEquals(kwargs['context'], {'form_errors': 'errors foo'}) + self.assertEqual(len(kwargs), 4) + self.assertEqual(kwargs['template_name'], ['template']) + self.assertEqual(kwargs['from_email'], None) + self.assertEqual(kwargs['recipient_list'], ['foo@example.com']) + self.assertEqual(kwargs['context'], {'form_errors': 'errors foo'}) class TemplatedEmailFormViewMixinTestCase(MockedNetworkTestCaseMixin, TestCase): @@ -101,48 +101,48 @@ def setUp(self): def test_form_valid_with_send_on_success(self): response = AuthorCreateView.as_view()(self.good_request) - self.assertEquals(response.status_code, 302) - self.assertEquals(Author.objects.count(), 1) - self.assertEquals(len(mail.outbox), 1) - self.assertEquals(mail.outbox[0].alternatives[0][0].strip(), + self.assertEqual(response.status_code, 302) + self.assertEqual(Author.objects.count(), 1) + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].alternatives[0][0].strip(), 'Andre - author@vinta.com.br') def test_form_valid_with_send_on_success_false(self): default_value = AuthorCreateView.templated_email_send_on_success AuthorCreateView.templated_email_send_on_success = False response = AuthorCreateView.as_view()(self.good_request) - self.assertEquals(response.status_code, 302) - self.assertEquals(Author.objects.count(), 1) - self.assertEquals(len(mail.outbox), 0) + self.assertEqual(response.status_code, 302) + self.assertEqual(Author.objects.count(), 1) + self.assertEqual(len(mail.outbox), 0) AuthorCreateView.templated_email_send_on_success = default_value def test_form_invalid_with_not_send_on_failure(self): response = AuthorCreateView.as_view()(self.bad_request) - self.assertEquals(response.status_code, 200) - self.assertEquals(Author.objects.count(), 0) - self.assertEquals(len(mail.outbox), 0) + self.assertEqual(response.status_code, 200) + self.assertEqual(Author.objects.count(), 0) + self.assertEqual(len(mail.outbox), 0) def test_form_invalid_with_send_on_failure(self): default_value = AuthorCreateView.templated_email_send_on_failure AuthorCreateView.templated_email_send_on_failure = True response = AuthorCreateView.as_view()(self.bad_request) - self.assertEquals(response.status_code, 200) - self.assertEquals(Author.objects.count(), 0) - self.assertEquals(len(mail.outbox), 1) - self.assertEquals(mail.outbox[0].alternatives[0][0].strip(), + self.assertEqual(response.status_code, 200) + self.assertEqual(Author.objects.count(), 0) + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].alternatives[0][0].strip(), '* Enter a valid email address.') AuthorCreateView.templated_email_send_on_failure = default_value @override_settings(TEMPLATED_EMAIL_FROM_EMAIL='from@vinta.com.br') def test_from_email(self): AuthorCreateView.as_view()(self.good_request) - self.assertEquals(len(mail.outbox), 1) - self.assertEquals(mail.outbox[0].from_email, 'from@vinta.com.br') + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].from_email, 'from@vinta.com.br') def test_from_email_with_templated_email_from_email(self): default_value = AuthorCreateView.templated_email_from_email AuthorCreateView.templated_email_from_email = 'from2@vinta.com.br' AuthorCreateView.as_view()(self.good_request) - self.assertEquals(len(mail.outbox), 1) - self.assertEquals(mail.outbox[0].from_email, 'from2@vinta.com.br') + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].from_email, 'from2@vinta.com.br') AuthorCreateView.templated_email_from_email = default_value diff --git a/tests/test_inline_image.py b/tests/test_inline_image.py index f6f0408..85635d7 100644 --- a/tests/test_inline_image.py +++ b/tests/test_inline_image.py @@ -30,4 +30,4 @@ def test_cid_in_message(self): def test_image_in_attachments(self): mimage = self.message.attachments[0] attachment_content = base64.b64encode(mimage.get_payload(decode=True)) - self.assertEquals(attachment_content.decode(), imageb64) + self.assertEqual(attachment_content.decode(), imageb64) diff --git a/tests/test_utils.py b/tests/test_utils.py index 4dc015b..d58e4c0 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -48,7 +48,7 @@ def test_attach_to_message(self): message = mock.Mock() self.inline_image.attach_to_message(message) mimeimage = message.attach.call_args[0][0] - self.assertEquals(mimeimage.get('Content-ID'), + self.assertEqual(mimeimage.get('Content-ID'), self.inline_image._content_id) - self.assertEquals(mimeimage.get('Content-Disposition'), + self.assertEqual(mimeimage.get('Content-Disposition'), 'inline; filename="foo.png"') diff --git a/tests/test_views.py b/tests/test_views.py index 815ffa2..f5358a1 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,8 +1,8 @@ import uuid +from django.urls import reverse from django.test import TestCase from django.test import Client -from django.core.urlresolvers import reverse from templated_email.models import SavedEmail @@ -18,24 +18,24 @@ def setUp(self): def test_get(self): response = self.client.get(self.url) - self.assertEquals(response.status_code, 200) + self.assertEqual(response.status_code, 200) def test_get_hex(self): response = self.client.get(self.url_hex) - self.assertEquals(response.status_code, 200) + self.assertEqual(response.status_code, 200) def test_get_non_valid(self): response = self.client.get('/email/bar/') - self.assertEquals(response.status_code, 404) + self.assertEqual(response.status_code, 404) def test_url(self): - self.assertEquals( + self.assertEqual( reverse('templated_email:show_email', kwargs={'uuid': self.saved_email.uuid}), self.url) def test_url_hex(self): - self.assertEquals( + self.assertEqual( reverse('templated_email:show_email', kwargs={'uuid': self.saved_email.uuid.hex}), self.url_hex) From d223e1edca767ed497a6b633ed47914276229515 Mon Sep 17 00:00:00 2001 From: lampslave Date: Fri, 1 May 2020 16:50:27 +0300 Subject: [PATCH 05/31] fix travis.yml --- .travis.yml | 66 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3ebf844..dbd9c14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,24 +1,52 @@ language: python -python: - - "3.6" - -env: - - TOX_ENV=py36-flake8 - - TOX_ENV=py34-django20 - - TOX_ENV=py35-django20 - - TOX_ENV=py36-django20 - - TOX_ENV=py37-django20 - - TOX_ENV=py35-django21 - - TOX_ENV=py36-django21 - - TOX_ENV=py37-django21 - - TOX_ENV=py35-django22 - - TOX_ENV=py36-django22 - - TOX_ENV=py37-django22 - - TOX_ENV=py38-django22 - - TOX_ENV=py36-django30 - - TOX_ENV=py37-django30 - - TOX_ENV=py38-django30 +matix: + include: + - python: 3.6 + env: + - TOX_ENV=py36-flake8 + - python: 3.4 + env: + - TOX_ENV=py34-django20 + - python: 3.5 + env: + - TOX_ENV=py35-django20 + - python: 3.6 + env: + - TOX_ENV=py36-django20 + - python: 3.7 + env: + - TOX_ENV=py37-django20 + - python: 3.5 + env: + - TOX_ENV=py35-django21 + - python: 3.6 + env: + - TOX_ENV=py36-django21 + - python: 3.7 + env: + - TOX_ENV=py37-django21 + - python: 3.5 + env: + - TOX_ENV=py35-django22 + - python: 3.6 + env: + - TOX_ENV=py36-django22 + - python: 3.7 + env: + - TOX_ENV=py37-django22 + - python: 3.8 + env: + - TOX_ENV=py38-django22 + - python: 3.6 + env: + - TOX_ENV=py36-django30 + - python: 3.7 + env: + - TOX_ENV=py37-django30 + - python: 3.8 + env: + - TOX_ENV=py38-django30 install: - pip install tox From ce1af7b4d3e77f8a241cccc367e174d434651183 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Fri, 9 Oct 2020 09:38:54 +0200 Subject: [PATCH 06/31] Auto-escape only the HTML part --- templated_email/backends/vanilla_django.py | 2 +- tox-requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templated_email/backends/vanilla_django.py b/templated_email/backends/vanilla_django.py index 6eccaa5..5f69648 100644 --- a/templated_email/backends/vanilla_django.py +++ b/templated_email/backends/vanilla_django.py @@ -82,7 +82,6 @@ def _render_email(self, template_name, context, template_dir=None, file_extension=None): response = {} errors = {} - render_context = Context(context, autoescape=False) file_extension = file_extension or self.template_suffix if file_extension.startswith('.'): @@ -102,6 +101,7 @@ def _render_email(self, template_name, context, full_template_names.append(one_full_template_name) for part in ['subject', 'html', 'plain']: + render_context = Context(context, autoescape=(part == 'html')) try: response[part] = render_block_to_string(full_template_names, part, render_context) except BlockNotFound as error: diff --git a/tox-requirements.txt b/tox-requirements.txt index fdd9d31..27aba70 100644 --- a/tox-requirements.txt +++ b/tox-requirements.txt @@ -1,6 +1,6 @@ django-anymail==3.0 django-pytest==0.2.0 -django-render-block==0.5 +django-render-block==0.8 html2text==2016.5.29 mock==2.0.0 pytest==4.1.0 From bacb1aa08699583d668bfea6a9c69094a1ea6b6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 7 May 2021 18:30:30 -0300 Subject: [PATCH 07/31] feat: update python and django versions in test environment --- tox.ini | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tox.ini b/tox.ini index d4fc36b..a676781 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,7 @@ [tox] envlist = py36-{flake8}, - {py34,py35,py36,py37}-django{20} - {py35,py36,py37}-django{21} - {py35,py36,py37,py38}-django{22} - {py36,py37,py38}-django{30} + {py36,py37,py38,py39}-django{22,31,32} [testenv] @@ -13,12 +10,11 @@ commands= deps= -rtox-requirements.txt pytest-cov - django20: Django==2.0 - django21: Django==2.1 django22: Django==2.2 - django30: Django==3.0 + django31: Django==3.1 + django32: Django==3.2 -[testenv:py27-flake8] +[testenv:py36-flake8] commands = flake8 templated_email tests --ignore=E501 deps = flake8 From 971b24892add514183f90b2c77dfe5d5aa400f6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 7 May 2021 18:30:59 -0300 Subject: [PATCH 08/31] refactor: updated deprecated code to clean warning list --- templated_email/backends/vanilla_django.py | 2 +- templated_email/urls.py | 4 ++-- tests/test_urls.py | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/templated_email/backends/vanilla_django.py b/templated_email/backends/vanilla_django.py index 6eccaa5..a28a29e 100644 --- a/templated_email/backends/vanilla_django.py +++ b/templated_email/backends/vanilla_django.py @@ -5,7 +5,7 @@ from django.conf import settings from django.core.mail import get_connection from django.template import Context -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.core.files.storage import default_storage from templated_email.utils import ( diff --git a/templated_email/urls.py b/templated_email/urls.py index fd7eb53..c9708cf 100644 --- a/templated_email/urls.py +++ b/templated_email/urls.py @@ -1,8 +1,8 @@ -from django.conf.urls import url +from django.urls import re_path from templated_email.views import ShowEmailView app_name = 'templated_email' urlpatterns = [ - url(r'^email/(?P([a-f\d]{32})|([a-f\d]{8}(-[a-f\d]{4}){3}-[a-f\d]{12}))/$', ShowEmailView.as_view(), name='show_email'), + re_path(r'^email/(?P([a-f\d]{32})|([a-f\d]{8}(-[a-f\d]{4}){3}-[a-f\d]{12}))/$', ShowEmailView.as_view(), name='show_email'), ] diff --git a/tests/test_urls.py b/tests/test_urls.py index c91a2b2..4b20eda 100644 --- a/tests/test_urls.py +++ b/tests/test_urls.py @@ -1,5 +1,6 @@ -from django.conf.urls import url, include +from django.conf.urls import include +from django.urls import re_path urlpatterns = [ - url(r'^', include('templated_email.urls', namespace='templated_email')), + re_path(r'^', include('templated_email.urls', namespace='templated_email')), ] From 5a90eadb70ed765370c13828f9405f14bc07f059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 7 May 2021 18:33:16 -0300 Subject: [PATCH 09/31] fix: refactor some code to fix flake8 checks --- tests/backends/test_vanilla_django_backend.py | 8 ++++---- tests/generic_views/test_views.py | 4 ++-- tests/test_utils.py | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/backends/test_vanilla_django_backend.py b/tests/backends/test_vanilla_django_backend.py index de0eea1..ab398c6 100644 --- a/tests/backends/test_vanilla_django_backend.py +++ b/tests/backends/test_vanilla_django_backend.py @@ -426,7 +426,7 @@ def test_send_attachment_mime_base(self, render_mock): attachments=[MIMEImage(TXT_FILE, 'text/plain')]) attachment = mail.outbox[0].attachments[0] self.assertEqual(decode_b64_msg(attachment.get_payload()), - TXT_FILE) + TXT_FILE) @patch.object( template_backend_klass, '_render_email', @@ -439,7 +439,7 @@ def test_send_attachment_tripple(self, render_mock): attachments=[('black_pixel.png', TXT_FILE, 'text/plain')]) attachment = mail.outbox[0].attachments[0] self.assertEqual(('black_pixel.png', TXT_FILE, 'text/plain'), - attachment) + attachment) @patch.object( template_backend_klass, '_render_email', @@ -453,7 +453,7 @@ def test_get_email_message_attachment_mime_base(self, mock): attachments=[MIMEImage(TXT_FILE, 'text/plain')]) attachment = message.attachments[0] self.assertEqual(decode_b64_msg(attachment.get_payload()), - TXT_FILE) + TXT_FILE) @patch.object( template_backend_klass, '_render_email', @@ -467,7 +467,7 @@ def test_get_email_message_attachment_tripple(self, mock): attachments=[('black_pixel.png', TXT_FILE, 'text/plain')]) attachment = message.attachments[0] self.assertEqual(('black_pixel.png', TXT_FILE, 'text/plain'), - attachment) + attachment) def test_removal_of_legacy(self): try: diff --git a/tests/generic_views/test_views.py b/tests/generic_views/test_views.py index 3bfc5d1..168b8c9 100644 --- a/tests/generic_views/test_views.py +++ b/tests/generic_views/test_views.py @@ -105,7 +105,7 @@ def test_form_valid_with_send_on_success(self): self.assertEqual(Author.objects.count(), 1) self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].alternatives[0][0].strip(), - 'Andre - author@vinta.com.br') + 'Andre - author@vinta.com.br') def test_form_valid_with_send_on_success_false(self): default_value = AuthorCreateView.templated_email_send_on_success @@ -130,7 +130,7 @@ def test_form_invalid_with_send_on_failure(self): self.assertEqual(Author.objects.count(), 0) self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].alternatives[0][0].strip(), - '* Enter a valid email address.') + '* Enter a valid email address.') AuthorCreateView.templated_email_send_on_failure = default_value @override_settings(TEMPLATED_EMAIL_FROM_EMAIL='from@vinta.com.br') diff --git a/tests/test_utils.py b/tests/test_utils.py index d58e4c0..10d80ae 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -49,6 +49,6 @@ def test_attach_to_message(self): self.inline_image.attach_to_message(message) mimeimage = message.attach.call_args[0][0] self.assertEqual(mimeimage.get('Content-ID'), - self.inline_image._content_id) + self.inline_image._content_id) self.assertEqual(mimeimage.get('Content-Disposition'), - 'inline; filename="foo.png"') + 'inline; filename="foo.png"') From 5db99522896d097e5ff6a50e0d48d03dd108138f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 7 May 2021 18:42:37 -0300 Subject: [PATCH 10/31] fix: update python and django versions in the travis config --- .travis.yml | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/.travis.yml b/.travis.yml index dbd9c14..a6c50e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,48 +5,42 @@ matix: - python: 3.6 env: - TOX_ENV=py36-flake8 - - python: 3.4 - env: - - TOX_ENV=py34-django20 - - python: 3.5 - env: - - TOX_ENV=py35-django20 - python: 3.6 env: - - TOX_ENV=py36-django20 + - TOX_ENV=py36-django22 - python: 3.7 env: - - TOX_ENV=py37-django20 - - python: 3.5 - env: - - TOX_ENV=py35-django21 - - python: 3.6 - env: - - TOX_ENV=py36-django21 - - python: 3.7 + - TOX_ENV=py37-django22 + - python: 3.8 env: - - TOX_ENV=py37-django21 - - python: 3.5 + - TOX_ENV=py38-django22 + - python: 3.9 env: - - TOX_ENV=py35-django22 + - TOX_ENV=py39-django22 - python: 3.6 env: - - TOX_ENV=py36-django22 + - TOX_ENV=py36-django31 - python: 3.7 env: - - TOX_ENV=py37-django22 + - TOX_ENV=py37-django31 - python: 3.8 env: - - TOX_ENV=py38-django22 + - TOX_ENV=py38-django31 + - python: 3.9 + env: + - TOX_ENV=py39-django31 - python: 3.6 env: - - TOX_ENV=py36-django30 + - TOX_ENV=py36-django32 - python: 3.7 env: - - TOX_ENV=py37-django30 + - TOX_ENV=py37-django32 - python: 3.8 env: - - TOX_ENV=py38-django30 + - TOX_ENV=py38-django32 + - python: 3.9 + env: + - TOX_ENV=py39-django32 install: - pip install tox From 6b6dd06abe8156a592228ecdcd7b81851308fd46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 7 May 2021 19:08:26 -0300 Subject: [PATCH 11/31] refactor: use tox-travis to reduce travis boilerplate --- .travis.yml | 47 ++++++----------------------------------------- 1 file changed, 6 insertions(+), 41 deletions(-) diff --git a/.travis.yml b/.travis.yml index a6c50e4..332ce4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,49 +1,14 @@ language: python -matix: - include: - - python: 3.6 - env: - - TOX_ENV=py36-flake8 - - python: 3.6 - env: - - TOX_ENV=py36-django22 - - python: 3.7 - env: - - TOX_ENV=py37-django22 - - python: 3.8 - env: - - TOX_ENV=py38-django22 - - python: 3.9 - env: - - TOX_ENV=py39-django22 - - python: 3.6 - env: - - TOX_ENV=py36-django31 - - python: 3.7 - env: - - TOX_ENV=py37-django31 - - python: 3.8 - env: - - TOX_ENV=py38-django31 - - python: 3.9 - env: - - TOX_ENV=py39-django31 - - python: 3.6 - env: - - TOX_ENV=py36-django32 - - python: 3.7 - env: - - TOX_ENV=py37-django32 - - python: 3.8 - env: - - TOX_ENV=py38-django32 - - python: 3.9 - env: - - TOX_ENV=py39-django32 +python: + - "3.6" + - "3.7" + - "3.8" + - "3.9" install: - pip install tox + - pip install tox-travis - pip install -r requirements.txt - pip install coveralls From c4720736d85d0910f2aa3c957dfa3f5a5fbf77a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 7 May 2021 19:13:28 -0300 Subject: [PATCH 12/31] fix: remove unneded ENV variable from tox command inside travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 332ce4d..b122f0b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ install: - pip install coveralls script: - - tox -e $TOX_ENV + - tox after_script: coveralls From 3574da7ff07d0b456840adec6014b61e4d0860a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 7 May 2021 19:18:16 -0300 Subject: [PATCH 13/31] fix: remove tox install from travis.yml --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b122f0b..fed0b4b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,6 @@ python: - "3.9" install: - - pip install tox - pip install tox-travis - pip install -r requirements.txt - pip install coveralls From 0237ef26f99eb3bd4cf4a00b2d04af8070a7fd3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 14 May 2021 17:18:01 -0300 Subject: [PATCH 14/31] Update setup.py classifiers and version to prepare for the pypi/badges update --- setup.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 3f27738..4f2908f 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import setup, find_packages DESCRIPTION = "A Django oriented templated / transaction email abstraction" -VERSION = '2.3.0' +VERSION = '2.4.0' LONG_DESCRIPTION = None try: LONG_DESCRIPTION = open('README.rst').read() @@ -25,12 +25,10 @@ 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', 'Topic :: Software Development :: Libraries :: Python Modules', 'Framework :: Django', ] From 2eed777d7dccea2782df63a6d66b5a4726fe68ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 14 May 2021 17:22:08 -0300 Subject: [PATCH 15/31] Add requirements section to README --- README.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.rst b/README.rst index 5c7f81c..b558a3b 100644 --- a/README.rst +++ b/README.rst @@ -24,6 +24,16 @@ develop branch: https://github.com/vintasoftware/django-templated-email/blob/dev stable pypi/master: https://github.com/vintasoftware/django-templated-email/blob/master/README.rst + +Requirements +================= +* Python (3.6, 3.7, 3.8, 3.9) +* Django (2.2, 3.1, 3.2) + +We **highly recommend** and only officially support the latest patch release of +each Python and Django series. + + Getting going - installation ============================== From 63961fcccf3ffe173c9034a27f78a2580b83a296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 14 May 2021 17:29:48 -0300 Subject: [PATCH 16/31] Remove the six package and some not used code --- setup.py | 3 +-- templated_email/__init__.py | 4 +--- templated_email/migrations/0001_initial.py | 1 - templated_email/utils.py | 4 +--- tox-requirements.txt | 1 - 5 files changed, 3 insertions(+), 10 deletions(-) diff --git a/setup.py b/setup.py index 4f2908f..f4ada1b 100644 --- a/setup.py +++ b/setup.py @@ -11,8 +11,7 @@ pass requirements = [ - 'django-render-block>=0.5', - 'six>=1', + 'django-render-block>=0.5' ] # python setup.py publish diff --git a/templated_email/__init__.py b/templated_email/__init__.py index b004283..5803207 100644 --- a/templated_email/__init__.py +++ b/templated_email/__init__.py @@ -1,8 +1,6 @@ from django.conf import settings from django.utils.module_loading import import_string -import six - from templated_email.backends.vanilla_django import TemplateBackend from templated_email.utils import InlineImage # noqa @@ -20,7 +18,7 @@ def get_connection(backend=None, template_prefix=None, template_suffix=None, # django.core.mail.get_connection klass_path = backend or getattr(settings, 'TEMPLATED_EMAIL_BACKEND', TemplateBackend) - if isinstance(klass_path, six.string_types): + if isinstance(klass_path, str): try: # First check if class name is omitted and we have module in settings klass = import_string(klass_path + '.' + 'TemplateBackend') diff --git a/templated_email/migrations/0001_initial.py b/templated_email/migrations/0001_initial.py index 2c5dc9d..dbed1fb 100644 --- a/templated_email/migrations/0001_initial.py +++ b/templated_email/migrations/0001_initial.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # Generated by Django 1.10 on 2016-10-05 17:09 -from __future__ import unicode_literals from django.db import migrations, models import uuid diff --git a/templated_email/utils.py b/templated_email/utils.py index 2a9cb9f..3f3400a 100644 --- a/templated_email/utils.py +++ b/templated_email/utils.py @@ -6,12 +6,10 @@ from django.utils.module_loading import import_string from django.conf import settings -import six - def _get_klass_from_config(config_variable, default): klass_path = getattr(settings, config_variable, default) - if isinstance(klass_path, six.string_types): + if isinstance(klass_path, str): klass_path = import_string(klass_path) return klass_path diff --git a/tox-requirements.txt b/tox-requirements.txt index ab5bd33..871945f 100644 --- a/tox-requirements.txt +++ b/tox-requirements.txt @@ -6,5 +6,4 @@ mock pytest pytest-django pytest-pythonpath -six tox From 3a696c2200017210752b045c5f4253a043006a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Mon, 17 May 2021 09:25:31 -0300 Subject: [PATCH 17/31] Fix readme and setup.py for pypi uploads --- README.rst | 3 +++ setup.py | 1 + 2 files changed, 4 insertions(+) diff --git a/README.rst b/README.rst index b558a3b..1b9a53c 100644 --- a/README.rst +++ b/README.rst @@ -325,6 +325,7 @@ Methods: **templated_email_get_recipients(self, form)** (mandatory): Return the recipient list to whom the email will be sent to. ie: + .. code-block:: python def templated_email_get_recipients(self, form): @@ -334,6 +335,7 @@ Methods: Use this method to add extra data to the context used for rendering the template. You should get the parent class's context from calling super. ie: + .. code-block:: python def templated_email_get_context_data(self, **kwargs): @@ -344,6 +346,7 @@ Methods: **templated_email_get_send_email_kwargs(self, valid, form)** (optional): Add or change the kwargs that will be used to send the e-mail. You should call super to get the default kwargs. ie: + .. code-block:: python def templated_email_get_send_email_kwargs(valid, form): diff --git a/setup.py b/setup.py index f4ada1b..4d98f3a 100644 --- a/setup.py +++ b/setup.py @@ -43,6 +43,7 @@ license='MIT', description=DESCRIPTION, long_description=LONG_DESCRIPTION, + long_description_content_type='text/x-rst', platforms=['any'], classifiers=CLASSIFIERS, install_requires=requirements, From d70a0c530e96dc2f0d9164efd7e4c2d2e8ff869f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Mon, 17 May 2021 09:26:20 -0300 Subject: [PATCH 18/31] Undoes version update on setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 4d98f3a..d955e50 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import setup, find_packages DESCRIPTION = "A Django oriented templated / transaction email abstraction" -VERSION = '2.4.0' +VERSION = '2.3.0' LONG_DESCRIPTION = None try: LONG_DESCRIPTION = open('README.rst').read() From 334e6c58037c904b8feb64310bba84b40cbe4b23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Mon, 17 May 2021 15:25:51 -0300 Subject: [PATCH 19/31] =?UTF-8?q?Bump=20version:=202.3.0=20=E2=86=92=202.4?= =?UTF-8?q?.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 3 +-- CHANGELOG | 8 ++++++++ setup.py | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 3636baa..d101bd1 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 2.3.0 +current_version = 2.4.0 commit = True tag = True tag_name = {new_version} @@ -7,4 +7,3 @@ tag_name = {new_version} [bumpversion:file:setup.py] search = VERSION = '{current_version}' replace = VERSION = '{new_version}' - diff --git a/CHANGELOG b/CHANGELOG index a7c7393..f4d2202 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,11 @@ +v2.4 +----- +Add Python 3.7, 3.8 and 3.9 support +Drop Python <3.4 support +Add Django 3.1 and 3.2 support +Drop Django 3.0 support +Remove six dependency + v2.3 ----- Remove Django as explicit dependency diff --git a/setup.py b/setup.py index d955e50..4d98f3a 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import setup, find_packages DESCRIPTION = "A Django oriented templated / transaction email abstraction" -VERSION = '2.3.0' +VERSION = '2.4.0' LONG_DESCRIPTION = None try: LONG_DESCRIPTION = open('README.rst').read() From 60faf2d815130e69c516f6410e3640900f38eb5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 21 May 2021 19:43:06 -0300 Subject: [PATCH 20/31] Add django main version to tox tests in preparation for nightly tests --- tox.ini | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index a676781..adb36a6 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,8 @@ [tox] envlist = py36-{flake8}, - {py36,py37,py38,py39}-django{22,31,32} + {py36,py37,py38,py39}-django{22,31,32}, + {py38,py39}-djangomain, [testenv] @@ -13,8 +14,13 @@ deps= django22: Django==2.2 django31: Django==3.1 django32: Django==3.2 + djangomain: https://github.com/django/django/archive/main.tar.gz [testenv:py36-flake8] commands = flake8 templated_email tests --ignore=E501 deps = flake8 + + +[testenv:{py38,py39}-djangomain] +ignore_outcome = true From 95352652b816d2dda34be31c771ed06d815b4ef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 28 May 2021 16:48:39 -0300 Subject: [PATCH 21/31] Renames image example in the docs to use something more friendly --- README.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 1b9a53c..9eba4ee 100644 --- a/README.rst +++ b/README.rst @@ -195,8 +195,8 @@ First get the image content from a file or a *ImageField*: .. code-block:: python # From a file - with open('lena.png', 'rb') as lena: - image = lena.read() + with open('pikachu.png', 'rb') as pikachu: + image = pikachu.read() # From an ImageField # Suppose we have this model @@ -211,7 +211,7 @@ Then create an instance of *InlineImage*: from templated_email import InlineImage - inline_image = InlineImage(filename="lena.png", content=image) + inline_image = InlineImage(filename="pikachu.png", content=image) Now pass the object on the context to the template when you send the email. @@ -220,13 +220,13 @@ Now pass the object on the context to the template when you send the email. send_templated_mail(template_name='welcome', from_email='from@example.com', recipient_list=['to@example.com'], - context={'lena_image': inline_image}) + context={'pikachu_image': inline_image}) Finally in your template add the image on the html template block: .. code-block:: html - + Note: All *InlineImage* objects you add to the context will be attached to the e-mail, even if they are not used in the template. From d694254d52f72d4317a97c3b5ca1927b5cae7c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 28 May 2021 16:49:54 -0300 Subject: [PATCH 22/31] Stop ignoring broken builds from djangomain tests --- tox.ini | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tox.ini b/tox.ini index adb36a6..342c95b 100644 --- a/tox.ini +++ b/tox.ini @@ -20,7 +20,3 @@ deps= commands = flake8 templated_email tests --ignore=E501 deps = flake8 - - -[testenv:{py38,py39}-djangomain] -ignore_outcome = true From 94abb7c7dc4dabec3ba2af95389a4610c63b9f24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 4 Jun 2021 17:22:58 -0300 Subject: [PATCH 23/31] add tests for the conditional text escaping feature --- tests/backends/test_vanilla_django_backend.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/backends/test_vanilla_django_backend.py b/tests/backends/test_vanilla_django_backend.py index ab398c6..a9d7323 100644 --- a/tests/backends/test_vanilla_django_backend.py +++ b/tests/backends/test_vanilla_django_backend.py @@ -45,6 +45,18 @@ MULTI_TEMPLATE_SUBJECT_RESULT = 'A subject' +NON_ESCAPED_PLAIN_RESULT = (u'\n Hi,\n\n You just signed up for my website, using:\n ' + u' username:

vintasoftware

\n join date: Aug. 22, 2016\n' + u'\n Thanks, you rock!\n') + + +ESCAPED_HTML_RESULT = (u'

Hi Foo Bar,

You just signed up for my website, ' + u'using:

username
<p>vintasoftwar' + u'e</p>
join date
Aug. 22, 2016
' + u'

Thanks, you rock!

') + +NON_ESCAPED_SUBJECT_RESULT = 'My subject for

vintasoftware

' + TXT_FILE = 'test' @@ -110,6 +122,16 @@ def test_render_inheritance_email(self): self.assertEqual(PLAIN_RESULT, response['plain']) self.assertEqual('Another subject for vintasoftware', response['subject']) + def test_email_text_escaping(self): + self.context['username'] = '

vintasoftware

' + self.context['subject'] = 'Subject with tag

' + + response = self.backend._render_email( + 'mixed_template.email', self.context) + self.assertHTMLEqual(ESCAPED_HTML_RESULT, response['html']) + self.assertEqual(NON_ESCAPED_PLAIN_RESULT, response['plain']) + self.assertEqual(NON_ESCAPED_SUBJECT_RESULT, response['subject']) + @patch.object( template_backend_klass, '_render_email', return_value={'plain': PLAIN_RESULT, 'subject': SUBJECT_RESULT} From a143f5692bb99c48945ed70e1fb41123447726e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 4 Jun 2021 17:33:46 -0300 Subject: [PATCH 24/31] fix test text identation --- tests/backends/test_vanilla_django_backend.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/backends/test_vanilla_django_backend.py b/tests/backends/test_vanilla_django_backend.py index a9d7323..6f2981d 100644 --- a/tests/backends/test_vanilla_django_backend.py +++ b/tests/backends/test_vanilla_django_backend.py @@ -46,14 +46,14 @@ MULTI_TEMPLATE_SUBJECT_RESULT = 'A subject' NON_ESCAPED_PLAIN_RESULT = (u'\n Hi,\n\n You just signed up for my website, using:\n ' - u' username:

vintasoftware

\n join date: Aug. 22, 2016\n' - u'\n Thanks, you rock!\n') + u' username:

vintasoftware

\n join date: Aug. 22, 2016\n' + u'\n Thanks, you rock!\n') ESCAPED_HTML_RESULT = (u'

Hi Foo Bar,

You just signed up for my website, ' - u'using:

username
<p>vintasoftwar' - u'e</p>
join date
Aug. 22, 2016
' - u'

Thanks, you rock!

') + u'using:
username
<p>vintasoftwar' + u'e</p>
join date
Aug. 22, 2016
' + u'

Thanks, you rock!

') NON_ESCAPED_SUBJECT_RESULT = 'My subject for

vintasoftware

' From 05853bbe6654f738d87e4b0bf4eaceeb8bfb49ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 4 Jun 2021 18:01:55 -0300 Subject: [PATCH 25/31] remove unused test variable --- tests/backends/test_vanilla_django_backend.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/backends/test_vanilla_django_backend.py b/tests/backends/test_vanilla_django_backend.py index 6f2981d..db4bc7e 100644 --- a/tests/backends/test_vanilla_django_backend.py +++ b/tests/backends/test_vanilla_django_backend.py @@ -124,7 +124,6 @@ def test_render_inheritance_email(self): def test_email_text_escaping(self): self.context['username'] = '

vintasoftware

' - self.context['subject'] = 'Subject with tag

' response = self.backend._render_email( 'mixed_template.email', self.context) From 864ce073297b59a6643e32ce711a22f1bd50b635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 4 Jun 2021 18:31:10 -0300 Subject: [PATCH 26/31] =?UTF-8?q?Bump=20version:=202.4.0=20=E2=86=92=203.0?= =?UTF-8?q?.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- CHANGELOG | 5 +++++ setup.py | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index d101bd1..f038530 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 2.4.0 +current_version = 3.0.0 commit = True tag = True tag_name = {new_version} diff --git a/CHANGELOG b/CHANGELOG index f4d2202..844a2b4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +v3.0 +----- +Add escaping to HTML parts in templates +Add tests for django main version + v2.4 ----- Add Python 3.7, 3.8 and 3.9 support diff --git a/setup.py b/setup.py index 4d98f3a..811db6e 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import setup, find_packages DESCRIPTION = "A Django oriented templated / transaction email abstraction" -VERSION = '2.4.0' +VERSION = '3.0.0' LONG_DESCRIPTION = None try: LONG_DESCRIPTION = open('README.rst').read() From 5c74efbbc35298faf4373ef75bb991c5f189c1e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 4 Jun 2021 18:34:24 -0300 Subject: [PATCH 27/31] fix readme text about version updates --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 9eba4ee..7ac0b79 100644 --- a/README.rst +++ b/README.rst @@ -415,7 +415,7 @@ Execute the following commands:: bumpversion [major,minor,patch] python setup.py publish - git push origin master --tags + git push origin --tags Commercial Support From 4a2761919bb580d90bcd2fee6fc0397becc3f3cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BAlio=20Lages?= Date: Fri, 18 Jun 2021 17:01:38 -0300 Subject: [PATCH 28/31] Update travis badge link to point to the new travis domain --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 7ac0b79..7aa6b41 100644 --- a/README.rst +++ b/README.rst @@ -428,8 +428,8 @@ This library, as others, is used in projects of Vinta clients. We are always loo .. _Django: http://djangoproject.com .. |GitterBadge| image:: https://badges.gitter.im/vintasoftware/django-templated-email.svg .. _GitterBadge: https://gitter.im/vintasoftware/django-templated-email?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge -.. |TravisBadge| image:: https://travis-ci.org/vintasoftware/django-templated-email.svg?branch=develop -.. _TravisBadge: https://travis-ci.org/vintasoftware/django-templated-email +.. |TravisBadge| image:: https://travis-ci.com/vintasoftware/django-templated-email.svg?branch=develop +.. _TravisBadge: https://travis-ci.com/vintasoftware/django-templated-email .. |CoverageBadge| image:: https://coveralls.io/repos/github/vintasoftware/django-templated-email/badge.svg?branch=develop .. _CoverageBadge: https://coveralls.io/github/vintasoftware/django-templated-email?branch=develop .. |PypiversionBadge| image:: https://img.shields.io/pypi/v/django-templated-email.svg From 106337cb340d7ff39a11b2a7066db5aa5dca9658 Mon Sep 17 00:00:00 2001 From: Greg Kempe Date: Fri, 11 Feb 2022 13:19:35 +0200 Subject: [PATCH 29/31] Remove all newlines from subject Django doesn't allow newlines at all in the subject, not just at the start or end. --- templated_email/backends/vanilla_django.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templated_email/backends/vanilla_django.py b/templated_email/backends/vanilla_django.py index d5a9059..58cef03 100644 --- a/templated_email/backends/vanilla_django.py +++ b/templated_email/backends/vanilla_django.py @@ -158,7 +158,7 @@ def get_email_message(self, template_name, context, from_email=None, to=None, subject_template = subject_dict.get(template_name, _('%s email subject' % template_name)) subject = subject_template % context - subject = subject.strip('\n\r') # strip newlines from subject + subject = subject.strip('\n\r').replace('\n', ' ').replace('\r', ' ') # strip newlines from subject if not plain_part: plain_part = self._generate_plain_part(parts) From a5fd5b88ffc63c6cce74516456a29f5f3b465d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20Juvenal=20da=20Silva=20Junior?= Date: Tue, 26 Apr 2022 16:01:25 -0300 Subject: [PATCH 30/31] Update README.rst --- README.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 7aa6b41..e283891 100644 --- a/README.rst +++ b/README.rst @@ -421,7 +421,11 @@ Execute the following commands:: Commercial Support ================== -This library, as others, is used in projects of Vinta clients. We are always looking for exciting work, so if you need any commercial support, feel free to get in touch: contact@vinta.com.br +.. image:: https://avatars2.githubusercontent.com/u/5529080?s=80&v=4 + :alt: Vinta Logo + :target: https://www.vinta.com.br + +This project, as other `Vinta Software `_ open-source projects is used in products of Vinta's clients. We are always looking for exciting work, so if you need any commercial support, feel free to get in touch: contact@vinta.com.br From 989235d05fbba102659cb445e05b8870c9655dea Mon Sep 17 00:00:00 2001 From: Carlos Coelho Date: Sat, 22 Oct 2022 17:20:02 -0300 Subject: [PATCH 31/31] Bump version from 3.0.0 to 3.0.1 CHANGELOG gets updated with content of the version --- .bumpversion.cfg | 2 +- CHANGELOG | 4 ++++ setup.py | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index f038530..4e3d256 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 3.0.0 +current_version = 3.0.1 commit = True tag = True tag_name = {new_version} diff --git a/CHANGELOG b/CHANGELOG index 844a2b4..6e1ee81 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +v3.0.1 +----- +Remove all newlines from subject + v3.0 ----- Add escaping to HTML parts in templates diff --git a/setup.py b/setup.py index 811db6e..5c5eb92 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import setup, find_packages DESCRIPTION = "A Django oriented templated / transaction email abstraction" -VERSION = '3.0.0' +VERSION = '3.0.1' LONG_DESCRIPTION = None try: LONG_DESCRIPTION = open('README.rst').read()