Skip to content

Commit ebb6b04

Browse files
committed
Support using AnymailMessage with django-mailer
Make UNSET preserve its identity across pickling. (Also make its repr mention "unset", to simplify interpretting stack traces.) Fixes #147.
1 parent 4c443f5 commit ebb6b04

File tree

3 files changed

+45
-2
lines changed

3 files changed

+45
-2
lines changed

CHANGELOG.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ Release history
2525
^^^^^^^^^^^^^^^
2626
.. This extra heading level keeps the ToC from becoming unmanageably long
2727
28+
vNext
29+
-----
30+
31+
*Unreleased changes on master*
32+
33+
Fixes
34+
~~~~~
35+
36+
* Support using `AnymailMessage` with django-mailer and similar packages that pickle
37+
messages. (See `#147`_. Thanks to `@ewingrj`_ for identifying the problem.)
38+
39+
2840
v6.0
2941
----
3042

@@ -928,11 +940,13 @@ Features
928940
.. _#111: https://github.com/anymail/issues/111
929941
.. _#112: https://github.com/anymail/issues/112
930942
.. _#115: https://github.com/anymail/issues/115
943+
.. _#147: https://github.com/anymail/issues/147
931944

932945
.. _@ailionx: https://github.com/ailionx
933946
.. _@calvin: https://github.com/calvin
934947
.. _@costela: https://github.com/costela
935948
.. _@decibyte: https://github.com/decibyte
949+
.. _@ewingrj: https://github.com/ewingrj
936950
.. _@janneThoft: https://github.com/janneThoft
937951
.. _@joshkersey: https://github.com/joshkersey
938952
.. _@Lekensteyn: https://github.com/Lekensteyn

anymail/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
BASIC_NUMERIC_TYPES = six.integer_types + (float,) # int, float, and (on Python 2) long
2727

2828

29-
UNSET = object() # Used as non-None default value
29+
UNSET = type('UNSET', (object,), {}) # Used as non-None default value
3030

3131

3232
def combine(*args):

tests/test_utils.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Tests for the anymail/utils.py module
22
# (not to be confused with utilities for testing found in in tests/utils.py)
33
import base64
4+
import copy
5+
import pickle
46
from email.mime.image import MIMEImage
57
from unittest import skipIf
68

@@ -24,7 +26,7 @@
2426
parse_address_list, parse_single_address, EmailAddress,
2527
Attachment,
2628
is_lazy, force_non_lazy, force_non_lazy_dict, force_non_lazy_list,
27-
update_deep,
29+
update_deep, UNSET,
2830
get_request_uri, get_request_basic_auth, parse_rfc2822date, querydict_getfirst,
2931
CaseInsensitiveCasePreservingDict)
3032

@@ -441,3 +443,30 @@ def test_get_item(self):
441443

442444
# The base CaseInsensitiveDict functionality is well-tested in Requests,
443445
# so we don't repeat it here.
446+
447+
448+
class UnsetValueTests(SimpleTestCase):
449+
"""Tests for the UNSET sentinel value"""
450+
451+
def test_not_other_values(self):
452+
self.assertIsNot(UNSET, None)
453+
self.assertIsNot(UNSET, False)
454+
self.assertNotEqual(UNSET, 0)
455+
self.assertNotEqual(UNSET, "")
456+
457+
def test_unset_survives_pickle(self):
458+
# Required for using AnymailMessage with django-mailer
459+
pickled = pickle.dumps(UNSET)
460+
self.assertIs(pickle.loads(pickled), UNSET)
461+
462+
def test_unset_survives_copy(self):
463+
self.assertIs(copy.copy(UNSET), UNSET)
464+
self.assertIs(copy.deepcopy(UNSET), UNSET)
465+
466+
def test_unset_has_useful_repr(self):
467+
# (something better than '<object object at ...>')
468+
self.assertIn("UNSET", repr(UNSET))
469+
470+
def test_equality(self):
471+
# `is UNSET` is preferred to `== UNSET`, but both should work
472+
self.assertEqual(UNSET, UNSET)

0 commit comments

Comments
 (0)