← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~gary/launchpad/bug650343-2 into lp:launchpad/devel

 

Gary Poster has proposed merging lp:~gary/launchpad/bug650343-2 into lp:launchpad/devel with lp:~gary/launchpad/bug650343 as a prerequisite.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)


In the reviews for https://code.edge.launchpad.net/~gary/launchpad/bug650343/+merge/37633 , I was asked to move the "incoming"-related files I touched over to lp/services/mail.  This branch performs that move, and does the various changes that make lint then requests.

While we're speaking of lint, here's the output.

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  cronscripts/process-mail.py
  lib/canonical/launchpad/doc/emailauthentication.txt
  lib/canonical/launchpad/ftests/test_system_documentation.py
  lib/canonical/launchpad/mail/handlers.py
  lib/lp/blueprints/doc/spec-mail-exploder.txt
  lib/lp/services/mail/incoming.py
  lib/lp/services/mail/tests/incomingmail.txt
  lib/lp/services/mail/tests/test_dkim.py
  lib/lp/services/mail/tests/test_incoming.py
  lib/lp/services/mail/tests/test_signedmessage.py

./cronscripts/process-mail.py
       9: '_pythonpath' imported but unused
./lib/canonical/launchpad/doc/emailauthentication.txt
     155: want exceeds 78 characters.

The ./cronscripts/process-mail.py request is because of our weird _pythonpath dance (maybe we should make these all buildout-generated scripts someday...or not).  Anyway, it's not pertinent.

The request for ./lib/canonical/launchpad/doc/emailauthentication.txt appears to not be appropriate: the test explicitly turns off whitespace normalization there, so I think the long line is intended.

Tests passed on ec2 with the current branch, except for a Windmill error that appears to be spurious.

Other than that, the only thing I know to mention is that I did not move the files I touched for this move (lib/canonical/launchpad/doc/emailauthentication.txt lib/canonical/launchpad/ftests/test_system_documentation.py lib/canonical/launchpad/mail/handlers.py).  Hopefully the move request does not have to cascade like that, or I may be at this for awhile. :-)

Thank you.
-- 
https://code.launchpad.net/~gary/launchpad/bug650343-2/+merge/38224
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~gary/launchpad/bug650343-2 into lp:launchpad/devel.
=== modified file 'cronscripts/process-mail.py'
--- cronscripts/process-mail.py	2010-10-03 15:30:06 +0000
+++ cronscripts/process-mail.py	2010-10-12 14:17:47 +0000
@@ -13,7 +13,7 @@
 from canonical.config import config
 from lp.services.scripts.base import (
     LaunchpadCronScript, LaunchpadScriptFailure)
-from canonical.launchpad.mail.incoming import handleMail
+from lp.services.mail.incoming import handleMail
 from canonical.launchpad.interfaces import IMailBox
 
 
@@ -21,6 +21,7 @@
     usage = """%prog [options]
 
     """ + __doc__
+
     def main(self):
         try:
             handleMail(self.txn)

=== modified file 'lib/canonical/launchpad/doc/emailauthentication.txt'
--- lib/canonical/launchpad/doc/emailauthentication.txt	2010-10-04 19:50:45 +0000
+++ lib/canonical/launchpad/doc/emailauthentication.txt	2010-10-12 14:17:47 +0000
@@ -1,9 +1,10 @@
-= Authentication of Emails =
+Authentication of Emails
+========================
 
 When an email arrives in Launchpad the user who sent it needs to be
 authenticated. This is done by authenticateEmail:
 
-    >>> from canonical.launchpad.mail.incoming import authenticateEmail
+    >>> from lp.services.mail.incoming import authenticateEmail
 
 The only way of authenticating the user is by looking at the OpenPGP
 signature. First we have to import the OpenPGP keys we will use in the
@@ -159,7 +160,8 @@
     Sample Person
 
 
-== IWeaklyAuthenticatedPrinipal ==
+IWeaklyAuthenticatedPrincipal
+-----------------------------
 
 It's a huge difference to signing an email with a key that is associated
 with the authenticated Person, and signing it with a key that isn't
@@ -172,7 +174,8 @@
 
 An unsigned email:
 
-    >>> from canonical.launchpad.interfaces import IWeaklyAuthenticatedPrincipal
+    >>> from canonical.launchpad.interfaces import (
+    ...     IWeaklyAuthenticatedPrincipal)
     >>> msg = read_test_message('unsigned_multipart.txt')
     >>> principal = authenticateEmail(msg)
     >>> IWeaklyAuthenticatedPrincipal.providedBy(principal)

=== modified file 'lib/canonical/launchpad/ftests/test_system_documentation.py'
--- lib/canonical/launchpad/ftests/test_system_documentation.py	2010-10-03 15:30:06 +0000
+++ lib/canonical/launchpad/ftests/test_system_documentation.py	2010-10-12 14:17:47 +0000
@@ -52,6 +52,7 @@
 
 here = os.path.dirname(os.path.realpath(__file__))
 
+
 def lobotomize_stevea():
     """Set SteveA's email address' status to NEW.
 
@@ -79,17 +80,20 @@
     LaunchpadZopelessLayer.switchDbUser('poexport')
     setUp(test)
 
+
 def poExportTearDown(test):
     """Tear down the PO export script tests."""
     # XXX sinzui 2007-11-14:
     # This function is not needed. The test should be switched to tearDown.
     tearDown(test)
 
+
 def uploaderSetUp(test):
     """setup the package uploader script tests."""
     setUp(test)
     LaunchpadZopelessLayer.switchDbUser('uploader')
 
+
 def uploaderTearDown(test):
     """Tear down the package uploader script tests."""
     # XXX sinzui 2007-11-14:
@@ -115,6 +119,7 @@
     # This function is not needed. The test should be switched to tearDown.
     tearDown(test)
 
+
 def uploadQueueSetUp(test):
     lobotomize_stevea()
     test_dbuser = config.uploadqueue.dbuser
@@ -127,6 +132,7 @@
     """Clean up any Zope registrations."""
     cleanUp()
 
+
 def _createUbuntuBugTaskLinkedToQuestion():
     """Get the id of an Ubuntu bugtask linked to a question.
 
@@ -154,10 +160,13 @@
     pop_notifications()
     return ubuntu_bugtask.id
 
+
 def bugLinkedToQuestionSetUp(test):
     """Setup the question and linked bug for testing."""
+
     def get_bugtask_linked_to_question():
         return getUtility(IBugTaskSet).get(bugtask_id)
+
     setUp(test)
     bugtask_id = _createUbuntuBugTaskLinkedToQuestion()
     test.globs['get_bugtask_linked_to_question'] = (
@@ -166,6 +175,7 @@
     # interaction in the test.
     login('no-priv@xxxxxxxxxxxxx')
 
+
 def uploaderBugLinkedToQuestionSetUp(test):
     LaunchpadZopelessLayer.switchDbUser('launchpad')
     bugLinkedToQuestionSetUp(test)
@@ -173,6 +183,7 @@
     uploaderSetUp(test)
     login(ANONYMOUS)
 
+
 def uploadQueueBugLinkedToQuestionSetUp(test):
     LaunchpadZopelessLayer.switchDbUser('launchpad')
     bugLinkedToQuestionSetUp(test)
@@ -185,8 +196,7 @@
 special = {
     # No setup or teardown at all, since it is demonstrating these features.
     'old-testing.txt': LayeredDocFileSuite(
-            '../doc/old-testing.txt', layer=FunctionalLayer
-            ),
+        '../doc/old-testing.txt', layer=FunctionalLayer),
 
     'autodecorate.txt':
         LayeredDocFileSuite('../doc/autodecorate.txt', layer=BaseLayer),
@@ -194,84 +204,70 @@
 
     # And this test want minimal environment too.
     'package-relationship.txt': LayeredDocFileSuite(
-            '../doc/package-relationship.txt',
-            stdout_logging=False, layer=None
-            ),
+        '../doc/package-relationship.txt',
+        stdout_logging=False, layer=None),
 
     'webservice-configuration.txt': LayeredDocFileSuite(
-            '../doc/webservice-configuration.txt',
-            setUp=setGlobs, tearDown=layerlessTearDown, layer=None
-            ),
+        '../doc/webservice-configuration.txt',
+        setUp=setGlobs, tearDown=layerlessTearDown, layer=None),
 
 
     # POExport stuff is Zopeless and connects as a different database user.
     # poexport-distroseries-(date-)tarball.txt is excluded, since they add
     # data to the database as well.
     'message.txt': LayeredDocFileSuite(
-            '../doc/message.txt',
-            setUp=setUp, tearDown=tearDown, layer=LaunchpadFunctionalLayer
-            ),
+        '../doc/message.txt',
+        setUp=setUp, tearDown=tearDown, layer=LaunchpadFunctionalLayer),
     'close-account.txt': LayeredDocFileSuite(
-            '../doc/close-account.txt', setUp=setUp, tearDown=tearDown,
-            layer=LaunchpadZopelessLayer
-            ),
+        '../doc/close-account.txt', setUp=setUp, tearDown=tearDown,
+        layer=LaunchpadZopelessLayer),
     'launchpadform.txt': LayeredDocFileSuite(
-            '../doc/launchpadform.txt',
-            setUp=setUp, tearDown=tearDown,
-            layer=LaunchpadFunctionalLayer
-            ),
+        '../doc/launchpadform.txt',
+        setUp=setUp, tearDown=tearDown,
+        layer=LaunchpadFunctionalLayer),
     'launchpadformharness.txt': LayeredDocFileSuite(
-            '../doc/launchpadformharness.txt',
-            setUp=setUp, tearDown=tearDown,
-            layer=LaunchpadFunctionalLayer
-            ),
+        '../doc/launchpadformharness.txt',
+        setUp=setUp, tearDown=tearDown,
+        layer=LaunchpadFunctionalLayer),
     'uri.txt': LayeredDocFileSuite(
-            '../doc/uri.txt',
-            setUp=setUp, tearDown=tearDown,
-            layer=FunctionalLayer
-            ),
+        '../doc/uri.txt',
+        setUp=setUp, tearDown=tearDown,
+        layer=FunctionalLayer),
     'notification-text-escape.txt': LayeredDocFileSuite(
-            '../doc/notification-text-escape.txt',
-            setUp=test_notifications.setUp,
-            tearDown=test_notifications.tearDown,
-            stdout_logging=False, layer=None
-            ),
+        '../doc/notification-text-escape.txt',
+        setUp=test_notifications.setUp,
+        tearDown=test_notifications.tearDown,
+        stdout_logging=False, layer=None),
     # This test is actually run twice to prove that the AppServerLayer
     # properly isolates the database between tests.
     'launchpadlib.txt': LayeredDocFileSuite(
         '../doc/launchpadlib.txt',
         layer=AppServerLayer,
-        setUp=browser.setUp, tearDown=browser.tearDown,
-        ),
+        setUp=browser.setUp, tearDown=browser.tearDown,),
     'launchpadlib2.txt': LayeredDocFileSuite(
         '../doc/launchpadlib.txt',
         layer=AppServerLayer,
-        setUp=browser.setUp, tearDown=browser.tearDown,
-        ),
+        setUp=browser.setUp, tearDown=browser.tearDown,),
     # XXX gary 2008-12-08 bug=306246 bug=305858: Disabled test because of
     # multiple spurious problems with layer and test.
     # 'google-service-stub.txt': LayeredDocFileSuite(
-    #         '../doc/google-service-stub.txt',
-    #         layer=GoogleServiceLayer,
-    #         ),
+    #     '../doc/google-service-stub.txt',
+    #     layer=GoogleServiceLayer,),
     'canonical_url.txt': LayeredDocFileSuite(
-            '../doc/canonical_url.txt',
-            setUp=setUp,
-            tearDown=tearDown,
-            layer=FunctionalLayer,
-            ),
+        '../doc/canonical_url.txt',
+        setUp=setUp,
+        tearDown=tearDown,
+        layer=FunctionalLayer,),
     'google-searchservice.txt': LayeredDocFileSuite(
-            '../doc/google-searchservice.txt',
-            setUp=setUp, tearDown=tearDown,
-            layer=GoogleLaunchpadFunctionalLayer,
-            ),
+        '../doc/google-searchservice.txt',
+        setUp=setUp, tearDown=tearDown,
+        layer=GoogleLaunchpadFunctionalLayer,),
     }
 
 
 class ProcessMailLayer(LaunchpadZopelessLayer):
     """Layer containing the tests running inside process-mail.py."""
 
-
     @classmethod
     def testSetUp(cls):
         """Fixture replicating the process-mail.py environment.
@@ -287,7 +283,7 @@
         """Tear down the test fixture."""
         setSecurityPolicy(cls._old_policy)
 
-    doctests_without_logging = [
+    doctests = [
         # XXX gary 2008-12-06 bug=305856: Spurious test failure
         # discovered on buildbot, build 40.  Note that, to completely
         # disable the test from running, the filename has been changed
@@ -299,21 +295,16 @@
         '../doc/emailauthentication.txt',
         ]
 
-    doctests_with_logging = [
-        '../doc/incomingmail.txt',
-        ]
-
     @classmethod
     def addTestsToSpecial(cls):
         """Adds all the tests related to process-mail.py to special"""
-        for filepath in cls.doctests_without_logging:
-            filename = os.path.basename(filepath)
-            special[filename] = cls.createLayeredDocFileSuite(filepath)
-
-        for filepath in cls.doctests_with_logging:
-            filename = os.path.basename(filepath)
-            special[filename] = cls.createLayeredDocFileSuite(
-                filepath, stdout_logging=True)
+        for filepath in cls.doctests:
+            filename = os.path.basename(filepath)
+            special[filename] = LayeredDocFileSuite(
+                filepath,
+                setUp=setUp, tearDown=tearDown,
+                layer=cls,
+                stdout_logging=False)
 
         # Adds a copy of some bug doctests that will be run with
         # the processmail user.
@@ -337,16 +328,6 @@
                 layer=cls,
                 stdout_logging=False)
 
-    @classmethod
-    def createLayeredDocFileSuite(cls, filename, stdout_logging=False):
-        """Helper to create a doctest using this layer."""
-        return LayeredDocFileSuite(
-            filename,
-            setUp=setUp, tearDown=tearDown,
-            layer=cls,
-            stdout_logging=stdout_logging,
-            stdout_logging_level=logging.WARNING)
-
 
 ProcessMailLayer.addTestsToSpecial()
 
@@ -360,15 +341,13 @@
         suite.addTest(special_suite)
 
     testsdir = os.path.abspath(
-            os.path.normpath(os.path.join(here, '..', 'doc'))
-            )
+        os.path.normpath(os.path.join(here, '..', 'doc')))
 
     # Add tests using default setup/teardown
     filenames = [filename
                  for filename in os.listdir(testsdir)
                  if filename.lower().endswith('.txt')
-                    and filename not in special
-                 ]
+                    and filename not in special]
     # Sort the list to give a predictable order.  We do this because when
     # tests interfere with each other, the varying orderings that os.listdir
     # gives on different people's systems make reproducing and debugging
@@ -383,8 +362,7 @@
             layer=LaunchpadFunctionalLayer,
             # 'icky way of running doctests with __future__ imports
             globs={'with_statement': with_statement},
-            stdout_logging_level=logging.WARNING
-            )
+            stdout_logging_level=logging.WARNING)
         suite.addTest(one_test)
 
     return suite

=== modified file 'lib/canonical/launchpad/mail/handlers.py'
--- lib/canonical/launchpad/mail/handlers.py	2010-10-03 15:30:06 +0000
+++ lib/canonical/launchpad/mail/handlers.py	2010-10-12 14:17:47 +0000
@@ -61,7 +61,7 @@
 
 def extract_signature_timestamp(signed_msg):
     # break import cycle
-    from canonical.launchpad.mail.incoming import (
+    from lp.services.mail.incoming import (
         canonicalise_line_endings)
     signature = getUtility(IGPGHandler).getVerifiedSignature(
         canonicalise_line_endings(signed_msg.signedContent),

=== modified file 'lib/lp/blueprints/doc/spec-mail-exploder.txt'
--- lib/lp/blueprints/doc/spec-mail-exploder.txt	2010-10-12 14:17:46 +0000
+++ lib/lp/blueprints/doc/spec-mail-exploder.txt	2010-10-12 14:17:47 +0000
@@ -269,7 +269,7 @@
     >>> moin_change['Sender'] = 'webmaster@xxxxxxxxxx'
 
     >>> from lp.services.mail.sendmail import sendmail
-    >>> from canonical.launchpad.mail.incoming import handleMail
+    >>> from lp.services.mail.incoming import handleMail
     >>> sendmail(moin_change, bulk=False)
     '...'
 

=== renamed file 'lib/canonical/launchpad/mail/incoming.py' => 'lib/lp/services/mail/incoming.py'
--- lib/canonical/launchpad/mail/incoming.py	2010-10-12 14:17:46 +0000
+++ lib/lp/services/mail/incoming.py	2010-10-12 14:17:47 +0000
@@ -325,7 +325,7 @@
                     mail = signed_message_from_string(raw_mail)
                 except email.Errors.MessageError, error:
                     mailbox.delete(mail_id)
-                    log = logging.getLogger('canonical.launchpad.mail')
+                    log = logging.getLogger('lp.services.mail')
                     log.warn(
                         "Couldn't convert email to email.Message: %s" % (
                             file_alias_url, ),
@@ -369,7 +369,7 @@
                 if 'X-Launchpad-Original-To' in mail:
                     addresses = [mail['X-Launchpad-Original-To']]
                 else:
-                    log = logging.getLogger('canonical.launchpad.mail')
+                    log = logging.getLogger('lp.services.mail')
                     log.warn(
                         "No X-Launchpad-Original-To header was present "
                         "in email: %s" %

=== renamed file 'lib/canonical/launchpad/doc/incomingmail.txt' => 'lib/lp/services/mail/tests/incomingmail.txt'
--- lib/canonical/launchpad/doc/incomingmail.txt	2010-10-12 14:17:46 +0000
+++ lib/lp/services/mail/tests/incomingmail.txt	2010-10-12 14:17:47 +0000
@@ -4,7 +4,7 @@
 When an email is sent to Launchpad we need to handle it somehow. This
 is done by handleEmails:
 
-    >>> from canonical.launchpad.mail.incoming import handleMail
+    >>> from lp.services.mail.incoming import handleMail
 
 Basically what it does is to open the Launchpad mail box, and for each
 message it:
@@ -88,10 +88,10 @@
 header is missing.)
 
     >>> handleMail(zopeless_transaction)
-    WARNING:canonical.launchpad.mail:No X-Launchpad-Original-To header was present ...
-    WARNING:canonical.launchpad.mail:No X-Launchpad-Original-To header was present ...
-    WARNING:canonical.launchpad.mail:No X-Launchpad-Original-To header was present ...
-    WARNING:canonical.launchpad.mail:No X-Launchpad-Original-To header was present ...
+    WARNING:lp.services.mail:No X-Launchpad-Original-To header was present ...
+    WARNING:lp.services.mail:No X-Launchpad-Original-To header was present ...
+    WARNING:lp.services.mail:No X-Launchpad-Original-To header was present ...
+    WARNING:lp.services.mail:No X-Launchpad-Original-To header was present ...
 
 Now we can see that each handler handled the emails sent to its domain:
 
@@ -389,7 +389,7 @@
     >>> len(stub.test_emails)
     2
 
-    >>> handleMail(transaction)
+    >>> handleMail(zopeless_transaction)
     ERROR:...:Upload to Librarian failed...
     ...
     UploadFailed: ...Connection refused...

=== modified file 'lib/lp/services/mail/tests/test_dkim.py'
--- lib/lp/services/mail/tests/test_dkim.py	2010-08-20 20:31:18 +0000
+++ lib/lp/services/mail/tests/test_dkim.py	2010-10-12 14:17:47 +0000
@@ -11,14 +11,11 @@
 
 import dkim
 import dns.resolver
-from zope.component import getUtility
 
 from canonical.launchpad.interfaces.mail import IWeaklyAuthenticatedPrincipal
-from canonical.launchpad.mail import (
-    incoming,
-    signed_message_from_string,
-    )
-from canonical.launchpad.mail.incoming import authenticateEmail
+from canonical.launchpad.mail import signed_message_from_string
+from lp.services.mail import incoming
+from lp.services.mail.incoming import authenticateEmail
 from canonical.testing.layers import DatabaseFunctionalLayer
 from lp.testing import TestCaseWithFactory
 
@@ -77,33 +74,36 @@
 
     def fake_signing(self, plain_message, canonicalize=None):
         if canonicalize is None:
-            canonicalize = (dkim.Relaxed, dkim.Relaxed) 
+            canonicalize = (dkim.Relaxed, dkim.Relaxed)
         dkim_line = dkim.sign(plain_message,
-            selector='example', 
+            selector='example',
             domain='canonical.com',
             privkey=sample_privkey,
             debuglog=self._log_output,
-            canonicalize=canonicalize
-            )
+            canonicalize=canonicalize)
         assert dkim_line[-1] == '\n'
         return dkim_line + plain_message
 
     def monkeypatch_dns(self):
         self._dns_responses = {}
+
         def my_lookup(name):
             try:
                 return self._dns_responses[name]
             except KeyError:
                 raise dns.resolver.NXDOMAIN()
+
         orig_dnstxt = dkim.dnstxt
         dkim.dnstxt = my_lookup
+
         def restore():
             dkim.dnstxt = orig_dnstxt
+
         self.addCleanup(restore)
 
     def get_dkim_log(self):
         return self._log_output.getvalue()
-    
+
     def assertStronglyAuthenticated(self, principal, signed_message):
         if IWeaklyAuthenticatedPrincipal.providedBy(principal):
             self.fail('expected strong authentication; got weak:\n'
@@ -157,8 +157,10 @@
         self._dns_responses['example._domainkey.canonical.com.'] = \
             sample_dns
         saved_domains = incoming._trusted_dkim_domains[:]
+
         def restore():
             incoming._trusted_dkim_domains = saved_domains
+
         self.addCleanup(restore)
         incoming._trusted_dkim_domains = []
         principal = authenticateEmail(
@@ -185,14 +187,15 @@
             'steve.alexander@xxxxxxxxxxxxxxx')
 
     def test_dkim_changed_from_address(self):
-        # if the address part of the message has changed, it's detected.  we
-        # still treat this as weakly authenticated by the purported From-header
-        # sender, though perhaps in future we would prefer to reject these
-        # messages.
+        # If the address part of the message has changed, it's detected.
+        #  We still treat this as weakly authenticated by the purported
+        # From-header sender, though perhaps in future we would prefer
+        # to reject these messages.
         signed_message = self.fake_signing(plain_content)
         self._dns_responses['example._domainkey.canonical.com.'] = \
             sample_dns
-        fiddled_message = signed_message.replace('From: Foo Bar <foo.bar@xxxxxxxxxxxxx>',
+        fiddled_message = signed_message.replace(
+            'From: Foo Bar <foo.bar@xxxxxxxxxxxxx>',
             'From: Carlos <carlos@xxxxxxxxxxxxx>')
         principal = authenticateEmail(
             signed_message_from_string(fiddled_message))
@@ -202,22 +205,23 @@
             'carlos@xxxxxxxxxxxxx')
 
     def test_dkim_changed_from_realname(self):
-        # if the real name part of the message has changed, it's detected
+        # If the real name part of the message has changed, it's detected.
         signed_message = self.fake_signing(plain_content)
         self._dns_responses['example._domainkey.canonical.com.'] = \
             sample_dns
-        fiddled_message = signed_message.replace('From: Foo Bar <foo.bar@xxxxxxxxxxxxx>',
+        fiddled_message = signed_message.replace(
+            'From: Foo Bar <foo.bar@xxxxxxxxxxxxx>',
             'From: Evil Foo <foo.bar@xxxxxxxxxxxxx>')
         principal = authenticateEmail(
             signed_message_from_string(fiddled_message))
-        # we don't care about the real name for determining the principal
+        # We don't care about the real name for determining the principal.
         self.assertWeaklyAuthenticated(principal, fiddled_message)
         self.assertEqual(principal.person.preferredemail.email,
             'foo.bar@xxxxxxxxxxxxx')
 
     def test_dkim_nxdomain(self):
-        # if there's no DNS entry for the pubkey
-        # it should be handled decently
+        # If there's no DNS entry for the pubkey it should be handled
+        # decently.
         signed_message = self.fake_signing(plain_content)
         principal = authenticateEmail(
             signed_message_from_string(signed_message))
@@ -226,18 +230,19 @@
             'foo.bar@xxxxxxxxxxxxx')
 
     def test_dkim_message_unsigned(self):
-        # degenerate case: no signature treated as weakly authenticated
+        # This is a degenerate case: no signature is treated as weakly
+        # authenticated.
+        # The library doesn't log anything if there's no header at all.
         principal = authenticateEmail(
             signed_message_from_string(plain_content))
         self.assertWeaklyAuthenticated(principal, plain_content)
         self.assertEqual(principal.person.preferredemail.email,
             'foo.bar@xxxxxxxxxxxxx')
-        # the library doesn't log anything if there's no header at all
 
     def test_dkim_body_mismatch(self):
-        # The message message has a syntactically valid DKIM signature that
-        # doesn't actually correspond to what was signed.  We log something about
-        # this but we don't want to drop the message.
+        # The message message has a syntactically valid DKIM signature
+        # that doesn't actually correspond to what was signed.  We log
+        # something about this but we don't want to drop the message.
         signed_message = self.fake_signing(plain_content)
         signed_message += 'blah blah'
         self._dns_responses['example._domainkey.canonical.com.'] = \

=== renamed file 'lib/canonical/launchpad/mail/tests/test_incoming.py' => 'lib/lp/services/mail/tests/test_incoming.py' (properties changed: -x to +x)
--- lib/canonical/launchpad/mail/tests/test_incoming.py	2010-10-04 19:50:45 +0000
+++ lib/lp/services/mail/tests/test_incoming.py	2010-10-12 14:17:47 +0000
@@ -2,13 +2,19 @@
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 from doctest import DocTestSuite
+import logging
 import os
 import unittest
 
 import transaction
 
+from zope.security.management import setSecurityPolicy
+
+from canonical.config import config
 from canonical.launchpad.mail.ftests.helpers import testmails_path
-from canonical.launchpad.mail.incoming import (
+from canonical.launchpad.testing.systemdocs import LayeredDocFileSuite
+from canonical.launchpad.webapp.authorization import LaunchpadSecurityPolicy
+from lp.services.mail.incoming import (
     handleMail,
     MailErrorUtility,
     )
@@ -77,10 +83,26 @@
             self.assertEqual(old_oops.id, current_oops.id)
 
 
+def setUp(test):
+    test._old_policy = setSecurityPolicy(LaunchpadSecurityPolicy)
+    LaunchpadZopelessLayer.switchDbUser(config.processmail.dbuser)
+
+
+def tearDown(test):
+    setSecurityPolicy(test._old_policy)
+
+
 def test_suite():
     suite = unittest.TestSuite()
     suite.addTest(unittest.TestLoader().loadTestsFromName(__name__))
-    suite.addTest(DocTestSuite('canonical.launchpad.mail.incoming'))
+    suite.addTest(DocTestSuite('lp.services.mail.incoming'))
+    suite.addTest(
+        LayeredDocFileSuite(
+            'incomingmail.txt',
+            setUp=setUp,
+            tearDown=tearDown,
+            layer=LaunchpadZopelessLayer,
+            stdout_logging_level=logging.WARNING))
     return suite
 
 

=== modified file 'lib/lp/services/mail/tests/test_signedmessage.py'
--- lib/lp/services/mail/tests/test_signedmessage.py	2010-08-20 20:31:18 +0000
+++ lib/lp/services/mail/tests/test_signedmessage.py	2010-10-12 14:17:47 +0000
@@ -25,18 +25,18 @@
 from canonical.launchpad.interfaces.gpghandler import IGPGHandler
 from canonical.launchpad.interfaces.mail import IWeaklyAuthenticatedPrincipal
 from canonical.launchpad.mail import signed_message_from_string
-from canonical.launchpad.mail.incoming import (
+from canonical.testing.layers import DatabaseFunctionalLayer
+from lp.registry.interfaces.person import IPersonSet
+from lp.services.mail.incoming import (
     authenticateEmail,
     canonicalise_line_endings,
     )
-from canonical.testing.layers import DatabaseFunctionalLayer
-from lp.registry.interfaces.person import IPersonSet
 from lp.testing import TestCaseWithFactory
 from lp.testing.factory import GPGSigningContext
 
 
 class TestSignedMessage(TestCaseWithFactory):
-    """Test SignedMessage class correctly extracts and verifies the GPG signatures."""
+    "Test SignedMessage class correctly extracts and verifies GPG signatures."
 
     layer = DatabaseFunctionalLayer
 
@@ -154,4 +154,3 @@
 
 def test_suite():
     return unittest.TestLoader().loadTestsFromName(__name__)
-