Fixed #22327 -- Turned BaseEmailBackend into a context manager

Changed the BaseEmailBackend to allow usage as context manager to open
and close connections.
This commit is contained in:
Daniel Neuhäuser 2014-03-23 17:29:10 +01:00 committed by Tim Graham
parent d902fd625d
commit 4aa80149e7
4 changed files with 52 additions and 1 deletions

View File

@ -6,6 +6,13 @@ class BaseEmailBackend(object):
Base class for email backend implementations.
Subclasses must at least overwrite send_messages().
open() and close() can be called indirectly by using a backend object as a
context manager:
with backend as connection:
# do something with connection
pass
"""
def __init__(self, fail_silently=False, **kwargs):
self.fail_silently = fail_silently
@ -32,6 +39,13 @@ class BaseEmailBackend(object):
"""Close a network connection."""
pass
def __enter__(self):
self.open()
return self
def __exit__(self, exc_type, exc_value, traceback):
self.close()
def send_messages(self, email_messages):
"""
Sends one or more EmailMessage objects and returns the number of email

View File

@ -91,7 +91,8 @@ Cache
Email
^^^^^
* ...
* :ref:`Email backends <topic-email-backends>` now support the context manager
protocol for opening and closing connections.
File Storage
^^^^^^^^^^^^

View File

@ -393,6 +393,21 @@ The email backend class has the following methods:
connection afterwards. If the connection is already open, it will be
left open after mail has been sent.
It can also be used as a context manager, which will automatically call
``open()`` and ``close()`` as needed::
from django.core import mail
with mail.get_connection() as connection:
mail.EmailMessage(subject1, body1, from1, [to1],
connection=connection).send()
mail.EmailMessage(subject2, body2, from2, [to2],
connection=connection).send()
.. versionadded:: 1.8
The context manager protocol was added.
Obtaining an instance of an email backend
-----------------------------------------

View File

@ -638,6 +638,27 @@ class BaseEmailBackendTests(HeadersCheckMixin, object):
except Exception as e:
self.fail("close() unexpectedly raised an exception: %s" % e)
def test_use_as_contextmanager(self):
"""
Test that the connection can be used as a contextmanager.
"""
opened = [False]
closed = [False]
conn = mail.get_connection(username='', password='')
def open():
opened[0] = True
conn.open = open
def close():
closed[0] = True
conn.close = close
with conn as same_conn:
self.assertTrue(opened[0])
self.assertIs(same_conn, conn)
self.assertFalse(closed[0])
self.assertTrue(closed[0])
class LocmemBackendTests(BaseEmailBackendTests, SimpleTestCase):
email_backend = 'django.core.mail.backends.locmem.EmailBackend'