mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-20 11:51:05 -05:00
Drop unintended json date encoding
This commit is contained in:
@@ -6,7 +6,6 @@ from django.core.mail.backends.base import BaseEmailBackend
|
|||||||
from django.core.mail.message import sanitize_address, DEFAULT_ATTACHMENT_MIME_TYPE
|
from django.core.mail.message import sanitize_address, DEFAULT_ATTACHMENT_MIME_TYPE
|
||||||
|
|
||||||
from djrill import MANDRILL_API_URL, MandrillAPIError, NotSupportedByMandrillError, __version__
|
from djrill import MANDRILL_API_URL, MandrillAPIError, NotSupportedByMandrillError, __version__
|
||||||
from djrill.exceptions import removed_in_djrill_2
|
|
||||||
|
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
@@ -37,19 +36,6 @@ def encode_date_for_mandrill(dt):
|
|||||||
return dt
|
return dt
|
||||||
|
|
||||||
|
|
||||||
class JSONDateUTCEncoder(json.JSONEncoder):
|
|
||||||
"""[deprecated] JSONEncoder that encodes dates in string format used by Mandrill."""
|
|
||||||
def default(self, obj):
|
|
||||||
if isinstance(obj, date):
|
|
||||||
removed_in_djrill_2(
|
|
||||||
"You've used the date '%r' as a Djrill message attribute "
|
|
||||||
"(perhaps in merge vars or metadata). Djrill 2.0 will require "
|
|
||||||
"you to explicitly convert this date to a string." % obj
|
|
||||||
)
|
|
||||||
return encode_date_for_mandrill(obj)
|
|
||||||
return super(JSONDateUTCEncoder, self).default(obj)
|
|
||||||
|
|
||||||
|
|
||||||
class DjrillBackend(BaseEmailBackend):
|
class DjrillBackend(BaseEmailBackend):
|
||||||
"""
|
"""
|
||||||
Mandrill API Email Backend
|
Mandrill API Email Backend
|
||||||
@@ -153,7 +139,7 @@ class DjrillBackend(BaseEmailBackend):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
api_data = json.dumps(api_params, cls=JSONDateUTCEncoder)
|
api_data = json.dumps(api_params)
|
||||||
except TypeError as err:
|
except TypeError as err:
|
||||||
# Add some context to the "not JSON serializable" message
|
# Add some context to the "not JSON serializable" message
|
||||||
if not err.args:
|
if not err.args:
|
||||||
|
|||||||
@@ -1,58 +1,8 @@
|
|||||||
# Tests deprecated Djrill features
|
# Tests deprecated Djrill features
|
||||||
|
|
||||||
from datetime import date, datetime
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
from django.core import mail
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from djrill import NotSupportedByMandrillError
|
from djrill import NotSupportedByMandrillError
|
||||||
from djrill.tests.mock_backend import DjrillBackendMockAPITestCase
|
|
||||||
from djrill.tests.utils import reset_warning_registry
|
|
||||||
|
|
||||||
|
|
||||||
class DjrillBackendDeprecationTests(DjrillBackendMockAPITestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
reset_warning_registry()
|
|
||||||
super(DjrillBackendDeprecationTests, self).setUp()
|
|
||||||
|
|
||||||
def test_deprecated_json_date_encoding(self):
|
|
||||||
"""Djrill 2.0+ avoids a blanket JSONDateUTCEncoder"""
|
|
||||||
# Djrill allows dates for send_at, so shouldn't warn:
|
|
||||||
message = mail.EmailMessage('Subject', 'Body', 'from@example.com', ['to@example.com'])
|
|
||||||
message.send_at = datetime(2022, 10, 11, 12, 13, 14, 567)
|
|
||||||
self.assertNotWarns(DeprecationWarning, message.send)
|
|
||||||
|
|
||||||
# merge_vars need to be json-serializable, so should generate a warning:
|
|
||||||
message = mail.EmailMessage('Subject', 'Body', 'from@example.com', ['to@example.com'])
|
|
||||||
message.global_merge_vars = {'DATE': date(2022, 10, 11)}
|
|
||||||
self.assertWarnsMessage(DeprecationWarning,
|
|
||||||
"Djrill 2.0 will require you to explicitly convert this date to a string",
|
|
||||||
message.send)
|
|
||||||
# ... but should still encode the date (for now):
|
|
||||||
data = self.get_api_call_data()
|
|
||||||
self.assertEqual(data['message']['global_merge_vars'],
|
|
||||||
[{'name': 'DATE', 'content': "2022-10-11 00:00:00"}])
|
|
||||||
|
|
||||||
def assertWarnsMessage(self, warning, message, callable, *args, **kwds):
|
|
||||||
"""Checks that `callable` issues a warning of category `warning` containing `message`"""
|
|
||||||
with warnings.catch_warnings(record=True) as warned:
|
|
||||||
warnings.simplefilter("always")
|
|
||||||
callable(*args, **kwds)
|
|
||||||
self.assertGreater(len(warned), 0, msg="No warnings issued")
|
|
||||||
self.assertTrue(
|
|
||||||
any(issubclass(w.category, warning) and message in str(w.message) for w in warned),
|
|
||||||
msg="%r(%r) not found in %r" % (warning, message, [str(w) for w in warned]))
|
|
||||||
|
|
||||||
def assertNotWarns(self, warning, callable, *args, **kwds):
|
|
||||||
"""Checks that `callable` does not issue any warnings of category `warning`"""
|
|
||||||
with warnings.catch_warnings(record=True) as warned:
|
|
||||||
warnings.simplefilter("always")
|
|
||||||
callable(*args, **kwds)
|
|
||||||
relevant_warnings = [w for w in warned if issubclass(w.category, warning)]
|
|
||||||
self.assertEqual(len(relevant_warnings), 0,
|
|
||||||
msg="Unexpected warnings %r" % [str(w) for w in relevant_warnings])
|
|
||||||
|
|
||||||
|
|
||||||
class DjrillLegacyExceptionTests(TestCase):
|
class DjrillLegacyExceptionTests(TestCase):
|
||||||
|
|||||||
@@ -529,7 +529,7 @@ class DjrillMandrillFeatureTests(DjrillBackendMockAPITestCase):
|
|||||||
self.assertEqual(sent, 0)
|
self.assertEqual(sent, 0)
|
||||||
self.assertIsNone(msg.mandrill_response)
|
self.assertIsNone(msg.mandrill_response)
|
||||||
|
|
||||||
def test_json_serialization_warnings(self):
|
def test_json_serialization_errors(self):
|
||||||
"""Try to provide more information about non-json-serializable data"""
|
"""Try to provide more information about non-json-serializable data"""
|
||||||
self.message.global_merge_vars = {'PRICE': Decimal('19.99')}
|
self.message.global_merge_vars = {'PRICE': Decimal('19.99')}
|
||||||
with self.assertRaisesMessage(
|
with self.assertRaisesMessage(
|
||||||
@@ -539,6 +539,12 @@ class DjrillMandrillFeatureTests(DjrillBackendMockAPITestCase):
|
|||||||
):
|
):
|
||||||
self.message.send()
|
self.message.send()
|
||||||
|
|
||||||
|
def test_dates_not_serialized(self):
|
||||||
|
"""Pre-2.0 Djrill accidentally serialized dates to ISO"""
|
||||||
|
self.message.global_merge_vars = {'SHIP_DATE': date(2015, 12, 2)}
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
self.message.send()
|
||||||
|
|
||||||
|
|
||||||
@override_settings(MANDRILL_SETTINGS={
|
@override_settings(MANDRILL_SETTINGS={
|
||||||
'from_name': 'Djrill Test',
|
'from_name': 'Djrill Test',
|
||||||
|
|||||||
@@ -48,6 +48,16 @@ Removed DjrillAdminSite
|
|||||||
(Do this only if you changed to SimpleAdminConfig for Djrill, and aren't
|
(Do this only if you changed to SimpleAdminConfig for Djrill, and aren't
|
||||||
creating custom admin sites for any other Django apps you use.)
|
creating custom admin sites for any other Django apps you use.)
|
||||||
|
|
||||||
|
Removed unintended date-to-string conversion
|
||||||
|
If your code was relying on Djrill to automatically convert date or datetime
|
||||||
|
values to strings in :attr:`merge_vars`, :attr:`metadata`, or other Mandrill
|
||||||
|
message attributes, you must now explicitly do the string conversion
|
||||||
|
yourself. See :ref:`formatting-merge-data` for an explanation.
|
||||||
|
(Djrill 1.4 reported a DeprecationWarning for this case.)
|
||||||
|
|
||||||
|
(The exception is :attr:`send_at`, which Djrill expects can be a date or
|
||||||
|
datetime.)
|
||||||
|
|
||||||
Removed DjrillMessage class
|
Removed DjrillMessage class
|
||||||
The ``DjrillMessage`` class has not been needed since Djrill 0.2.
|
The ``DjrillMessage`` class has not been needed since Djrill 0.2.
|
||||||
You should replace any uses of it with the standard
|
You should replace any uses of it with the standard
|
||||||
@@ -58,24 +68,6 @@ Removed DjrillBackendHTTPError
|
|||||||
with :exc:`djrill.MandrillAPIError`.
|
with :exc:`djrill.MandrillAPIError`.
|
||||||
|
|
||||||
|
|
||||||
**Dates in merge data and other attributes**
|
|
||||||
|
|
||||||
Djrill automatically converts :attr:`send_at` date and datetime
|
|
||||||
values to the ISO 8601 string format expected by the Mandrill API.
|
|
||||||
|
|
||||||
Unintentionally, it also converts dates used in other Mandrill message
|
|
||||||
attributes (such as :attr:`merge_vars` or :attr:`metadata`) where it
|
|
||||||
might not be expected (or appropriate).
|
|
||||||
|
|
||||||
Djrill 2.0 will remove this automatic date formatting, except
|
|
||||||
for attributes that are inherently dates (currently only `send_at`).
|
|
||||||
|
|
||||||
To assist in detecting code relying on the (undocumented) current
|
|
||||||
behavior, Djrill 1.4 will report a DeprecationWarning for date
|
|
||||||
or datetime values used in any Mandrill message attributes other
|
|
||||||
than `send_at`. See :ref:`formatting-merge-data` for other options.
|
|
||||||
|
|
||||||
|
|
||||||
Older Releases
|
Older Releases
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user