Ver código fonte

Fixed #22327 -- Turned BaseEmailBackend into a context manager

Changed the BaseEmailBackend to allow usage as context manager to open
and close connections.
Daniel Neuhäuser 11 anos atrás
pai
commit
4aa80149e7

+ 14 - 0
django/core/mail/backends/base.py

@@ -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

+ 2 - 1
docs/releases/1.8.txt

@@ -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
 ^^^^^^^^^^^^

+ 15 - 0
docs/topics/email.txt

@@ -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
 -----------------------------------------
 

+ 21 - 0
tests/mail/tests.py

@@ -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'