Commits

Matthew Frazier committed 79a2f57

altered the sender interface

Comments (0)

Files changed (6)

cartero/sender.py

     
     def send(self, messages):
         """
-        This sends the given messages and returns the number of messages sent.
-        It should automatically call the `use` and `done` methods.
+        This sends the given messages. It should be able to accept any kind of
+        iterable, as well as a lone `Message` instance.
+        It should automatically call the `use` and `done` methods. (You can
+        use `send_wrapper` to make this a bit easier.)
+        
+        Due to the many perils and uncertainties of sending e-mail, the `send`
+        method takes a very optimistic approach to exceptions. It returns a
+        `dict` that maps `Message` objects to exceptions. If an error
+        happens during the delivery of a message that results in the message
+        definitely not being sent to anyone, the error is stored in the `dict`
+        with the associated `Message` as the key. Any other failures that it
+        is capable of detecting should merely be logged.
+        
+        Exceptions should only be **raised** for connection-level errors (i.e.
+        the SMTP server refused the given credentials).
         """
         raise NotImplementedError("This doesn't actually send messages!")
     
     You can wrap your `send` method with this to make your life easier. When
     called, this will automatically:
     
-    - Return with 0 if an empty iterable was given
+    - Return with {} if an empty iterable was given
     - Ensure that the messages are a `tuple` (even if only a single one was
       passed in) and that they are in fact `Message` instances
     - Call `~Sender.use` and `~Sender.done` for you
         else:
             messages = tuple(messages)
         if not messages:
-            return 0
+            return {}
         if not all(isinstance(m, Message) for m in messages):
             raise TypeError("Only Message instances can be passed to send")
         self.use()

cartero/senders/console.py

                 self.stream.write('\n\n')
         finally:
             self._lock.release()
-        return len(messages)
+        return {}
     
     def format(self, msg):
         if self.config.format == 'friendly':

cartero/senders/memory.py

                          `Message` instance).
         """
         self.active_outbox.extend(messages)
-        return len(messages)
+        return {}

cartero/senders/null.py

             for rcpt in msg.recipients:
                 senderlog.info('NullSender: sending message %s to %s' %
                                (id(msg), rcpt))
-        return len(messages)
+        return {}
 
 
 sender_class = NullSender

tests/sender-tests/test-console-sender.py

     from StringIO import StringIO
 
 
-class StreamTrapper(object):
-    "Hack of epic proportions."
-    def trap_stdout(self):
-        self.old_stdout = sys.stdout
-        sys.stdout = StringIO()
-    
-    def untrap_stdout(self):
-        buf = sys.stdout
-        sys.stdout = self.old_stdout
-        return buf.getvalue()
-    
-    def trap_stderr(self):
-        self.old_stderr = sys.stderr
-        sys.stderr = StringIO()
-    
-    def untrap_stderr(self):
-        buf = sys.stderr
-        sys.stderr = self.old_stderr
-        return buf.getvalue()
-
-
 def make_test_message():
     text = (u'Get to Coruscant as soon as possible, and don\'t tell '
             u'anyone, even General Cracken.')

tests/test-sender-inf.py

     
     def test_send_wrapper(self):
         sdr = Dummy()
-        assert sdr.send(()) == 0
+        assert sdr.send(()) == {}
         msg1 = Message(to='tycho.celchu@starfighter.gffa')
         assert sdr.send(msg1) == (msg1,)
         assert sdr.send([msg1]) == (msg1,)