Skip to content

Commit aa86377

Browse files
ciottochristianbianciotto
authored andcommitted
fixe cannot serialize '_io.BufferedReader' object (#15)
Co-authored-by: christianbianciotto <[email protected]>
1 parent 887c6c0 commit aa86377

File tree

2 files changed

+108
-13
lines changed

2 files changed

+108
-13
lines changed

src/mail_panel/backend.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,32 @@
1+
from django.core import mail
12
from django.core.mail.backends.locmem import EmailBackend
23
import datetime
34
from uuid import uuid4
45

56
from .utils import load_outbox, save_outbox
67

8+
9+
class MailToolbarBackendEmail(mail.EmailMultiAlternatives):
10+
def __init__(self, message):
11+
try:
12+
self.id = uuid4().get_hex()
13+
except AttributeError:
14+
self.id = uuid4().hex # python 3
15+
self.date_sent = datetime.datetime.now()
16+
self.read = False
17+
message.message() # triggers header validation
18+
19+
super(MailToolbarBackendEmail, self).__init__(
20+
to=message.to,
21+
cc=message.cc,
22+
bcc=message.bcc,
23+
reply_to=message.reply_to,
24+
from_email=message.from_email,
25+
body=message.body,
26+
alternatives=message.alternatives,
27+
)
28+
29+
730
class MailToolbarBackend(EmailBackend):
831
"""A email backend for use during testing.
932
@@ -19,19 +42,12 @@ def __init__(self, *args, **kwargs):
1942

2043
self.outbox = load_outbox()
2144

22-
2345
def send_messages(self, messages):
2446
"""Redirect messages to the cached outbox"""
2547

2648
for message in messages:
27-
try:
28-
message.id = uuid4().get_hex()
29-
except AttributeError:
30-
message.id = uuid4().hex # python 3
31-
message.date_sent = datetime.datetime.now()
32-
message.read = False
33-
message.message() # triggers header validation
34-
self.outbox[message.id] = message
49+
new_message = MailToolbarBackendEmail(message)
50+
self.outbox[new_message.id] = new_message
3551

3652
save_outbox(self.outbox)
3753

tests/test_toolbar.py

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,62 @@
1+
import io
2+
import pickle
3+
14
from .context import *
25

36
import unittest
47
import debug_toolbar
8+
from debug_toolbar.toolbar import DebugToolbar
9+
from django.core import mail
10+
from mail_panel.backend import MailToolbarBackendEmail, MailToolbarBackend
511
from mail_panel.panels import MailToolbarPanel
612

13+
from django.test.client import RequestFactory
14+
rf = RequestFactory()
15+
get_request = rf.get('/hello/')
16+
post_request = rf.post('/submit/', {'foo': 'bar'})
17+
718

819
class ToolbarSuite(unittest.TestCase):
920
def setUp(self):
1021
debug_toolbar_version = debug_toolbar.VERSION
11-
22+
23+
self.request = rf.post('/submit/', {'foo': 'bar'})
24+
1225
# django-debug-toolbar 1.x take 1 argument, 2.x take 2 arguments
13-
self.panel_args = (None, None)
1426
if debug_toolbar_version < '2.0':
15-
self.panel_args = (None, )
27+
self.toolbar = DebugToolbar(self.request)
28+
self.panel_args = (self.toolbar, )
29+
else:
30+
self.toolbar = DebugToolbar(self.request, None)
31+
self.panel_args = (self.toolbar, None)
32+
33+
@staticmethod
34+
def get_fake_message(
35+
to=None,
36+
cc=None,
37+
bcc=None,
38+
reply_to=None,
39+
from_email=None,
40+
body=None,
41+
alternatives=None,
42+
):
43+
# TODO Use Faker (https://github.com/joke2k/faker)
44+
return mail.EmailMultiAlternatives(
45+
to=to or ['[email protected]'],
46+
cc=cc or ['[email protected]'],
47+
bcc=bcc or ['[email protected]'],
48+
reply_to=reply_to or ['[email protected]'],
49+
from_email=from_email or '[email protected]',
50+
body=body or 'body',
51+
alternatives=alternatives or [('<b>HTML</b> body', 'text/html')],
52+
)
1653

1754
def test_panel(self):
1855
"""
1956
General 'does it run' test.
2057
"""
2158
p = MailToolbarPanel(*self.panel_args)
22-
self.assertIsNone(p.toolbar)
59+
self.assertEqual(p.toolbar, self.toolbar)
2360

2461
def test_generate_stats(self):
2562
p = MailToolbarPanel(*self.panel_args)
@@ -29,10 +66,52 @@ def test_process_response(self):
2966
p = MailToolbarPanel(*self.panel_args)
3067
p.process_response(None, None)
3168

69+
def test_backend_email(self):
70+
fake_message = self.get_fake_message()
71+
72+
# Create MailToolbarBackendEmail from fake EmailMultiAlternatives
73+
message = MailToolbarBackendEmail(fake_message)
74+
75+
# Check email fields
76+
self.assertEqual(message.to, fake_message.to)
77+
self.assertEqual(message.cc, fake_message.cc)
78+
self.assertEqual(message.bcc, fake_message.bcc)
79+
self.assertEqual(message.reply_to, fake_message.reply_to)
80+
self.assertEqual(message.from_email, fake_message.from_email)
81+
self.assertEqual(message.body, fake_message.body)
82+
self.assertEqual(message.alternatives, fake_message.alternatives)
83+
84+
# Check extra fields
85+
self.assertIsNotNone(message.id)
86+
self.assertIsNotNone(message.date_sent)
87+
self.assertFalse(message.read)
88+
89+
def test_backend(self):
90+
# Test with simple message
91+
fake_message = self.get_fake_message()
92+
93+
backend = MailToolbarBackend()
94+
backend.send_messages([fake_message])
95+
96+
# Test with not serializable message
97+
fake_message = self.get_fake_message()
98+
fake_message.not_serializable_field = io.BufferedReader(io.StringIO(u'initial text data'))
99+
100+
# BufferedReader is serializable in Python2
101+
if sys.version_info[0] >= 3:
102+
with self.assertRaises(TypeError):
103+
pickle.dumps(fake_message, pickle.HIGHEST_PROTOCOL)
104+
105+
backend = MailToolbarBackend()
106+
backend.send_messages([fake_message])
107+
108+
32109
def suite():
33110
suite = unittest.TestSuite()
34111
suite.addTest(unittest.makeSuite(ToolbarSuite))
35112
return suite
36113

114+
37115
def main():
38116
unittest.TextTestRunner().run(suite())
117+

0 commit comments

Comments
 (0)