← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:doctest-remove-py2-exception-module into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:doctest-remove-py2-exception-module into launchpad:master.

Commit message:
Remove all uses of IGNORE_EXCEPTION_MODULE_IN_PYTHON2

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/407194

This is no longer needed now that we require Python 3.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:doctest-remove-py2-exception-module into launchpad:master.
diff --git a/lib/lp/answers/doc/faq.txt b/lib/lp/answers/doc/faq.txt
index 594242d..c4af905 100644
--- a/lib/lp/answers/doc/faq.txt
+++ b/lib/lp/answers/doc/faq.txt
@@ -320,7 +320,6 @@ That change is also considered an answer:
 It is not possible to modify the faq attribute directly:
 
     >>> fnord_question.faq = None
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.ForbiddenAttribute: ...
@@ -329,7 +328,6 @@ And it is not allowed to call linkFAQ() when the FAQ is already linked:
 
     >>> message = fnord_question.linkFAQ(
     ...     no_priv, firefox_faq, 'See the FAQ.')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.answers.errors.FAQTargetError: Cannot call linkFAQ() with already linked FAQ.
diff --git a/lib/lp/answers/doc/faqtarget.txt b/lib/lp/answers/doc/faqtarget.txt
index 0518e70..d3302d1 100644
--- a/lib/lp/answers/doc/faqtarget.txt
+++ b/lib/lp/answers/doc/faqtarget.txt
@@ -38,7 +38,6 @@ the target.
 
     >>> no_priv = getUtility(ILaunchBag).user
     >>> target.newFAQ(no_priv, 'Title', 'Summary', content='Content')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/answers/doc/questiontarget.txt b/lib/lp/answers/doc/questiontarget.txt
index 99731b0..252d463 100644
--- a/lib/lp/answers/doc/questiontarget.txt
+++ b/lib/lp/answers/doc/questiontarget.txt
@@ -89,7 +89,6 @@ Anonymous users cannot use newQuestion().
     >>> login(ANONYMOUS)
     >>> question = target.newQuestion(
     ...     sample_person, 'This will fail', 'Failed?')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
@@ -388,7 +387,6 @@ is only available to registered users.
 
     >>> name18 = getUtility(IPersonSet).getByName('name18')
     >>> target.addAnswerContact(name18, name18)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
@@ -419,7 +417,6 @@ languages.
     >>> len(sample_person.languages)
     0
     >>> target.addAnswerContact(sample_person, sample_person)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.answers.errors.AddAnswerContactError: An answer contact must speak a language...
@@ -441,7 +438,6 @@ Only registered users can remove an answer contact.
 
     >>> login(ANONYMOUS)
     >>> target.removeAnswerContact(name18, name18)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/answers/doc/workflow.txt b/lib/lp/answers/doc/workflow.txt
index c9d3c74..6f25e23 100644
--- a/lib/lp/answers/doc/workflow.txt
+++ b/lib/lp/answers/doc/workflow.txt
@@ -426,7 +426,6 @@ As a Launchpad administrator, so can Stub.
     >>> login(marilize.preferredemail.email)
     >>> spam_question.reject(
     ...     marilize, "We don't send free CDs any more.")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
@@ -485,7 +484,6 @@ It is not possible to change the status attribute directly.
     >>> login('foo.bar@xxxxxxxxxxxxx')
     >>> question = ubuntu.newQuestion(**new_question_args)
     >>> question.status = QuestionStatus.INVALID
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.ForbiddenAttribute: ...
@@ -544,7 +542,6 @@ permission, an Unauthorized exception is thrown.
 
     >>> login('test@xxxxxxxxxxxxx')
     >>> question.setStatus(sample_person, QuestionStatus.EXPIRED, 'Expire.')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
@@ -593,7 +590,6 @@ Users without launchpad.Moderator privileges cannot set the assignee.
 
     >>> login('no-priv@xxxxxxxxxxxxx')
     >>> question.assignee = sample_person
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: (<lp.answers.model.question.Question ...>, 'assignee', 'launchpad.Append')
@@ -767,7 +763,6 @@ method.
 
     >>> login(stub.preferredemail.email)
     >>> question.setStatus(stub, QuestionStatus.OPEN, reject_message)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.answers.errors.NotMessageOwnerError: ...
diff --git a/lib/lp/answers/stories/distribution-package-answer-contact.txt b/lib/lp/answers/stories/distribution-package-answer-contact.txt
index 2aa64a0..2d2ebd8 100644
--- a/lib/lp/answers/stories/distribution-package-answer-contact.txt
+++ b/lib/lp/answers/stories/distribution-package-answer-contact.txt
@@ -38,7 +38,6 @@ To register themselves as answer contact, the user clicks on the
 'Set answer contact' link. They need to login to access that function.
 
     >>> anon_browser.getLink('Set answer contact').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/answers/stories/faq-add.txt b/lib/lp/answers/stories/faq-add.txt
index ac6023e..ae54966 100644
--- a/lib/lp/answers/stories/faq-add.txt
+++ b/lib/lp/answers/stories/faq-add.txt
@@ -11,14 +11,12 @@ the project owner, therefore they cannot create a new FAQ.
     >>> user_browser.getLink('All FAQs').click()
 
     >>> user_browser.getLink('Create a new FAQ')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> user_browser.open(
     ...     'http://answers.launchpad.test/firefox/+createfaq')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/answers/stories/faq-browse-and-search.txt b/lib/lp/answers/stories/faq-browse-and-search.txt
index fab6403..b911c59 100644
--- a/lib/lp/answers/stories/faq-browse-and-search.txt
+++ b/lib/lp/answers/stories/faq-browse-and-search.txt
@@ -185,13 +185,11 @@ Accessing an FAQ directly
 Asking for a non-existent FAQ or an invalid ID will raise a 404 error.
 
     >>> anon_browser.open('http://answers.launchpad.test/ubuntu/+faq/171717')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
 
     >>> anon_browser.open('http://answers.launchpad.test/ubuntu/+faq/bad')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/answers/stories/faq-edit.txt b/lib/lp/answers/stories/faq-edit.txt
index 9a635d4..be6a95e 100644
--- a/lib/lp/answers/stories/faq-edit.txt
+++ b/lib/lp/answers/stories/faq-edit.txt
@@ -14,14 +14,12 @@ appear for the anonymous user nor No Privileges Person:
     FAQ #7 : Questions : Mozilla Firefox
 
     >>> anon_browser.getLink('Edit FAQ')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> user_browser.open('http://answers.launchpad.test/firefox/+faq/7')
     >>> user_browser.getLink('Edit FAQ')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -30,13 +28,11 @@ Even trying to access the link directly will fail:
 
     >>> anon_browser.open(
     ...     'http://answers.launchpad.test/firefox/+faq/7/+edit')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
     >>> user_browser.open(
     ...     'http://answers.launchpad.test/firefox/+faq/7/+edit')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/answers/stories/project-add-question.txt b/lib/lp/answers/stories/project-add-question.txt
index eb3703c..737952c 100644
--- a/lib/lp/answers/stories/project-add-question.txt
+++ b/lib/lp/answers/stories/project-add-question.txt
@@ -26,7 +26,6 @@ Project in this case.
 
     >>> anon_browser.open('http://answers.launchpad.test/mozilla')
     >>> anon_browser.getLink('Ask a question').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/answers/stories/question-add.txt b/lib/lp/answers/stories/question-add.txt
index e7debb4..b24893c 100644
--- a/lib/lp/answers/stories/question-add.txt
+++ b/lib/lp/answers/stories/question-add.txt
@@ -18,7 +18,6 @@ The user sees an involvement link to ask a question.
 Asking a new question requires logging in:
 
     >>> browser.getLink('Ask a question').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/answers/stories/question-browse-and-search.txt b/lib/lp/answers/stories/question-browse-and-search.txt
index cbbfaec..0af0cb3 100644
--- a/lib/lp/answers/stories/question-browse-and-search.txt
+++ b/lib/lp/answers/stories/question-browse-and-search.txt
@@ -44,7 +44,6 @@ For projects that don't have products, the Answers facet is disabled.
 
     >>> browser.open('http://launchpad.test/aaa')
     >>> browser.getLink('Answers')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -88,14 +87,12 @@ out.
     >>> 'Next' in browser.contents
     True
     >>> browser.getLink('Next')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
     >>> 'Last' in browser.contents
     True
     >>> browser.getLink('Last')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
@@ -111,14 +108,12 @@ greyed out:
     >>> 'Previous' in browser.contents
     True
     >>> browser.getLink('Previous')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
     >>> 'First' in browser.contents
     True
     >>> browser.getLink('First')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
@@ -386,7 +381,6 @@ They need to login to access that page:
     ...     'http://launchpad.test/ubuntu/+source/mozilla-firefox/'
     ...     '+questions')
     >>> anon_browser.getLink('My questions').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
@@ -460,7 +454,6 @@ They need to login to access that page:
 
     >>> anon_browser.open('http://launchpad.test/distros/ubuntu/+questions')
     >>> anon_browser.getLink('Need attention').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/answers/stories/question-edit.txt b/lib/lp/answers/stories/question-edit.txt
index ef36a05..8aeed0d 100644
--- a/lib/lp/answers/stories/question-edit.txt
+++ b/lib/lp/answers/stories/question-edit.txt
@@ -8,7 +8,6 @@ title and description.
 
     >>> anon_browser.open('http://launchpad.test/firefox/+question/2')
     >>> anon_browser.getLink('Edit question').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/answers/stories/question-overview.txt b/lib/lp/answers/stories/question-overview.txt
index 374dc16..54afeb6 100644
--- a/lib/lp/answers/stories/question-overview.txt
+++ b/lib/lp/answers/stories/question-overview.txt
@@ -235,13 +235,11 @@ Asking for a non-existent question or an invalid ID will still raise a
 404 though:
 
     >>> browser.open('http://answers.launchpad.test/questions/255')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
 
     >>> browser.open('http://answers.launchpad.test/questions/bad_id')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
@@ -268,14 +266,12 @@ It also works with pages below that URL:
 But again, an invalid ID still raises a 404:
 
     >>> browser.open('http://answers.launchpad.test/ubuntu/+question/255')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
 
     >>> browser.open(
     ...     'http://answers.launchpad.test/ubuntu/+question/bad_id')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/answers/stories/question-reject-and-change-status.txt b/lib/lp/answers/stories/question-reject-and-change-status.txt
index c7466fd..bdbffe2 100644
--- a/lib/lp/answers/stories/question-reject-and-change-status.txt
+++ b/lib/lp/answers/stories/question-reject-and-change-status.txt
@@ -10,7 +10,6 @@ don't have access to that feature.
 
     >>> user_browser.open('http://launchpad.test/firefox/+question/2')
     >>> user_browser.getLink('Reject question')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -20,7 +19,6 @@ error.
 
     >>> user_browser.open(
     ...     'http://launchpad.test/firefox/+question/2/+reject')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
@@ -104,7 +102,6 @@ That action isn't available to a non-privileged user:
 
     >>> browser.open('http://launchpad.test/firefox/+question/2')
     >>> browser.getLink('Change status')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/answers/stories/this-is-a-faq.txt b/lib/lp/answers/stories/this-is-a-faq.txt
index 3438e03..d382d3b 100644
--- a/lib/lp/answers/stories/this-is-a-faq.txt
+++ b/lib/lp/answers/stories/this-is-a-faq.txt
@@ -209,21 +209,18 @@ Since No Privileges Person isn't an answer contact for the project nor
 the project owner, they don't have the possibility to create a new FAQ.
 
     >>> user_browser.getLink('Create a FAQ')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> user_browser.getLink('Link to a FAQ').click()
     >>> user_browser.getLink('create a new FAQ')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> user_browser.open(
     ...     'http://answers.launchpad.test/firefox/+question/2/+createfaq')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/app/doc/batch-navigation.txt b/lib/lp/app/doc/batch-navigation.txt
index eebef5d..7087dc2 100644
--- a/lib/lp/app/doc/batch-navigation.txt
+++ b/lib/lp/app/doc/batch-navigation.txt
@@ -81,7 +81,6 @@ InvalidBatchSizeError is raised.
     ...     """))
     >>> request = build_request({"start": "0", "batch": "20"})
     >>> BatchNavigator(reindeer, request=request )
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lazr.batchnavigator.interfaces.InvalidBatchSizeError: Maximum for "batch" parameter is 5.
diff --git a/lib/lp/app/doc/displaying-numbers.txt b/lib/lp/app/doc/displaying-numbers.txt
index fcdd4e0..6da695d 100644
--- a/lib/lp/app/doc/displaying-numbers.txt
+++ b/lib/lp/app/doc/displaying-numbers.txt
@@ -59,7 +59,6 @@ Is the same as:
 Here's a set of exhaustive examples:
 
     >>> test_tales('foo/fmt:float', foo=12345.67890)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.location.interfaces.LocationError: 'fmt:float requires a single decimal argument'
diff --git a/lib/lp/app/doc/launchpadform.txt b/lib/lp/app/doc/launchpadform.txt
index a42833f..58239fb 100644
--- a/lib/lp/app/doc/launchpadform.txt
+++ b/lib/lp/app/doc/launchpadform.txt
@@ -568,7 +568,6 @@ request:
     ...           'field.actions.change': 'Change'})
     >>> view = UnsafeActionTestView(context, request)
     >>> view.initialize()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.services.webapp.interfaces.UnsafeFormGetSubmissionError: field.actions.change
diff --git a/lib/lp/app/doc/object-privacy.txt b/lib/lp/app/doc/object-privacy.txt
index 18c14e5..7f2c46e 100644
--- a/lib/lp/app/doc/object-privacy.txt
+++ b/lib/lp/app/doc/object-privacy.txt
@@ -30,7 +30,6 @@ private.
 
     >>> question = getUtility(IQuestionSet).get(1)
     >>> question.private
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ...
diff --git a/lib/lp/app/doc/tales.txt b/lib/lp/app/doc/tales.txt
index 0d56ac6..e5d2284 100644
--- a/lib/lp/app/doc/tales.txt
+++ b/lib/lp/app/doc/tales.txt
@@ -1314,7 +1314,6 @@ Everything you can do with 'something/fmt:foo', you should be able to do
 with 'None/fmt:foo'.
 
     >>> test_tales('foo/fmt:shorten', foo=None)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.location.interfaces.LocationError: 'you need to traverse a number after fmt:shorten'
@@ -1417,7 +1416,6 @@ We don't get a ValueError when we use a value that doesn't appear in the
 DBSchema the item comes from.
 
     >>> test_tales('deb/enumvalue:CHEESEFISH', deb=udeb)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.location.interfaces.LocationError: 'The enumerated type BinaryPackageFormat does not have a value CHEESEFISH.'
@@ -1439,7 +1437,6 @@ dbschema items too:
     False
 
     >>> test_tales('deb/enumvalue:CHEESEFISH', deb=wrapped_deb)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.location.interfaces.LocationError: 'The enumerated type BinaryPackageFormat does not have a value CHEESEFISH.'
diff --git a/lib/lp/app/stories/basics/marketing.txt b/lib/lp/app/stories/basics/marketing.txt
index eeb08b6..4ccc41a 100644
--- a/lib/lp/app/stories/basics/marketing.txt
+++ b/lib/lp/app/stories/basics/marketing.txt
@@ -45,7 +45,6 @@ But the source directory isn't available:
 
     >>> browser.open(
     ...     'http://launchpad.test/+tour/source/code-hosting_SVG.svg')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/app/stories/basics/max-batch-size.txt b/lib/lp/app/stories/basics/max-batch-size.txt
index ce3d44b..71c9635 100644
--- a/lib/lp/app/stories/basics/max-batch-size.txt
+++ b/lib/lp/app/stories/basics/max-batch-size.txt
@@ -8,7 +8,6 @@ large and what is the current maximum.
 
     >>> anon_browser.handleErrors = True
     >>> anon_browser.open('http://launchpad.test/projects/+all?start=0&batch=1000')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     urllib.error.HTTPError: HTTP Error 400: Bad Request
diff --git a/lib/lp/app/stories/basics/xx-developerexceptions.txt b/lib/lp/app/stories/basics/xx-developerexceptions.txt
index b8373f8..42a794d 100644
--- a/lib/lp/app/stories/basics/xx-developerexceptions.txt
+++ b/lib/lp/app/stories/basics/xx-developerexceptions.txt
@@ -106,7 +106,6 @@ want to see tracebacks instead of error pages.
     >>> print(http(r"""
     ... GET /whatever HTTP/1.1
     ... """, handle_errors=False))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/app/stories/basics/xx-launchpad-statistics.txt b/lib/lp/app/stories/basics/xx-launchpad-statistics.txt
index f7185c7..c81ca7a 100644
--- a/lib/lp/app/stories/basics/xx-launchpad-statistics.txt
+++ b/lib/lp/app/stories/basics/xx-launchpad-statistics.txt
@@ -3,7 +3,6 @@ We also have the special Launchpad Statistics summary page. This is only
 acessible to launchpad Admins:
 
     >>> user_browser.open('http://launchpad.test/+statistics')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/app/stories/basics/xx-offsite-form-post.txt b/lib/lp/app/stories/basics/xx-offsite-form-post.txt
index f00a78e..12d4127 100644
--- a/lib/lp/app/stories/basics/xx-offsite-form-post.txt
+++ b/lib/lp/app/stories/basics/xx-offsite-form-post.txt
@@ -44,7 +44,6 @@ If we try to create a new team with with the referrer set to
     >>> browser.getControl('Name', index=0).value = 'team1'
     >>> browser.getControl('Display Name').value = 'Team 1'
     >>> browser.getControl('Create').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.services.webapp.interfaces.OffsiteFormPostError: http://evil.people.com/
@@ -57,7 +56,6 @@ Similarly, posting with a garbage referer fails:
     >>> browser.getControl('Name', index=0).value = 'team2'
     >>> browser.getControl('Display Name').value = 'Team 2'
     >>> browser.getControl('Create').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.services.webapp.interfaces.OffsiteFormPostError: not a url
@@ -70,7 +68,6 @@ It also fails if there is no referrer.
     >>> browser.getControl('Name', index=0).value = 'team3'
     >>> browser.getControl('Display Name').value = 'Team 3'
     >>> browser.getControl('Create').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.services.webapp.interfaces.NoReferrerError: No value for REFERER header
@@ -84,7 +81,6 @@ present a hopefully helpful error message.
     >>> browser.getControl('Name', index=0).value = 'team3'
     >>> browser.getControl('Display Name').value = 'Team 3'
     >>> browser.getControl('Create').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     urllib.error.HTTPError: ...
@@ -117,7 +113,6 @@ exception for +access-token, it would result in an
 OffsiteFormPostError.
 
     >>> browser.post('http://launchpad.test/+access-token', 'x=1')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     urllib.error.HTTPError: HTTP Error 401: Unauthorized
@@ -154,14 +149,12 @@ a referrerless POST request to the browser-accessible API.
 
     >>> browser.post(
     ...     'http://launchpad.test/api/devel/people', 'ws.op=foo&x=1')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.webapp.interfaces.OffsiteFormPostError: http://evil.people.com/
 
     >>> no_referrer_browser.post(
     ...     'http://launchpad.test/api/devel/people', 'ws.op=foo&x=1')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.webapp.interfaces.NoReferrerError: No value for REFERER header
@@ -172,7 +165,6 @@ though it were signed with OAuth.
     >>> browser.post(
     ...     'http://launchpad.test/',
     ...     'oauth_consumer_key=foo&oauth_token=bar')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.webapp.interfaces.OffsiteFormPostError: http://evil.people.com/
@@ -180,7 +172,6 @@ though it were signed with OAuth.
     >>> no_referrer_browser.post(
     ...     'http://launchpad.test/',
     ...     'oauth_consumer_key=foo&oauth_token=bar')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.webapp.interfaces.NoReferrerError: No value for REFERER header
@@ -200,7 +191,6 @@ But the browser-accessible API ignores OAuth credentials altogether.
 
     >>> browser.post(
     ...     'http://launchpad.test/api/devel/projects', sig)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.webapp.interfaces.OffsiteFormPostError: http://evil.people.com/
@@ -209,7 +199,6 @@ If you go through the 'api' vhost, the signed request will be
 processed despite the bogus referrer, but...
 
     >>> browser.post('http://api.launchpad.test/devel/projects', sig)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     storm.exceptions.NoneError: None isn't acceptable as a value for Product...
diff --git a/lib/lp/app/stories/basics/xx-opstats.txt b/lib/lp/app/stories/basics/xx-opstats.txt
index 32002b3..de80e59 100644
--- a/lib/lp/app/stories/basics/xx-opstats.txt
+++ b/lib/lp/app/stories/basics/xx-opstats.txt
@@ -352,7 +352,6 @@ But our database connections are broken.
     >>> from lp.services.database.interfaces import IStore
     >>> from lp.registry.model.person import Person
     >>> IStore(Person).find(Person, name='janitor')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     storm.exceptions.DisconnectionError: FATAL:  database "nonexistant" does not exist
diff --git a/lib/lp/app/stories/folder.txt b/lib/lp/app/stories/folder.txt
index 8124932..8bde596 100644
--- a/lib/lp/app/stories/folder.txt
+++ b/lib/lp/app/stories/folder.txt
@@ -67,7 +67,7 @@ Requesting a directory raises a NotFound.
 
     >>> view = MyFolder(object(), FakeRequest(version="devel"))
     >>> view = view.publishTraverse(view.request, 'a_dir')
-    >>> view()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> view()
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
@@ -78,7 +78,7 @@ this)
     >>> view = MyFolder(object(), FakeRequest(version="devel"))
     >>> view = view.publishTraverse(view.request, 'a_dir')
     >>> view = view.publishTraverse(view.request, 'other.txt')
-    >>> view()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> view()
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
@@ -86,7 +86,7 @@ this)
 Not requesting any file, also raises NotFound.
 
     >>> view = MyFolder(object(), FakeRequest(version="devel"))
-    >>> view()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> view()
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
@@ -95,7 +95,7 @@ As requesting a non-existent file.
 
     >>> view = MyFolder(object(), FakeRequest(version="devel"))
     >>> view = view.publishTraverse(view.request, 'image2')
-    >>> view()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> view()
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
@@ -176,7 +176,7 @@ But traversing to the subdirectory itself will raise a NotFound.
 
     >>> view = MyTree(object(), FakeRequest(version="devel"))
     >>> view = view.publishTraverse(view.request, 'public')
-    >>> view()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> view()
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
@@ -186,7 +186,7 @@ Trying to request a non-existent file, will also raise a NotFound.
     >>> view = MyTree(object(), FakeRequest(version="devel"))
     >>> view = view.publishTraverse(view.request, 'public')
     >>> view = view.publishTraverse(view.request, 'nosuchfile.txt')
-    >>> view()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> view()
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
@@ -199,7 +199,7 @@ NotFound.
     >>> view = view.publishTraverse(view.request, 'subdir1')
     >>> view = view.publishTraverse(view.request, 'test1.txt')
     >>> view = view.publishTraverse(view.request, 'nosuchpath')
-    >>> view()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> view()
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/app/stories/form/xx-form-layout.txt b/lib/lp/app/stories/form/xx-form-layout.txt
index c9b09ea..478c97e 100644
--- a/lib/lp/app/stories/form/xx-form-layout.txt
+++ b/lib/lp/app/stories/form/xx-form-layout.txt
@@ -98,7 +98,6 @@ display forms.
 
     >>> cprov_browser.open(
     ...     'http://launchpad.test/~cprov/+editsshkeys/++form++')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
@@ -107,7 +106,6 @@ Nor will it allow unauthorized access to data that it should not present.
 
     >>> browser.open(
     ...     'http://launchpad.test/~cprov/+archive/ppa/+edit/++form++')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/app/stories/launchpad-root/xx-featuredprojects.txt b/lib/lp/app/stories/launchpad-root/xx-featuredprojects.txt
index 060a023..8e54d4c 100644
--- a/lib/lp/app/stories/launchpad-root/xx-featuredprojects.txt
+++ b/lib/lp/app/stories/launchpad-root/xx-featuredprojects.txt
@@ -52,7 +52,6 @@ Adding a featured project
 Anonymous users cannot see the link to administer featured projects:
 
     >>> anon_browser.getLink(MANAGE_LINK)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -61,7 +60,6 @@ A user without privileges cannot see the administration link, either:
 
     >>> user_browser.open('http://launchpad.test/')
     >>> user_browser.getLink(MANAGE_LINK)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -76,7 +74,6 @@ But Foo Bar, who is an administrator, can see the management link:
 No Privilege persons is denied access to this page:
 
     >>> user_browser.open('http://launchpad.test/+featuredprojects')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/app/validators/email.py b/lib/lp/app/validators/email.py
index 04599f8..8f57276 100644
--- a/lib/lp/app/validators/email.py
+++ b/lib/lp/app/validators/email.py
@@ -77,11 +77,10 @@ def email_validator(emailaddr):
     >>> email_validator('bugs@xxxxxxxxxxx')
     True
     >>> email_validator('not-valid')
-    ... # noqa
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
-    lp.app.validators.LaunchpadValidationError: Invalid email &#x27;not-valid&#x27;.
+    lp.app.validators.LaunchpadValidationError: Invalid email
+    &#x27;not-valid&#x27;.
     """
     if not valid_email(emailaddr):
         raise LaunchpadValidationError(_(
diff --git a/lib/lp/app/validators/tests/validation.txt b/lib/lp/app/validators/tests/validation.txt
index a8d4a8e..b66c031 100644
--- a/lib/lp/app/validators/tests/validation.txt
+++ b/lib/lp/app/validators/tests/validation.txt
@@ -38,13 +38,11 @@ fail for that specific series.
 
     >>> nomination = bug.addNomination(no_priv, firefox.series[0])
     >>> can_be_nominated_for_series(firefox.series)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.validators.LaunchpadValidationError: ...
 
     >>> can_be_nominated_for_series([firefox.series[0]])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.validators.LaunchpadValidationError: ...
@@ -62,7 +60,6 @@ fail:
     ...     'foo.bar@xxxxxxxxxxxxx')
     >>> nomination.approve(foo_bar)
     >>> can_be_nominated_for_series([firefox.series[0]])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.validators.LaunchpadValidationError: ...
@@ -73,7 +70,6 @@ nominated.
     >>> trunk_nomination = bug.addNomination(
     ...     no_priv, firefox.series[1])
     >>> can_be_nominated_for_series(firefox.series)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.validators.LaunchpadValidationError: This bug has already been nominated for these series: 1.0, Trunk
@@ -115,7 +111,6 @@ Or a name that is not already in use.
 But you can't use Mark's name, of course. ;)
 
     >>> field.validate(u'mark')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.validators.LaunchpadValidationError: ...mark is already in use by another person or team...
diff --git a/lib/lp/app/validators/url.py b/lib/lp/app/validators/url.py
index 8df0a18..8dcc05b 100644
--- a/lib/lp/app/validators/url.py
+++ b/lib/lp/app/validators/url.py
@@ -152,7 +152,6 @@ def valid_webref(web_ref):
     >>> valid_webref('sftp://example.com//absolute/path/maybe')
     True
     >>> valid_webref('other://example.com/moo')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.validators.LaunchpadValidationError: ...
diff --git a/lib/lp/app/widgets/date.py b/lib/lp/app/widgets/date.py
index c24da8f..4d58907 100644
--- a/lib/lp/app/widgets/date.py
+++ b/lib/lp/app/widgets/date.py
@@ -85,12 +85,11 @@ class DateTimeWidget(TextWidget):
       >>> widget.from_date = datetime(2006, 5, 23,
       ...                             tzinfo=pytz.timezone('UTC'))
       >>> print(widget.getInputValue())
-      ... # noqa
       ... # doctest: +NORMALIZE_WHITESPACE,+ELLIPSIS
-      ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
       Traceback (most recent call last):
       ...
-      zope.formlib.interfaces.WidgetInputError: (...Please pick a date after 2006-05-22 17:00:00...)
+      zope.formlib.interfaces.WidgetInputError:
+      (...Please pick a date after 2006-05-22 17:00:00...)
 
     If the date provided is greater than from_date then the widget works as
     expected.
@@ -104,12 +103,11 @@ class DateTimeWidget(TextWidget):
       >>> widget.to_date = datetime(2008, 1, 26,
       ...                           tzinfo=pytz.timezone('UTC'))
       >>> print(widget.getInputValue())
-      ... # noqa
       ... # doctest: +NORMALIZE_WHITESPACE,+ELLIPSIS
-      ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
       Traceback (most recent call last):
       ...
-      zope.formlib.interfaces.WidgetInputError: (...Please pick a date before 2008-01-25 16:00:00...)
+      zope.formlib.interfaces.WidgetInputError:
+      (...Please pick a date before 2008-01-25 16:00:00...)
 
     A datetime picker can be disabled initially:
 
@@ -392,7 +390,6 @@ class DateTimeWidget(TextWidget):
 
           >>> print(widget._parseInput('not a date'))
           ... # doctest: +NORMALIZE_WHITESPACE,+ELLIPSIS
-          ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
           Traceback (most recent call last):
             ...
           zope.formlib.interfaces.ConversionError: ('Invalid date value', ...)
@@ -555,7 +552,6 @@ class DateWidget(DateTimeWidget):
 
           >>> print(widget._toFieldValue('not a date'))
           ... # doctest: +NORMALIZE_WHITESPACE,+ELLIPSIS
-          ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
           Traceback (most recent call last):
             ...
           zope.formlib.interfaces.ConversionError: ('Invalid date value', ...)
diff --git a/lib/lp/app/widgets/doc/announcement-date-widget.txt b/lib/lp/app/widgets/doc/announcement-date-widget.txt
index b33fcaa..a50a431 100644
--- a/lib/lp/app/widgets/doc/announcement-date-widget.txt
+++ b/lib/lp/app/widgets/doc/announcement-date-widget.txt
@@ -57,7 +57,6 @@ If you choose to publish immediately, the date field must be empty.
     >>> action_widget.request.form[action_widget.name] = 'immediately'
     >>> date_widget.request.form[date_widget.name] = '2005-07-23'
     >>> print(widget.getInputValue())
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ('field.foo', ...'Foo', LaunchpadValidationError(...'Please do not provide a date if you want to publish immediately.'))
@@ -68,7 +67,6 @@ must be filled.
     >>> action_widget.request.form[action_widget.name] = 'specific'
     >>> date_widget.request.form[date_widget.name] = ''
     >>> print(widget.getInputValue())
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ('field.foo', ...'Foo', LaunchpadValidationError(...'Please provide a publication date.'))
diff --git a/lib/lp/app/widgets/doc/image-widget.txt b/lib/lp/app/widgets/doc/image-widget.txt
index 0d68f3b..35bc4ab 100644
--- a/lib/lp/app/widgets/doc/image-widget.txt
+++ b/lib/lp/app/widgets/doc/image-widget.txt
@@ -266,7 +266,7 @@ dimensions smaller than person_mugshot.dimensions, it must be rejected.
     >>> form = {'field.mugshot.action': 'change', 'field.mugshot.image': logo}
     >>> widget = ImageChangeWidget(
     ...     person_mugshot, LaunchpadTestRequest(form=form), edit_style)
-    >>> widget.getInputValue()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> widget.getInputValue()
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ('field.mugshot', ...'Mugshot', LaunchpadValidationError(...'\nThis image is not exactly 192x192\npixels in size.'))
@@ -310,7 +310,7 @@ image, we'll get a validation error.
     >>> _ = mugshot.seek(0)
     >>> widget = ImageChangeWidget(
     ...     person_mugshot, LaunchpadTestRequest(form=form), edit_style)
-    >>> widget.getInputValue()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> widget.getInputValue()
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ('field.mugshot', ...'Mugshot', LaunchpadValidationError(...'\nThis image exceeds the maximum allowed size in bytes.'))
@@ -323,7 +323,7 @@ the maximum we allow.
     >>> _ = mugshot.seek(0)
     >>> widget = ImageChangeWidget(
     ...     person_mugshot, LaunchpadTestRequest(form=form), edit_style)
-    >>> widget.getInputValue()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> widget.getInputValue()
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ('field.mugshot', ...'Mugshot', LaunchpadValidationError(...'\nThis image is not exactly 191x193\npixels in size.'))
@@ -332,7 +332,7 @@ the maximum we allow.
     >>> _ = mugshot.seek(0)
     >>> widget = ImageChangeWidget(
     ...     person_mugshot, LaunchpadTestRequest(form=form), edit_style)
-    >>> widget.getInputValue()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> widget.getInputValue()
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ('field.mugshot', ...'Mugshot', LaunchpadValidationError(...'\nThis image is not exactly 193x191\npixels in size.'))
@@ -343,7 +343,7 @@ a file to be uploaded.
     >>> form = {'field.mugshot.action': 'change', 'field.mugshot.image': ''}
     >>> widget = ImageChangeWidget(
     ...     person_mugshot, LaunchpadTestRequest(form=form), edit_style)
-    >>> widget.getInputValue()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> widget.getInputValue()
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ('field.mugshot', ...'Mugshot', LaunchpadValidationError(...'Please specify the image you want to use.'))
@@ -365,7 +365,7 @@ by setting the exact_dimensions attribute of the field to False:
     ...         'field.mugshot.image': mugshot}
     >>> widget = ImageChangeWidget(
     ...     person_mugshot, LaunchpadTestRequest(form=form), edit_style)
-    >>> widget.getInputValue()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> widget.getInputValue()
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ('field.mugshot', ...'Mugshot', LaunchpadValidationError(...'\nThis image is larger than 64x64\npixels in size.'))
diff --git a/lib/lp/app/widgets/doc/project-scope-widget.txt b/lib/lp/app/widgets/doc/project-scope-widget.txt
index e0bf442..1f11593 100644
--- a/lib/lp/app/widgets/doc/project-scope-widget.txt
+++ b/lib/lp/app/widgets/doc/project-scope-widget.txt
@@ -52,7 +52,7 @@ If the widget is required, getInputValue() raises UnexpectedFormData if
 there is no input.
 
     >>> widget.required = True
-    >>> widget.getInputValue()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> widget.getInputValue()
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: No valid option was selected.
@@ -120,7 +120,6 @@ raised:
     >>> widget.hasInput()
     True
     >>> selected_scope = widget.getInputValue()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ('field.scope', ...'', LaunchpadValidationError(...'There is no project named &#x27;invalid&#x27; registered in Launchpad'))
@@ -139,7 +138,6 @@ If no project name is given at all, a widget error is also raised:
     >>> widget.hasInput()
     True
     >>> selected_scope = widget.getInputValue()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ('field.scope', ...'', LaunchpadValidationError(...'Please enter a project name'))
@@ -154,7 +152,6 @@ If no project name is given at all, a widget error is also raised:
     >>> widget.hasInput()
     True
     >>> selected_scope = widget.getInputValue()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ('field.scope', ...'', LaunchpadValidationError(...'Please enter a project name'))
diff --git a/lib/lp/app/widgets/doc/stripped-text-widget.txt b/lib/lp/app/widgets/doc/stripped-text-widget.txt
index 7648db0..7c393da 100644
--- a/lib/lp/app/widgets/doc/stripped-text-widget.txt
+++ b/lib/lp/app/widgets/doc/stripped-text-widget.txt
@@ -60,7 +60,7 @@ provided.
     ...     __name__=six.ensure_str('field'), title=u'Title', required=True)
     >>> request = LaunchpadTestRequest(form={'field.field':'    \n    '})
     >>> widget = StrippedTextWidget(required_field, request)
-    >>> widget.getInputValue()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> widget.getInputValue()
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ('field', ...'Title', RequiredMissing('field'))
diff --git a/lib/lp/app/widgets/doc/zope3-widgets-use-form-ng.txt b/lib/lp/app/widgets/doc/zope3-widgets-use-form-ng.txt
index 5888dee..dea969a 100644
--- a/lib/lp/app/widgets/doc/zope3-widgets-use-form-ng.txt
+++ b/lib/lp/app/widgets/doc/zope3-widgets-use-form-ng.txt
@@ -41,7 +41,6 @@ contains more than one argument.
     >>> Zope3WidgetsUseIBrowserFormNGMonkeyPatch.install()
 
     >>> int_widget.getInputValue()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.errors.UnexpectedFormData: ...
@@ -51,7 +50,6 @@ contains more than one argument.
     ...     form={'field.text': ['two', 'strings']})
     >>> text_widget = TextWidget(text_field, request)
     >>> text_widget.getInputValue()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.errors.UnexpectedFormData: ...
@@ -63,7 +61,6 @@ with the Launchpad widgets extending it:
 
     >>> stripped_text_widget = StrippedTextWidget(text_field, request)
     >>> stripped_text_widget.getInputValue()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.errors.UnexpectedFormData: ...
diff --git a/lib/lp/archivepublisher/tests/archive-signing.txt b/lib/lp/archivepublisher/tests/archive-signing.txt
index d2efc4f..266b42b 100644
--- a/lib/lp/archivepublisher/tests/archive-signing.txt
+++ b/lib/lp/archivepublisher/tests/archive-signing.txt
@@ -457,7 +457,6 @@ have a 'signing_key' set,  it raises an error.
     >>> del get_property_cache(cprov.archive).signing_key
 
     >>> archive_signing_key.signRepository(test_suite)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archivepublisher.interfaces.archivegpgsigningkey.CannotSignArchive: No signing key available for PPA for Celso Providelo
diff --git a/lib/lp/archiveuploader/tests/nascentupload-announcements.txt b/lib/lp/archiveuploader/tests/nascentupload-announcements.txt
index 9f7c2f9..fc12cfd 100644
--- a/lib/lp/archiveuploader/tests/nascentupload-announcements.txt
+++ b/lib/lp/archiveuploader/tests/nascentupload-announcements.txt
@@ -754,7 +754,7 @@ And then try to upload using the changes file with the malformed name.
 
     >>> bar_src = NascentUpload.from_changesfile_path(
     ...     copyp, sync_policy, DevNullLogger())
-    >>> bar_src.process()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> bar_src.process()
     Traceback (most recent call last):
     ...
     lp.archiveuploader.nascentupload.EarlyReturnUploadError: An error occurred that prevented further processing.
diff --git a/lib/lp/archiveuploader/tests/nascentupload-epoch-handling.txt b/lib/lp/archiveuploader/tests/nascentupload-epoch-handling.txt
index 45190aa..cb4c2ef 100644
--- a/lib/lp/archiveuploader/tests/nascentupload-epoch-handling.txt
+++ b/lib/lp/archiveuploader/tests/nascentupload-epoch-handling.txt
@@ -151,7 +151,6 @@ Published the 'non-epoched' bar source version as the base package:
 When publishing the 'epoched' bar source the collision is detected:
 
     >>> bar_src_queue_epoch.realiseUpload()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.queue.QueueInconsistentStateError: bar_1.0-1.diff.gz is already published in archive for hoary
@@ -170,7 +169,6 @@ containing a orig file with diferent contents than the one already
 published in 'non-epoched' version:
 
     >>> bar_src_queue_epoch2.realiseUpload()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.queue.QueueInconsistentStateError: bar_1.0.orig.tar.gz is already published in archive for hoary with a different SHA1 hash (e918d6f5ec2184ae1d795a130da36c9a82c4beaf != 73a04163fee97fd2257ab266bd48f1d3d528e012)
diff --git a/lib/lp/archiveuploader/tests/nascentupload.txt b/lib/lp/archiveuploader/tests/nascentupload.txt
index 20fb5f1..30272a4 100644
--- a/lib/lp/archiveuploader/tests/nascentupload.txt
+++ b/lib/lp/archiveuploader/tests/nascentupload.txt
@@ -54,7 +54,7 @@ on that.
 
     >>> nonexistent = NascentUpload.from_changesfile_path(
     ...     datadir("DOES-NOT-EXIST"), buildd_policy, FakeLogger())
-    >>> nonexistent.process()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> nonexistent.process()
     Traceback (most recent call last):
     ...
     lp.archiveuploader.nascentupload.EarlyReturnUploadError: An error occurred that prevented further processing.
diff --git a/lib/lp/archiveuploader/tests/nascentuploadfile.txt b/lib/lp/archiveuploader/tests/nascentuploadfile.txt
index 60ea018..0747315 100644
--- a/lib/lp/archiveuploader/tests/nascentuploadfile.txt
+++ b/lib/lp/archiveuploader/tests/nascentuploadfile.txt
@@ -44,7 +44,6 @@ Construct the base object with just enough data to do the check:
 The filename tries to use an epoch in an invalid way:
 
     >>> upload_file.checkNameIsTaintFree()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.utils.UploadError: Invalid character(s) in filename: 'package-1.1.2-3:0ubuntu4'.
@@ -263,7 +262,6 @@ Launchpad:
 If the address is unparsable, we get an error.
 
     >>> sig_file.parseAddress("Cannot Parse Me <FOOO>")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.utils.UploadError: Cannot Parse Me <FOOO>: no @ found in email address part.
diff --git a/lib/lp/archiveuploader/tests/upload-path-parsing.txt b/lib/lp/archiveuploader/tests/upload-path-parsing.txt
index c4c998d..41a834e 100644
--- a/lib/lp/archiveuploader/tests/upload-path-parsing.txt
+++ b/lib/lp/archiveuploader/tests/upload-path-parsing.txt
@@ -48,7 +48,6 @@ If such distribution doesn't exist, parse_upload_path() raises
 `UploadPathError`.
 
     >>> check_upload('does-not-exist')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.UploadPathError: Could not find distribution 'does-not-exist'.
@@ -70,7 +69,6 @@ Again, if the given suite name can not be found an `UploadPathError`
 is raised.
 
     >>> check_upload('debian/imaginary')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.UploadPathError: Could not find suite 'imaginary'.
@@ -104,13 +102,11 @@ up as a Person in Launchpad.
     Suite: None
 
     >>> check_upload('~does-not-exist/ubuntu/ppa')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.PPAUploadPathError: Could not find person or team named 'does-not-exist'.
 
     >>> check_upload('~cprov/notbuntu/ppa')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.PPAUploadPathError: Could not find distribution 'notbuntu'.
@@ -148,7 +144,6 @@ valid. It's also supported for uploads to the deprecated paths.
     Suite: warty-backports
 
     >>> check_upload('~cprov/ppa/ubuntu/boing')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.PPAUploadPathError: Could not find suite 'boing'.
@@ -164,13 +159,11 @@ an error.
     >>> transaction.commit()
 
     >>> check_upload('~cprov/ubuntu/ppa')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.PPAUploadPathError: PPA for Celso Providelo is disabled.
 
     >>> check_upload('~cprov/ppa/ubuntu')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.PPAUploadPathError: PPA for Celso Providelo is disabled.
@@ -178,13 +171,11 @@ an error.
 Uploading to named PPA that does not exist fails.
 
     >>> check_upload('~cprov/ubuntu/beta')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.PPAUploadPathError: Could not find a PPA owned by 'cprov' for 'ubuntu' named 'beta'.
 
     >>> check_upload('~cprov/beta/ubuntu')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.PPAUploadPathError: Could not find a PPA owned by 'cprov' for 'ubuntu' named 'beta'.
@@ -216,7 +207,6 @@ identifies and warns users accordingly.
 An extra path part that cannot be processed for distribution uploads.
 
     >>> check_upload('ubuntu/warty/ding-dong')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.UploadPathError: Path format mismatch.
@@ -225,7 +215,6 @@ A distribution specific uploads starting with '~' as if it was a
 person name. Note that users can't be named like distribution anyways.
 
     >>> check_upload('~ubuntu')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.UploadPathError: Path format mismatch.
@@ -233,7 +222,6 @@ person name. Note that users can't be named like distribution anyways.
 An extra path part that cannot be processed for PPA uploads.
 
     >>> check_upload('~cprov/ubuntu/ppa/warty/ding-dong')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.UploadPathError: Path format mismatch.
@@ -241,7 +229,6 @@ An extra path part that cannot be processed for PPA uploads.
 A PPA upload missing '~':
 
     >>> check_upload('cprov/ubuntu/ppa')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.UploadPathError: Path format mismatch.
@@ -249,7 +236,6 @@ A PPA upload missing '~':
 A old-style PPA upload missing '~':
 
     >>> check_upload('cprov/ubuntu')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.UploadPathError: Could not find distribution 'cprov'.
@@ -257,7 +243,6 @@ A old-style PPA upload missing '~':
 An old-style named PPA upload missing '~'.
 
     >>> check_upload('cprov/ppa/ubuntu')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.UploadPathError: Path format mismatch.
@@ -301,7 +286,6 @@ In the case where an archive cannot be found an 'UploadPathError' exception
 is raised.
 
     >>> check_upload('1234567890/ubuntu')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.archiveuploader.uploadprocessor.UploadPathError: Could not find archive with id=1234567890.
diff --git a/lib/lp/blueprints/doc/specgraph.txt b/lib/lp/blueprints/doc/specgraph.txt
index ad3114e..4e2f985 100644
--- a/lib/lp/blueprints/doc/specgraph.txt
+++ b/lib/lp/blueprints/doc/specgraph.txt
@@ -306,7 +306,6 @@ to the command is bad:
     ...     (svg_support, request), name="+deptreeimgtag")
     >>> graph_view.initialize()
     >>> graph_view.renderGraphvizGraph('cmapx')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     lp.blueprints.browser.specification.ProblemRenderingGraph: (... syntax error in line 1 near 'bad'...)
diff --git a/lib/lp/blueprints/stories/blueprints/xx-creation.txt b/lib/lp/blueprints/stories/blueprints/xx-creation.txt
index 265dbff..c95ab67 100644
--- a/lib/lp/blueprints/stories/blueprints/xx-creation.txt
+++ b/lib/lp/blueprints/stories/blueprints/xx-creation.txt
@@ -723,7 +723,6 @@ individual user's blueprint listing page:
 
     >>> user_browser.open('http://blueprints.launchpad.test/~mark')
     >>> print(user_browser.getLink('Register a blueprint'))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
         ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -733,7 +732,6 @@ listing page:
 
     >>> user_browser.open('http://blueprints.launchpad.test/~admins')
     >>> print(user_browser.getLink('Register a blueprint'))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
         ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/blueprints/stories/blueprints/xx-dependencies.txt b/lib/lp/blueprints/stories/blueprints/xx-dependencies.txt
index 39b6a01..0164163 100644
--- a/lib/lp/blueprints/stories/blueprints/xx-dependencies.txt
+++ b/lib/lp/blueprints/stories/blueprints/xx-dependencies.txt
@@ -41,14 +41,12 @@ users with launchpad.Edit permission for the blueprint.
     >>> user_browser.open(
     ...     'http://blueprints.launchpad.test/firefox/+spec/canvas')
     >>> user_browser.getLink('Add dependency')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.open(
     ...     'http://blueprints.launchpad.test/firefox/+spec/canvas/'
     ...     '+linkdependency')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -114,14 +112,12 @@ users with launchpad.Edit permission for the blueprint.
     >>> user_browser.open(
     ...     'http://blueprints.launchpad.test/firefox/+spec/canvas')
     >>> user_browser.getLink('Remove dependency')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.open(
     ...     'http://blueprints.launchpad.test/firefox/+spec/canvas/'
     ...     '+removedependency')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/blueprints/stories/blueprints/xx-editing.txt b/lib/lp/blueprints/stories/blueprints/xx-editing.txt
index cf0a920..8c9009b 100644
--- a/lib/lp/blueprints/stories/blueprints/xx-editing.txt
+++ b/lib/lp/blueprints/stories/blueprints/xx-editing.txt
@@ -116,7 +116,6 @@ Any logged in user can edit a specification whiteboard.
 Regular users can't access the change status page.
 
     >>> user_browser.getLink(url='+status')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -124,7 +123,6 @@ Regular users can't access the change status page.
     >>> user_browser.open(
     ...     'http://blueprints.launchpad.test/kubuntu/'
     ...     '+spec/krunch-desktop-plan/+status')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -135,7 +133,6 @@ Nor can they change a blueprint's priority.
     ...     'http://blueprints.launchpad.test/kubuntu/'
     ...     '+spec/krunch-desktop-plan')
     >>> user_browser.getLink(url='+priority')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/blueprints/stories/sprints/sprint-settopics.txt b/lib/lp/blueprints/stories/sprints/sprint-settopics.txt
index d0185b9..a0a0775 100644
--- a/lib/lp/blueprints/stories/sprints/sprint-settopics.txt
+++ b/lib/lp/blueprints/stories/sprints/sprint-settopics.txt
@@ -23,21 +23,18 @@ Regular users can't approve items to be discussed in a sprint.
 
     >>> user_browser.open('http://launchpad.test/sprints/uds-guacamole')
     >>> user_browser.getLink('proposed')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> user_browser.getLink('Blueprints').click()
     >>> user_browser.getLink('Set agenda').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> user_browser.open(
     ...     'http://launchpad.test/sprints/uds-guacamole/+settopics')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/blueprints/stories/sprints/xx-sprints.txt b/lib/lp/blueprints/stories/sprints/xx-sprints.txt
index 0068d91..ea2e537 100644
--- a/lib/lp/blueprints/stories/sprints/xx-sprints.txt
+++ b/lib/lp/blueprints/stories/sprints/xx-sprints.txt
@@ -174,7 +174,6 @@ available to those who have permissions to edit that sprint.
     Ubuntu Below Zero : Meetings
 
     >>> anon_browser.getLink('Change details')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -498,13 +497,11 @@ Unregistered and anonymous users cannot access the CSV report.
 
     >>> user_browser.open('http://launchpad.test/sprints/ubz')
     >>> user_browser.getLink('Export attendees to CSV').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> anon_browser.open('http://launchpad.test/sprints/ubz/+attendees-csv')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/blueprints/stories/standalone/subscribing.txt b/lib/lp/blueprints/stories/standalone/subscribing.txt
index f3feaef..beab847 100644
--- a/lib/lp/blueprints/stories/standalone/subscribing.txt
+++ b/lib/lp/blueprints/stories/standalone/subscribing.txt
@@ -18,7 +18,6 @@ First, let's make sure we can see the link called "Subscribe..."
 If I try to go to the subscription page I will be told to login.
 
     >>> subscribe_link.click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...AnyP...
diff --git a/lib/lp/blueprints/stories/standalone/xx-branch-links.txt b/lib/lp/blueprints/stories/standalone/xx-branch-links.txt
index f95f051..9af766c 100644
--- a/lib/lp/blueprints/stories/standalone/xx-branch-links.txt
+++ b/lib/lp/blueprints/stories/standalone/xx-branch-links.txt
@@ -19,7 +19,6 @@ If the user is not logged in, they will be asked to log in.
     >>> anon_browser.open(
     ...     'http://code.launchpad.test/~name12/firefox/main')
     >>> anon_browser.getLink('Link to a blueprint').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (...launchpad.AnyPerson')
diff --git a/lib/lp/blueprints/stories/standalone/xx-views.txt b/lib/lp/blueprints/stories/standalone/xx-views.txt
index 570fa1d..05bec72 100644
--- a/lib/lp/blueprints/stories/standalone/xx-views.txt
+++ b/lib/lp/blueprints/stories/standalone/xx-views.txt
@@ -223,7 +223,6 @@ second blueprint is no longer visible:
     >>> browser.getLink('blueprint-1')
     <Link...
     >>> browser.getLink('blueprint-2')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
         ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/bugs/doc/bug-change.txt b/lib/lp/bugs/doc/bug-change.txt
index f51c352..3e6acb7 100644
--- a/lib/lp/bugs/doc/bug-change.txt
+++ b/lib/lp/bugs/doc/bug-change.txt
@@ -208,7 +208,6 @@ If get_bug_change_class() is asked for a BugChange for an object or
 field that it doesn't know about, it will raise a NoBugChangeFoundError.
 
     >>> get_bug_change_class(object(), 'fooix')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.adapters.bugchange.NoBugChangeFoundError: Unable to find a suitable BugChange for field 'fooix' on object <object object at ...>
diff --git a/lib/lp/bugs/doc/bug-reported-acknowledgement.txt b/lib/lp/bugs/doc/bug-reported-acknowledgement.txt
index 393b23b..cdb4ebd 100644
--- a/lib/lp/bugs/doc/bug-reported-acknowledgement.txt
+++ b/lib/lp/bugs/doc/bug-reported-acknowledgement.txt
@@ -54,19 +54,16 @@ read-only property, and the security proxies also only allow read
 access.
 
     >>> distro_series.bug_reported_acknowledgement = 'Foobar'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ...
 
     >>> source_package.bug_reported_acknowledgement = 'Foobar'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ...
 
     >>> product_series.bug_reported_acknowledgement = 'Foobar'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ...
@@ -88,25 +85,21 @@ message.
     ...     print(context.bug_reported_acknowledgement)
 
     >>> check_access("no-priv@xxxxxxxxxxxxx", distribution)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
 
     >>> check_access("no-priv@xxxxxxxxxxxxx", distribution_source_package)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
 
     >>> check_access("no-priv@xxxxxxxxxxxxx", project)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
 
     >>> check_access("no-priv@xxxxxxxxxxxxx", product)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/bugs/doc/bug-reporting-guidelines.txt b/lib/lp/bugs/doc/bug-reporting-guidelines.txt
index 44cb6c4..a89f692 100644
--- a/lib/lp/bugs/doc/bug-reporting-guidelines.txt
+++ b/lib/lp/bugs/doc/bug-reporting-guidelines.txt
@@ -53,19 +53,16 @@ read-only property, and the security proxies also only allow read
 access.
 
     >>> distro_series.bug_reporting_guidelines = 'Foobar'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ...
 
     >>> source_package.bug_reporting_guidelines = 'Foobar'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ...
 
     >>> product_series.bug_reporting_guidelines = 'Foobar'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ...
@@ -87,25 +84,21 @@ guidelines.
     ...     print(context.bug_reporting_guidelines)
 
     >>> check_access("no-priv@xxxxxxxxxxxxx", distribution)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
 
     >>> check_access("no-priv@xxxxxxxxxxxxx", distribution_source_package)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
 
     >>> check_access("no-priv@xxxxxxxxxxxxx", project)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
 
     >>> check_access("no-priv@xxxxxxxxxxxxx", product)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/bugs/doc/bug-tags.txt b/lib/lp/bugs/doc/bug-tags.txt
index b6aee57..ab49131 100644
--- a/lib/lp/bugs/doc/bug-tags.txt
+++ b/lib/lp/bugs/doc/bug-tags.txt
@@ -138,7 +138,6 @@ wrong.
     >>> request = LaunchpadTestRequest(form={'field.tags': u'!!!! foo $$$$'})
     >>> tags_widget = BugTagsWidget(bug_tags_field, tag_field, request)
     >>> tags_widget.getInputValue()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ...
diff --git a/lib/lp/bugs/doc/bug.txt b/lib/lp/bugs/doc/bug.txt
index 41d48d0..7ca7d2b 100644
--- a/lib/lp/bugs/doc/bug.txt
+++ b/lib/lp/bugs/doc/bug.txt
@@ -29,13 +29,12 @@ Or you can use IBugSet.getByNameOrID to get it by its nickname:
 If the bug can't be found, a zope.exceptions.NotFoundError will be
 raised:
 
-    >>> bugset.get(123456)  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> bugset.get(123456)
     Traceback (most recent call last):
       ...
     lp.app.errors.NotFoundError: 'Unable to locate bug with ID 123456.'
 
     >>> bugset.getByNameOrID('+bugs')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.errors.NotFoundError: ...'Unable to locate bug with nickname +bugs.'
@@ -176,13 +175,11 @@ private. A bug cannot be made private by an anonymous user.
     ...     return getUtility(ILaunchBag).user
 
     >>> firefox_crashes.private = True
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.ForbiddenAttribute: ('private', ...)
 
     >>> firefox_crashes.setPrivate(True, current_user())
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: (..., 'setPrivate', 'launchpad.Append')
@@ -208,7 +205,6 @@ Even though we are logged in and subscribed to the bug, we are
 prevented from using the private attribute to mark bug #6 private:
 
     >>> firefox_crashes.private = True
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.ForbiddenAttribute: ('private', ...)
@@ -337,7 +333,6 @@ Trying to access a property of this bug will again raise an
 Unauthorized:
 
     >>> reflow_problems_bug.title
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: (..., 'title', 'launchpad.View')
diff --git a/lib/lp/bugs/doc/bugattachments.txt b/lib/lp/bugs/doc/bugattachments.txt
index 3e58d5f..5a96419 100644
--- a/lib/lp/bugs/doc/bugattachments.txt
+++ b/lib/lp/bugs/doc/bugattachments.txt
@@ -313,7 +313,6 @@ anonymous can read the attachment's attributes, but they can't set them:
     >>> print(attachment.title)
     this fixes the bug
     >>> attachment.title = 'Better Title'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (..., 'title',...
@@ -347,12 +346,10 @@ attachments attributes:
     >>> login("no-priv@xxxxxxxxxxxxx")
 
     >>> attachment.title
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (..., 'title',...
     >>> attachment.title = 'Better Title'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (..., 'title',...
@@ -360,12 +357,11 @@ attachments attributes:
 Of course, anonymous is also not allowed to access or set them:
 
     >>> login(ANONYMOUS)
-    >>> attachment.title  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> attachment.title
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (..., 'title',...
     >>> attachment.title = 'Some info.'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (..., 'title',...
@@ -666,7 +662,6 @@ A NotFoundError is raised if the file name passed to getFileByName()
 does not match the file name of the Librarian file.
 
     >>> attachment.getFileByName('nonsense')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...'nonsense'
diff --git a/lib/lp/bugs/doc/bugmessage-visibility.txt b/lib/lp/bugs/doc/bugmessage-visibility.txt
index 43c683e..44f65e0 100644
--- a/lib/lp/bugs/doc/bugmessage-visibility.txt
+++ b/lib/lp/bugs/doc/bugmessage-visibility.txt
@@ -43,7 +43,6 @@ field.
     >>> abugmessage.message.visible
     False
     >>> abugmessage.message.visible = True
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (<Message at ...>, 'visible', 'launchpad.Admin')
diff --git a/lib/lp/bugs/doc/bugsubscription.txt b/lib/lp/bugs/doc/bugsubscription.txt
index bf6b69b..4b175ab 100644
--- a/lib/lp/bugs/doc/bugsubscription.txt
+++ b/lib/lp/bugs/doc/bugsubscription.txt
@@ -560,7 +560,6 @@ that the unsubscribing user has the appropriate permissions.  unsubscribe
 will raise an exception if the user does not have permission.
 
     >>> bug.unsubscribe(team, non_member)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UserCannotUnsubscribePerson: ...
diff --git a/lib/lp/bugs/doc/bugtask-assignee-widget.txt b/lib/lp/bugs/doc/bugtask-assignee-widget.txt
index 5bc18d6..cb4a0d2 100644
--- a/lib/lp/bugs/doc/bugtask-assignee-widget.txt
+++ b/lib/lp/bugs/doc/bugtask-assignee-widget.txt
@@ -129,7 +129,7 @@ The chooser widget got its name updated as well.
 If this option is selected, but no value is entered in
 "field.assignee", validation will fail:
 
-    >>> widget.validate()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> widget.validate()
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ...
@@ -138,7 +138,7 @@ Likewise, if a non-existent field.assignee is provided, the validation
 will fail:
 
     >>> request.form['foo.assignee'] = 'name'
-    >>> widget.validate()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> widget.validate()
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ...
diff --git a/lib/lp/bugs/doc/bugtask-bugwatch-widget.txt b/lib/lp/bugs/doc/bugtask-bugwatch-widget.txt
index 2fd1524..d247fd1 100644
--- a/lib/lp/bugs/doc/bugtask-bugwatch-widget.txt
+++ b/lib/lp/bugs/doc/bugtask-bugwatch-widget.txt
@@ -159,7 +159,6 @@ a WidgetInputError is being raised.
     ...     bugwatch_field, bugwatch_field.vocabulary, request)
 
     >>> bugwatch = bugwatch_widget.getInputValue()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ...
diff --git a/lib/lp/bugs/doc/bugtask-package-widget.txt b/lib/lp/bugs/doc/bugtask-package-widget.txt
index 81722bb..266e62c 100644
--- a/lib/lp/bugs/doc/bugtask-package-widget.txt
+++ b/lib/lp/bugs/doc/bugtask-package-widget.txt
@@ -71,7 +71,6 @@ NotFoundError.
 
     >>> gentoo = getUtility(IDistributionSet)['gentoo']
     >>> gentoo.guessPublishedSourcePackageName('evolution')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...
@@ -100,7 +99,7 @@ ConversionError saying that the package name doesn't exist.
     ...     form={'field.sourcepackagename': 'no-package'})
     >>> widget = BugTaskSourcePackageNameWidget(
     ...     package_field, package_field.vocabulary, request)
-    >>> widget.getInputValue()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> widget.getInputValue()
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.ConversionError: ...
@@ -133,7 +132,6 @@ name isn't the name of a distro, UnexpectedFormData is raised.
     >>> BugTaskAlsoAffectsSourcePackageNameWidget(
     ...     package_field, package_field.vocabulary,
     ...     request).getDistribution().name
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: ...
@@ -200,7 +198,6 @@ contain, so IDistribution.guessPublishedSourcePackageName will raise a
 NotFoundError.
 
     >>> gentoo_task.distribution.guessPublishedSourcePackageName('evolution')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...
@@ -227,7 +224,7 @@ ConversionError saying that the package name doesn't exist.
     ...     form={'field.packagename': 'no-package'})
     >>> widget = FileBugSourcePackageNameWidget(
     ...     package_field, package_field.vocabulary, request)
-    >>> widget.getInputValue()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> widget.getInputValue()
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.ConversionError: ...
diff --git a/lib/lp/bugs/doc/bugtask-retrieval.txt b/lib/lp/bugs/doc/bugtask-retrieval.txt
index 52cc894..287b8cc 100644
--- a/lib/lp/bugs/doc/bugtask-retrieval.txt
+++ b/lib/lp/bugs/doc/bugtask-retrieval.txt
@@ -35,7 +35,6 @@ When given a bug task ID that doesn't exist in the database, the method
 raises a NotFoundError:
 
     >>> no_such_task = task_set.get(0)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...
@@ -82,7 +81,7 @@ those bug task IDs that are present in the database:
     >>> task_set.getMultiple([1, 2])
     {2: <BugTask ...>}
 
-    >>> task_set.get(1)  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> task_set.get(1)
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...
diff --git a/lib/lp/bugs/doc/bugtask-search.txt b/lib/lp/bugs/doc/bugtask-search.txt
index f00d145..fcbd161 100644
--- a/lib/lp/bugs/doc/bugtask-search.txt
+++ b/lib/lp/bugs/doc/bugtask-search.txt
@@ -107,7 +107,6 @@ Passing invalid tsquery expressions as fast_searchtext raises an exception.
     >>> bad_search = BugTaskSearchParams(
     ...     user=None, fast_searchtext=u'happens pretty often')
     >>> list(firefox.searchTasks(bad_search))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     storm.database.ProgrammingError: syntax error in tsquery: "happens pretty often" ...
diff --git a/lib/lp/bugs/doc/bugtask-status-changes.txt b/lib/lp/bugs/doc/bugtask-status-changes.txt
index f7b63f8..c0b3949 100644
--- a/lib/lp/bugs/doc/bugtask-status-changes.txt
+++ b/lib/lp/bugs/doc/bugtask-status-changes.txt
@@ -32,7 +32,6 @@ other status.
 
     >>> ignored = login_person(user)
     >>> bugtask.transitionToStatus(BugTaskStatus.CONFIRMED, user)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.bugs.interfaces.bugtask.UserCannotEditBugTaskStatus: ...
diff --git a/lib/lp/bugs/doc/bugtask-status-workflow.txt b/lib/lp/bugs/doc/bugtask-status-workflow.txt
index 2ffd3be..3ee347f 100644
--- a/lib/lp/bugs/doc/bugtask-status-workflow.txt
+++ b/lib/lp/bugs/doc/bugtask-status-workflow.txt
@@ -56,7 +56,6 @@ directly.
     >>> from lp.bugs.interfaces.bugtask import BugTaskStatus
 
     >>> ubuntu_firefox_task.status = BugTaskStatus.CONFIRMED
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.ForbiddenAttribute: ...
@@ -282,7 +281,6 @@ setting an assignee has "side effects".
     >>> sample_person = getUtility(IPersonSet).get(12)
 
     >>> ubuntu_firefox_task.assignee = foobar
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.ForbiddenAttribute: ...
diff --git a/lib/lp/bugs/doc/bugtracker-person.txt b/lib/lp/bugs/doc/bugtracker-person.txt
index a36932c..d5599f0 100644
--- a/lib/lp/bugs/doc/bugtracker-person.txt
+++ b/lib/lp/bugs/doc/bugtracker-person.txt
@@ -42,7 +42,6 @@ new person to a bugtracker using an existing name will cause an error.
     >>> foo_bar = getUtility(IPersonSet).getByName('name16')
     >>> bugtracker_person = bugtracker.linkPersonToSelf(
     ...         'some-name-i-made-up', foo_bar)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.interfaces.bugtrackerperson.BugTrackerPersonAlreadyExists: Name 'some-name-i-made-up' is already in use for bugtracker 'bugzilla-checkwatches'.
diff --git a/lib/lp/bugs/doc/bugwatch.txt b/lib/lp/bugs/doc/bugwatch.txt
index f69fdc8..415be41 100644
--- a/lib/lp/bugs/doc/bugwatch.txt
+++ b/lib/lp/bugs/doc/bugwatch.txt
@@ -22,7 +22,6 @@ Bug watches are accessed via a utility that provides IBugWatchSet.
     >>> from zope.component import getUtility
     >>> from lp.bugs.interfaces.bugwatch import IBugWatchSet
     >>> getUtility(IBugWatchSet).get(98765)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: 98765
@@ -627,7 +626,6 @@ Calling setNextCheck() on this watch will cause an Exception,
 BugWatchCannotBeRescheduled, to be raised.
 
     >>> schedulable_watch.setNextCheck(datetime.now(utc))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.interfaces.bugwatch.BugWatchCannotBeRescheduled
diff --git a/lib/lp/bugs/doc/bugwidget.txt b/lib/lp/bugs/doc/bugwidget.txt
index f20d44a..c3f0012 100644
--- a/lib/lp/bugs/doc/bugwidget.txt
+++ b/lib/lp/bugs/doc/bugwidget.txt
@@ -22,7 +22,6 @@ If non-existant bug number is entered, an error is raised.
     >>> request = LaunchpadTestRequest(form={'field.bug': '1234567'})
     >>> bug_widget = BugWidget(bug_field, request)
     >>> bug_widget.getInputValue()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.ConversionError: ('Not a valid bug number or nickname.', None)
diff --git a/lib/lp/bugs/doc/cve-update.txt b/lib/lp/bugs/doc/cve-update.txt
index 417728a..ad7d8fd 100644
--- a/lib/lp/bugs/doc/cve-update.txt
+++ b/lib/lp/bugs/doc/cve-update.txt
@@ -168,7 +168,6 @@ schema is changed.
 
     >>> cve_updater = CVEUpdater('cve-updater', test_args=[])
     >>> cve_updater.processCVEXML('<some-xml />')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.scripts.base.LaunchpadScriptFailure: No CVEs found in XML file.
diff --git a/lib/lp/bugs/doc/cve.txt b/lib/lp/bugs/doc/cve.txt
index 3322f40..98e3480 100644
--- a/lib/lp/bugs/doc/cve.txt
+++ b/lib/lp/bugs/doc/cve.txt
@@ -111,7 +111,6 @@ linkCVE are bypassed.
     >>> private_bug = factory.makeBug(
     ...     information_type=InformationType.USERDATA)
     >>> private_bug.linkCVE(cve, user=no_priv)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/bugs/doc/externalbugtracker-bugzilla-api.txt b/lib/lp/bugs/doc/externalbugtracker-bugzilla-api.txt
index e6120cd..c7fb1fa 100644
--- a/lib/lp/bugs/doc/externalbugtracker-bugzilla-api.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-bugzilla-api.txt
@@ -65,7 +65,6 @@ will raise an error:
     ...     xmlrpc_transport=transport)
 
     >>> non_auth_bugzilla._authenticate()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugTrackerAuthenticationError: http://thiswillfail.example.com: No credentials found.
@@ -82,7 +81,6 @@ raise an error.
     ...     xmlrpc_transport=transport)
 
     >>> non_auth_bugzilla._authenticate()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
         ...
     lp.bugs.externalbugtracker.base.BugTrackerAuthenticationError: http://thiswillfail.example.com: Fault 300: The username or password you entered is not valid.
@@ -305,7 +303,6 @@ severity as a string.
 If a bug can't be found a BugNotFound error will be raised.
 
     >>> bugzilla.getRemoteStatus('no-such-bug')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugNotFound: no-such-bug
@@ -316,7 +313,6 @@ error will be raised. We can add a sample bug to demonstrate this.
 
     >>> bugzilla._bugs[999] = {}
     >>> bugzilla.getRemoteStatus(999)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnparsableBugData: No status or resolution defined for bug 999
@@ -406,7 +402,6 @@ If the product is requested for a bug that can't be found, BugNotFound
 is raised.
 
     >>> bugzilla.getRemoteProduct(12345)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.bugs.externalbugtracker.base.BugNotFound: 12345
@@ -469,7 +464,6 @@ getCommentIds() can only be called if initializeRemoteBugDB() has been
 called and the bug exists locally.
 
     >>> bugzilla.getCommentIds(bug_watch_broken.remotebug)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugNotFound: 42
@@ -619,7 +613,6 @@ then that instance does not provide ISupportsCommentPushing.
 
     >>> verifyObject(ISupportsCommentPushing, BugzillaAPI(
     ...     'http://unknown.example.com/', xmlrpc_transport=test_transport))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.interface.exceptions.DoesNotImplement: ...
@@ -681,7 +674,6 @@ then that instance does not provide ISupportsBackLinking.
 
     >>> verifyObject(ISupportsBackLinking, BugzillaAPI(
     ...     'http://unknown.example.com/', xmlrpc_transport=test_transport))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.interface.exceptions.DoesNotImplement: ...
diff --git a/lib/lp/bugs/doc/externalbugtracker-bugzilla-lp-plugin.txt b/lib/lp/bugs/doc/externalbugtracker-bugzilla-lp-plugin.txt
index b13e159..d2dbd78 100644
--- a/lib/lp/bugs/doc/externalbugtracker-bugzilla-lp-plugin.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-bugzilla-lp-plugin.txt
@@ -108,7 +108,6 @@ login_required() raises a fault.
 
     >>> test_transport.expireCookie(test_transport.auth_cookie)
     >>> test_bugzilla.xmlrpc_proxy.Test.login_required()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     xmlrpc.client.Fault: <Fault 410: 'Login Required'>
@@ -148,7 +147,6 @@ If authentication fails, a BugTrackerAuthenticationError will be raised.
     ...     )
 
     >>> test_bugzilla._authenticate()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugTrackerAuthenticationError: http://example.com: XML-RPC Fault: 100 "Sorry, you can't log in."
@@ -158,7 +156,6 @@ This is also true if an error occurs at the protocol level:
     >>> fail_transport.error = ProtocolError(
     ...     'http://example.com', 500, 'Internal server error', {})
     >>> test_bugzilla._authenticate()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
        ...
     lp.bugs.externalbugtracker.base.BugTrackerAuthenticationError: http://example.com: Protocol error: 500 "Internal server error"
@@ -385,7 +382,6 @@ called and the bug exists locally.
     >>> transaction.commit()
 
     >>> bugzilla.getCommentIds(remote_bug)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugNotFound: 42
diff --git a/lib/lp/bugs/doc/externalbugtracker-bugzilla-oddities.txt b/lib/lp/bugs/doc/externalbugtracker-bugzilla-oddities.txt
index b6d2f3a..52b1cc7 100644
--- a/lib/lp/bugs/doc/externalbugtracker-bugzilla-oddities.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-bugzilla-oddities.txt
@@ -147,7 +147,6 @@ invalid XML:
     >>> remote_bugs = ['42', '2000']
     >>> with broken_bugzilla.responses():
     ...     broken_bugzilla.initializeRemoteBugDB(remote_bugs)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.bugs.externalbugtracker.base.UnparsableBugData: Failed to parse XML description...
diff --git a/lib/lp/bugs/doc/externalbugtracker-bugzilla.txt b/lib/lp/bugs/doc/externalbugtracker-bugzilla.txt
index b8a9226..94cc309 100644
--- a/lib/lp/bugs/doc/externalbugtracker-bugzilla.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-bugzilla.txt
@@ -27,7 +27,6 @@ UnparsableBugTrackerVersion is raised:
     >>> from lp.testing.layers import LaunchpadZopelessLayer
     >>> txn = LaunchpadZopelessLayer.txn
     >>> external_bugzilla = Bugzilla('http://example.com/', version='A.B')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnparsableBugTrackerVersion: Failed to parse version 'A.B' for http://...
@@ -345,12 +344,10 @@ If the status can't be converted an UnknownRemoteStatusError will be
 returned.
 
     >>> external_bugzilla.convertRemoteStatus('FOO').title
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnknownRemoteStatusError: FOO
     >>> external_bugzilla.convertRemoteStatus('CLOSED BAR').title
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnknownRemoteStatusError: CLOSED BAR
@@ -464,12 +461,10 @@ However, we still treat as an error if the priority or severity are set
 to some other unexpected string.
 
     >>> external_bugzilla.convertRemoteImportance('foo bar')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.bugs.externalbugtracker.base.UnknownRemoteImportanceError: foo bar
     >>> external_bugzilla.convertRemoteImportance('%&*@*#&$%!')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.bugs.externalbugtracker.base.UnknownRemoteImportanceError: %&*@*#&$%!
@@ -742,7 +737,6 @@ bug tracker, an error is logged.
     ...     requests_mock.add('POST', re.compile(r'.*'), body='<invalid xml>')
     ...     bug_watch_updater.updateBugWatches(
     ...         external_bugzilla, [bug_watch1, bug_watch2])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.bugs.externalbugtracker.base.UnparsableBugData: Failed to parse XML description for https://bugzilla.mozilla.org...
@@ -801,7 +795,6 @@ Requesting the product for a bug that doesn't exist raises BugNotFound.
     >>> with external_bugzilla.responses():
     ...     external_bugzilla.initializeRemoteBugDB(['84'])
     >>> external_bugzilla.getRemoteProduct('42')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.bugs.externalbugtracker.base.BugNotFound: 42
diff --git a/lib/lp/bugs/doc/externalbugtracker-debbugs.txt b/lib/lp/bugs/doc/externalbugtracker-debbugs.txt
index 3ed2b15..5dc2fe8 100644
--- a/lib/lp/bugs/doc/externalbugtracker-debbugs.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-debbugs.txt
@@ -56,7 +56,6 @@ getRemoteStatus() method. If we pass a bug number that doesn't exist in
 the debbugs db, BugNotFound is raised.
 
     >>> external_debbugs.getRemoteStatus('42')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.bugs.externalbugtracker.base.BugNotFound: 42
@@ -64,7 +63,6 @@ the debbugs db, BugNotFound is raised.
 If we pass a non-integer bug id, InvalidBugId is raised.
 
     >>> external_debbugs.getRemoteStatus('foo')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.bugs.externalbugtracker.base.InvalidBugId: Debbugs bug number not an integer: foo
@@ -281,7 +279,6 @@ If we pass in a malformed status string an UnknownRemoteStatusError will
 be raised.
 
     >>> print(external_debbugs.convertRemoteStatus('open'))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnknownRemoteStatusError: open
@@ -719,7 +716,6 @@ Trying to call getRemoteProduct() on a bug that doesn't exist will raise
 a BugNotFound error.
 
     >>> print(external_debbugs.getRemoteProduct('42'))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugNotFound: 42
diff --git a/lib/lp/bugs/doc/externalbugtracker-emailaddress.txt b/lib/lp/bugs/doc/externalbugtracker-emailaddress.txt
index 9e6adf8..b0b5c8c 100644
--- a/lib/lp/bugs/doc/externalbugtracker-emailaddress.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-emailaddress.txt
@@ -25,7 +25,6 @@ create a new ExternalBugTracker for an email address will fail.
     ...     new_bugtracker)
     >>> bug_tracker = get_external_bugtracker(
     ...     new_bugtracker(BugTrackerType.EMAILADDRESS))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnknownBugTrackerTypeError: EMAILADDRESS
diff --git a/lib/lp/bugs/doc/externalbugtracker-mantis-csv.txt b/lib/lp/bugs/doc/externalbugtracker-mantis-csv.txt
index d9fb120..05bbcb5 100644
--- a/lib/lp/bugs/doc/externalbugtracker-mantis-csv.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-mantis-csv.txt
@@ -38,7 +38,6 @@ in the form "status: resolution" as follows:
 If the status can't be converted an UnknownRemoteStatusError is raised.
 
     >>> alsa_mantis.convertRemoteStatus(('foo: bar')).title
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnknownRemoteStatusError: foo: bar
diff --git a/lib/lp/bugs/doc/externalbugtracker-mantis-logging-in.txt b/lib/lp/bugs/doc/externalbugtracker-mantis-logging-in.txt
index 259726c..8b87b9f 100644
--- a/lib/lp/bugs/doc/externalbugtracker-mantis-logging-in.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-mantis-logging-in.txt
@@ -56,7 +56,6 @@ when Mantis redirects back to the login page with an error it forgets
 the "return" parameter.
 
     >>> run_hook('http://mantis.example.com/login_page.php')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugTrackerConnectError: http://mantis.example.com/login_page.php: Mantis redirected us to the login page but did not set a return path.
diff --git a/lib/lp/bugs/doc/externalbugtracker-mantis.txt b/lib/lp/bugs/doc/externalbugtracker-mantis.txt
index bf2768b..0a15a0e 100644
--- a/lib/lp/bugs/doc/externalbugtracker-mantis.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-mantis.txt
@@ -41,7 +41,6 @@ in the form "status: resolution" as follows:
 If the status can't be converted an UnknownRemoteStatusError is raised.
 
     >>> alsa_mantis.convertRemoteStatus(('foo: bar')).title
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnknownRemoteStatusError: foo: bar
diff --git a/lib/lp/bugs/doc/externalbugtracker-roundup-python-bugs.txt b/lib/lp/bugs/doc/externalbugtracker-roundup-python-bugs.txt
index 4c2916a..7225c7f 100644
--- a/lib/lp/bugs/doc/externalbugtracker-roundup-python-bugs.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-roundup-python-bugs.txt
@@ -77,7 +77,6 @@ If the status isn't something that our Python_Bugs ExternalBugTracker can
 understand an UnknownRemoteStatusError will be raised.
 
     >>> python_bugs.convertRemoteStatus('7:13').title
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnknownRemoteStatusError: 7:13
diff --git a/lib/lp/bugs/doc/externalbugtracker-roundup.txt b/lib/lp/bugs/doc/externalbugtracker-roundup.txt
index 1d369a2..44c577b 100644
--- a/lib/lp/bugs/doc/externalbugtracker-roundup.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-roundup.txt
@@ -58,7 +58,6 @@ support), and will generate an error when we have more or less field
 values compared to the expected number of fields.
 
     >>> roundup.convertRemoteStatus('1:2')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnknownRemoteStatusError: 1 field(s) expected, got 2: 1:2
@@ -67,7 +66,6 @@ If the status isn't something that our Roundup ExternalBugTracker can
 understand an UnknownRemoteStatusError will be raised.
 
     >>> roundup.convertRemoteStatus('eggs').title
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnknownRemoteStatusError: Unrecognized value for field 1 (status): eggs
diff --git a/lib/lp/bugs/doc/externalbugtracker-rt.txt b/lib/lp/bugs/doc/externalbugtracker-rt.txt
index d25c1ed..7a1b9bd 100644
--- a/lib/lp/bugs/doc/externalbugtracker-rt.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-rt.txt
@@ -70,7 +70,6 @@ Passing a status which the RequestTracker instance can't understand will
 result in an UnknownRemoteStatusError being raised.
 
     >>> rt.convertRemoteStatus('spam').title
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnknownRemoteStatusError: spam
@@ -159,7 +158,6 @@ our test RT instance simulate such a situation.
 
     >>> with rt.responses(bad=True):
     ...     rt.initializeRemoteBugDB([1585])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugTrackerConnectError: ...
@@ -168,7 +166,6 @@ This can also be demonstrated for importing bugs as a batch:
 
     >>> with rt.responses(bad=True):
     ...     rt.initializeRemoteBugDB([1585, 1586, 1587, 1588, 1589])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugTrackerConnectError: ...
@@ -276,7 +273,6 @@ If you try to get the remote product of a bug that doesn't exist you'll
 get a BugNotFound error.
 
     >>> print(rt.getRemoteProduct('this-doesnt-exist'))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugNotFound: this-doesnt-exist
diff --git a/lib/lp/bugs/doc/externalbugtracker-sourceforge.txt b/lib/lp/bugs/doc/externalbugtracker-sourceforge.txt
index 707bbb4..ddaf8b0 100644
--- a/lib/lp/bugs/doc/externalbugtracker-sourceforge.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-sourceforge.txt
@@ -70,7 +70,6 @@ If the status isn't something that our SourceForge ExternalBugTracker can
 understand an UnknownRemoteStatusError will be raised.
 
     >>> sourceforge.convertRemoteStatus('eggs').title
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnknownRemoteStatusError: eggs
@@ -100,7 +99,6 @@ resolution, to demonstrate this:
 
     >>> with sourceforge.responses():
     ...     sourceforge.initializeRemoteBugDB([0])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnparsableBugData: Remote bug 0 does not define a status.
@@ -134,7 +132,6 @@ Trying to access the remote status of a private bug, however, will raise
 a PrivateRemoteBug error.
 
     >>> sourceforge.getRemoteStatus(99)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     lp.bugs.externalbugtracker.base.PrivateRemoteBug: Bug 99 on http://example.com is private.
@@ -284,7 +281,6 @@ If you try to get the remote product of a bug that doesn't exist you'll
 get a BugNotFound error.
 
     >>> print(sourceforge.getRemoteProduct(999999999))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugNotFound: 999999999
diff --git a/lib/lp/bugs/doc/externalbugtracker-trac-lp-plugin.txt b/lib/lp/bugs/doc/externalbugtracker-trac-lp-plugin.txt
index 4fdb9f7..e15b181 100644
--- a/lib/lp/bugs/doc/externalbugtracker-trac-lp-plugin.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-trac-lp-plugin.txt
@@ -132,7 +132,6 @@ If authentication fails, a BugTrackerAuthenticationError will be raised.
     ...     requests_mock.add(
     ...         'GET', re.compile(r'.*/launchpad-auth/.*'), status=401)
     ...     trac._authenticate()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugTrackerAuthenticationError: http://example.com: 401 Client Error: Unauthorized
@@ -303,7 +302,6 @@ since that bug wasn't in the list of bugs that were modified since our
 last_checked time.
 
     >>> trac.getRemoteStatus('2')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugNotFound: 2
@@ -398,7 +396,6 @@ Trying to call getCommentIds() on a bug that doesn't exist will raise a
 BugNotFound error.
 
     >>> trac.getCommentIds(bug_watch_broken.remotebug)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugNotFound: 123
@@ -606,14 +603,12 @@ If we try to call getLaunchpadBugId() or setLaunchpadBugId() for a
 remote bug that doesn't exist, a BugNotFound error will be raised.
 
     >>> trac.getLaunchpadBugId('12345')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugNotFound: 12345
 
     >>> trac.setLaunchpadBugId(
     ...     '12345', 1, 'http://bugs.launchpad.test/bugs/xxx')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugNotFound: 12345
diff --git a/lib/lp/bugs/doc/externalbugtracker-trac.txt b/lib/lp/bugs/doc/externalbugtracker-trac.txt
index 53df563..b3daf94 100644
--- a/lib/lp/bugs/doc/externalbugtracker-trac.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-trac.txt
@@ -138,7 +138,6 @@ If the status isn't one that our Trac ExternalBugTracker can understand
 an UnknownRemoteStatusError will be raised.
 
     >>> trac.convertRemoteStatus('eggs').title
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnknownRemoteStatusError: eggs
@@ -215,7 +214,6 @@ test.
 
     >>> with trac.responses(broken=True):
     ...     trac.initializeRemoteBugDB([6, 7, 8, 9, 10])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnparsableBugData: External bugtracker http://test.trac does not define all the necessary fields for bug status imports (Defined field names: ['<html>']).
@@ -224,7 +222,6 @@ This is also true of the single bug export mode.
 
     >>> with trac.responses(broken=True):
     ...     trac.initializeRemoteBugDB([6])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnparsableBugData: External bugtracker http://test.trac does not define all the necessary fields for bug status imports (Defined field names: ['<html>']).
@@ -233,7 +230,6 @@ Trying to get the remote status of the bug will raise a BugNotFound
 error since the bug was never imported.
 
     >>> trac.getRemoteStatus(6)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.BugNotFound: 6
@@ -263,7 +259,6 @@ export, it will raise an UnparsableBugData error.
 
     >>> with trac.responses(broken=True):
     ...     trac._fetchBugData(query_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.bugs.externalbugtracker.base.UnparsableBugData: External bugtracker http://test.trac does not define all the necessary fields for bug status imports (Defined field names: ['<html>']).
diff --git a/lib/lp/bugs/doc/externalbugtracker.txt b/lib/lp/bugs/doc/externalbugtracker.txt
index 815d9db..9d22920 100644
--- a/lib/lp/bugs/doc/externalbugtracker.txt
+++ b/lib/lp/bugs/doc/externalbugtracker.txt
@@ -345,7 +345,6 @@ is, an error is raised.
 
     >>> bug_watch_updater.updateBugWatches(
     ...     PositiveTimeSkewExternalBugTracker(), [], now=utc_now)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.bugs.scripts.checkwatches.core.TooMuchTimeSkew: ...
@@ -357,7 +356,6 @@ is, an error is raised.
 
     >>> bug_watch_updater.updateBugWatches(
     ...     NegativeTimeSkewExternalBugTracker(), [], now=utc_now)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.bugs.scripts.checkwatches.core.TooMuchTimeSkew: ...
@@ -371,7 +369,6 @@ before re-raising the error.
     >>> server_time = utc_now - timedelta(minutes=25)
     >>> bug_watch_updater._getRemoteIdsToCheck(
     ...     NegativeTimeSkewExternalBugTracker(), [], server_time, utc_now)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.bugs.scripts.checkwatches.core.TooMuchTimeSkew: ...
diff --git a/lib/lp/bugs/doc/initial-bug-contacts.txt b/lib/lp/bugs/doc/initial-bug-contacts.txt
index 68e66c0..46e8ed2 100644
--- a/lib/lp/bugs/doc/initial-bug-contacts.txt
+++ b/lib/lp/bugs/doc/initial-bug-contacts.txt
@@ -29,7 +29,6 @@ logged in to call this method:
     >>> sample_person = personset.getByName("name12")
 
     >>> debian_firefox.addBugSubscription(sample_person, sample_person)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
@@ -80,7 +79,6 @@ raises a DeleteSubscriptionError.
 
     >>> foobar = personset.getByName("name16")
     >>> debian_firefox.removeBugSubscription(foobar, foobar)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.registry.errors.DeleteSubscriptionError: ...
diff --git a/lib/lp/bugs/doc/malone-xmlrpc.txt b/lib/lp/bugs/doc/malone-xmlrpc.txt
index 4e6d68d..5df5db6 100644
--- a/lib/lp/bugs/doc/malone-xmlrpc.txt
+++ b/lib/lp/bugs/doc/malone-xmlrpc.txt
@@ -165,7 +165,6 @@ Failing to specify a product or distribution.
 
     >>> params = dict()
     >>> filebug_api.filebug(params)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     xmlrpc.client.Fault: <Fault 60: 'Required arguments missing. You must specify either a product or distribution in which the bug exists.'>
@@ -174,7 +173,6 @@ Specifying *both* a product and distribution.
 
     >>> params = dict(product='firefox', distro='ubuntu')
     >>> filebug_api.filebug(params)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     xmlrpc.client.Fault: <Fault 70: 'Too many arguments. You may specify either a product or a distribution, but not both.'>
@@ -183,7 +181,6 @@ Specifying a non-existent product.
 
     >>> params = dict(product='nosuchproduct')
     >>> filebug_api.filebug(params)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     xmlrpc.client.Fault: <Fault 10: 'No such project: nosuchproduct'>
@@ -192,7 +189,6 @@ Specifying a non-existent distribution.
 
     >>> params = dict(distro='nosuchdistro')
     >>> filebug_api.filebug(params)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     xmlrpc.client.Fault: <Fault 80: 'No such distribution: nosuchdistro'>
@@ -201,7 +197,6 @@ Specifying a non-existent package.
 
     >>> params = dict(distro='ubuntu', package='nosuchpackage')
     >>> filebug_api.filebug(params)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     xmlrpc.client.Fault: <Fault 90: 'No such package: nosuchpackage'>
@@ -210,7 +205,6 @@ Missing summary.
 
     >>> params = dict(product='firefox')
     >>> filebug_api.filebug(params)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     xmlrpc.client.Fault: <Fault 100: 'Required parameter missing: summary'>
@@ -219,7 +213,6 @@ Missing comment.
 
     >>> params = dict(product='firefox', summary='the summary')
     >>> filebug_api.filebug(params)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     xmlrpc.client.Fault: <Fault 100: 'Required parameter missing: comment'>
@@ -230,7 +223,6 @@ Invalid subscriber.
     ...     product='firefox', summary='summary', comment='comment',
     ...     subscribers=["foo.bar@xxxxxxxxxxxxx", "nosuch@xxxxxxxxxxxxxx"])
     >>> filebug_api.filebug(params)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     xmlrpc.client.Fault: <Fault 20: 'Invalid subscriber: No user with the email address "nosuch@xxxxxxxxxxxxxx" was found'>
diff --git a/lib/lp/bugs/doc/official-bug-tags.txt b/lib/lp/bugs/doc/official-bug-tags.txt
index 5d939be..44f7d93 100644
--- a/lib/lp/bugs/doc/official-bug-tags.txt
+++ b/lib/lp/bugs/doc/official-bug-tags.txt
@@ -41,7 +41,6 @@ But bug tags must be unique for each product and distribution.
     >>> store.add(distro_tag3)
     <lp.bugs.model.bugtarget.OfficialBugTag object at...
     >>> store.flush()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     storm.database.IntegrityError: ...
 
@@ -116,25 +115,21 @@ Ordinary users cannot add and remove official bug tags.
 
     >>> login('no-priv@xxxxxxxxxxxxx')
     >>> ubuntu.addOfficialBugTag(u'foo')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (<Distribution 'Ubuntu' (ubuntu)>, 'addOfficialBugTag', 'launchpad.Edit')
 
     >>> ubuntu.removeOfficialBugTag(u'foo')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (<Distribution 'Ubuntu' (ubuntu)>, 'removeOfficialBugTag', 'launchpad.Edit')
 
     >>> firefox.addOfficialBugTag(u'foo')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (<Product at ...>, 'addOfficialBugTag', 'launchpad.Edit')
 
     >>> firefox.removeOfficialBugTag(u'foo')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (<Product at ...>, 'removeOfficialBugTag', 'launchpad.Edit')
@@ -175,7 +170,6 @@ But only writable for users with edit permissions.
 
     >>> login('no-priv@xxxxxxxxxxxxx')
     >>> ubuntu.official_bug_tags = [u'foo', u'bar']
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (<Distribution 'Ubuntu' (ubuntu)>, 'official_bug_tags', 'launchpad.BugSupervisor')
diff --git a/lib/lp/bugs/doc/vocabularies.txt b/lib/lp/bugs/doc/vocabularies.txt
index bfd449b..a7916bc 100644
--- a/lib/lp/bugs/doc/vocabularies.txt
+++ b/lib/lp/bugs/doc/vocabularies.txt
@@ -244,7 +244,6 @@ Trying to get a non-existent release will result in a
 NoSuchDistroSeries error.
 
     >>> series_vocabulary.getTermByToken('non-such-release')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.registry.errors.NoSuchDistroSeries: ...
diff --git a/lib/lp/bugs/stories/bug-privacy/xx-bug-privacy.txt b/lib/lp/bugs/stories/bug-privacy/xx-bug-privacy.txt
index a0b911d..f6c5c45 100644
--- a/lib/lp/bugs/stories/bug-privacy/xx-bug-privacy.txt
+++ b/lib/lp/bugs/stories/bug-privacy/xx-bug-privacy.txt
@@ -80,7 +80,6 @@ Anonymous users cannot see private bugs filed on distros, of course!
 Not directly.
 
     >>> anon_browser.open("http://launchpad.test/bugs/14";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
@@ -97,7 +96,6 @@ Neither directly.
 
     >>> browser = setupBrowser("Basic no-privs@xxxxxxxxxxxxx:test")
     >>> browser.open("http://launchpad.test/bugs/14";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/bugs/stories/bug-privacy/xx-presenting-private-bugs.txt b/lib/lp/bugs/stories/bug-privacy/xx-presenting-private-bugs.txt
index 81778ee..f56deb7 100644
--- a/lib/lp/bugs/stories/bug-privacy/xx-presenting-private-bugs.txt
+++ b/lib/lp/bugs/stories/bug-privacy/xx-presenting-private-bugs.txt
@@ -61,13 +61,11 @@ But poor old no privs does not, and neither do anonymous users:
 
     >>> browser = setupBrowser(auth="Basic no-priv@xxxxxxxxxxxxx:test")
     >>> browser.open('http://bugs.launchpad.test/bugs/4')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
 
     >>> anon_browser.open('http://bugs.launchpad.test/bugs/4')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/bugs/stories/bug-release-management/xx-anonymous-bug-nomination.txt b/lib/lp/bugs/stories/bug-release-management/xx-anonymous-bug-nomination.txt
index 947bbb4..52c7c53 100644
--- a/lib/lp/bugs/stories/bug-release-management/xx-anonymous-bug-nomination.txt
+++ b/lib/lp/bugs/stories/bug-release-management/xx-anonymous-bug-nomination.txt
@@ -7,7 +7,6 @@ launchpad.Edit permission is required to do so.:
     >>> anon_browser.open('http://bugs.launchpad.test/jokosher/+bug/12')
 
     >>> anon_browser.getLink('Nominate for series').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...'launchpad.Edit'...
diff --git a/lib/lp/bugs/stories/bug-release-management/xx-bug-release-management.txt b/lib/lp/bugs/stories/bug-release-management/xx-bug-release-management.txt
index 7da1064..9dff651 100644
--- a/lib/lp/bugs/stories/bug-release-management/xx-bug-release-management.txt
+++ b/lib/lp/bugs/stories/bug-release-management/xx-bug-release-management.txt
@@ -203,7 +203,6 @@ in the release task.
     >>> ubuntu_edit_url = (
     ...     'http://bugs.launchpad.test/ubuntu/+bug/2/+editstatus')
     >>> user_browser.getLink(url=ubuntu_edit_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -255,7 +254,6 @@ the distribution task won't be editable.
     >>> user_browser.getControl('Save Changes').click()
 
     >>> user_browser.getLink(url=ubuntu_edit_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -272,7 +270,6 @@ general distribution task will remain uneditable.
     >>> user_browser.getControl('Save Changes').click()
 
     >>> user_browser.getLink(url=ubuntu_edit_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -293,7 +290,6 @@ in the series task.
     >>> firefox_edit_url = (
     ...     'http://bugs.launchpad.test/firefox/+bug/4/+editstatus')
     >>> user_browser.getLink(url=firefox_edit_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -347,7 +343,6 @@ the distribution task won't be editable.
     >>> user_browser.getControl('Save Changes').click()
 
     >>> user_browser.getLink(url=firefox_edit_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -364,7 +359,6 @@ general distribution task will remain uneditable.
     >>> user_browser.getControl('Save Changes').click()
 
     >>> user_browser.getLink(url=firefox_edit_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/bugs/stories/bug-tags/xx-official-bug-tags.txt b/lib/lp/bugs/stories/bug-tags/xx-official-bug-tags.txt
index 9b3596f..4fa1eb4 100644
--- a/lib/lp/bugs/stories/bug-tags/xx-official-bug-tags.txt
+++ b/lib/lp/bugs/stories/bug-tags/xx-official-bug-tags.txt
@@ -28,14 +28,12 @@ distributions but not for other bug targets.
     >>> admin_browser.open(
     ...     'http://bugs.launchpad.test/firefox/1.0')
     >>> print(admin_browser.getLink('Edit official tags'))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> admin_browser.open(
     ...     'http://bugs.launchpad.test/firefox/1.0/+manage-official-tags')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
@@ -45,14 +43,12 @@ administrators but not for ordinary users.
 
     >>> browser.open('http://bugs.launchpad.test/firefox')
     >>> print(browser.getLink('Edit official tags'))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> browser.open(
     ...     'http://bugs.launchpad.test/firefox/+manage-official-tags')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/bugs/stories/bugattachments/xx-bugattachments.txt b/lib/lp/bugs/stories/bugattachments/xx-bugattachments.txt
index caa26a7..01f6659 100644
--- a/lib/lp/bugs/stories/bugattachments/xx-bugattachments.txt
+++ b/lib/lp/bugs/stories/bugattachments/xx-bugattachments.txt
@@ -2,7 +2,6 @@ We need to login in order to add attachments.
 
     >>> anon_browser.open(
     ...     'http://bugs.launchpad.test/firefox/+bug/1/+addcomment')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/bugs/stories/bugs/bug-add-subscriber.txt b/lib/lp/bugs/stories/bugs/bug-add-subscriber.txt
index 0e82fc5..e0bbfc9 100644
--- a/lib/lp/bugs/stories/bugs/bug-add-subscriber.txt
+++ b/lib/lp/bugs/stories/bugs/bug-add-subscriber.txt
@@ -9,7 +9,6 @@ Anonymous users should not be able to subscribe someone else to a bug.
 
     >>> anon_browser.open('http://bugs.launchpad.test/firefox/+bug/1')
     >>> anon_browser.getLink('Subscribe someone else').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/bugs/stories/bugs/xx-bug-comment-attach-file.txt b/lib/lp/bugs/stories/bugs/xx-bug-comment-attach-file.txt
index 7d38b84..a870168 100644
--- a/lib/lp/bugs/stories/bugs/xx-bug-comment-attach-file.txt
+++ b/lib/lp/bugs/stories/bugs/xx-bug-comment-attach-file.txt
@@ -6,7 +6,6 @@ case, it means being logged in.
 
     >>> anon_browser.open(
     ...     "http://bugs.launchpad.test/firefox/+bug/1/+addcomment-form";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.security.interfaces.Unauthorized: ...launchpad.Edit...
diff --git a/lib/lp/bugs/stories/bugs/xx-bug-create-question.txt b/lib/lp/bugs/stories/bugs/xx-bug-create-question.txt
index f9ebcda..b2d2ee3 100644
--- a/lib/lp/bugs/stories/bugs/xx-bug-create-question.txt
+++ b/lib/lp/bugs/stories/bugs/xx-bug-create-question.txt
@@ -17,7 +17,6 @@ An anonymous user cannot create a question.
     'Bug #10 ... : Bugs : linux-source-2.6.15 package : Ubuntu'
 
     >>> anon_browser.getLink('Convert to a question').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/bugs/stories/bugs/xx-bug-edit.txt b/lib/lp/bugs/stories/bugs/xx-bug-edit.txt
index 9e9af89..7e888cd 100644
--- a/lib/lp/bugs/stories/bugs/xx-bug-edit.txt
+++ b/lib/lp/bugs/stories/bugs/xx-bug-edit.txt
@@ -40,7 +40,6 @@ there is no link to the original description.
 
     >>> user_browser.open('http://bugs.launchpad.test/firefox/+bug/4')
     >>> user_browser.getLink('original description')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/bugs/stories/bugs/xx-bug-hidden-comments.txt b/lib/lp/bugs/stories/bugs/xx-bug-hidden-comments.txt
index 31fb476..1a8c9cc 100644
--- a/lib/lp/bugs/stories/bugs/xx-bug-hidden-comments.txt
+++ b/lib/lp/bugs/stories/bugs/xx-bug-hidden-comments.txt
@@ -59,7 +59,6 @@ Ordinary users also cannot reach the message via direct link.
     >>> test_browser.open(
     ...     'http://bugs.launchpad.test'
     ...     '/jokosher/+bug/11/comments/%d' % (int(latest_index[1:]) + 1))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/bugs/stories/bugs/xx-bug-nomination-table-row.txt b/lib/lp/bugs/stories/bugs/xx-bug-nomination-table-row.txt
index f5b0609..747f331 100644
--- a/lib/lp/bugs/stories/bugs/xx-bug-nomination-table-row.txt
+++ b/lib/lp/bugs/stories/bugs/xx-bug-nomination-table-row.txt
@@ -56,7 +56,6 @@ buttons) directly either.
     >>> user_browser.open(
     ...     "http://launchpad.test/distros/ubuntu/+source/mozilla-firefox/";
     ...     "+bug/1/nominations/2/+edit-form")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/bugs/stories/bugs/xx-bugs-advanced-search-upstream-status.txt b/lib/lp/bugs/stories/bugs/xx-bugs-advanced-search-upstream-status.txt
index cdbc150..b405996 100644
--- a/lib/lp/bugs/stories/bugs/xx-bugs-advanced-search-upstream-status.txt
+++ b/lib/lp/bugs/stories/bugs/xx-bugs-advanced-search-upstream-status.txt
@@ -211,7 +211,6 @@ Other values for status_upstream lead to an error.
     >>> anon_browser.open(
     ...     'http://bugs.launchpad.test/ubuntu/+bugs?' + urlencode(
     ...         bookmark_params, True))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: Unexpected value for field 'status_upstream'. Perhaps your bookmarks are out of date or you changed the URL by hand?
diff --git a/lib/lp/bugs/stories/bugs/xx-distribution-bugs-page.txt b/lib/lp/bugs/stories/bugs/xx-distribution-bugs-page.txt
index 0a114d2..ef5e0be 100644
--- a/lib/lp/bugs/stories/bugs/xx-distribution-bugs-page.txt
+++ b/lib/lp/bugs/stories/bugs/xx-distribution-bugs-page.txt
@@ -86,7 +86,6 @@ see any link reporting that bugs can expire.
 
     >>> anon_browser.open('http://bugs.launchpad.test/debian/+bugs')
     >>> expirable_bugs_link = anon_browser.getLink('Incomplete bugs')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt b/lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt
index b54b9f1..8bbe996 100644
--- a/lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt
+++ b/lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt
@@ -180,7 +180,6 @@ This specialized list does not include the search form. So there is no
 The 'Report a bug' link is also not present.
 
     >>> user_browser.getLink('Report a bug')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/bugs/stories/bugs/xx-product-bugs-page.txt b/lib/lp/bugs/stories/bugs/xx-product-bugs-page.txt
index 5d17888..fdc8858 100644
--- a/lib/lp/bugs/stories/bugs/xx-product-bugs-page.txt
+++ b/lib/lp/bugs/stories/bugs/xx-product-bugs-page.txt
@@ -98,7 +98,6 @@ cannot see any link reporting that bugs can expire.
 
     >>> anon_browser.open('http://bugs.launchpad.test/thunderbird')
     >>> expirable_bugs_link = anon_browser.getLink('Incomplete bugs')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/bugs/stories/bugs/xx-unique-ids-on-bug-page.txt b/lib/lp/bugs/stories/bugs/xx-unique-ids-on-bug-page.txt
index b183d8f..39d7cb4 100644
--- a/lib/lp/bugs/stories/bugs/xx-unique-ids-on-bug-page.txt
+++ b/lib/lp/bugs/stories/bugs/xx-unique-ids-on-bug-page.txt
@@ -11,7 +11,6 @@ For example, bug one has more than one Package field.
 
     >>> user_browser.open('http://launchpad.test/bugs/1')
     >>> user_browser.getControl('Package')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.AmbiguityError: label ...'Package' matches: ...
diff --git a/lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.txt b/lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.txt
index ff2d0cd..e8b4111 100644
--- a/lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.txt
+++ b/lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.txt
@@ -41,13 +41,11 @@ those statuses are not shown in the UI:
     ['Confirmed']
 
     >>> status_control.displayValue = ["Won't Fix"]
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.ItemNotFoundError: Won't Fix
 
     >>> status_control.displayValue = ["Triaged"]
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.ItemNotFoundError: Triaged
diff --git a/lib/lp/bugs/stories/bugtask-management/xx-bugtask-edit-forms.txt b/lib/lp/bugs/stories/bugtask-management/xx-bugtask-edit-forms.txt
index d60ed21..dc57806 100644
--- a/lib/lp/bugs/stories/bugtask-management/xx-bugtask-edit-forms.txt
+++ b/lib/lp/bugs/stories/bugtask-management/xx-bugtask-edit-forms.txt
@@ -26,7 +26,6 @@ respective bug task.
     http://bugs.launchpad.test/firefox/+bug/1/+editstatus
 
     >>> print(admin_browser.getLink('Confirmed').url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/bugs/stories/bugtask-management/xx-view-editable-bug-task.txt b/lib/lp/bugs/stories/bugtask-management/xx-view-editable-bug-task.txt
index 5159513..c906387 100644
--- a/lib/lp/bugs/stories/bugtask-management/xx-view-editable-bug-task.txt
+++ b/lib/lp/bugs/stories/bugtask-management/xx-view-editable-bug-task.txt
@@ -2,7 +2,6 @@ An anonymous user who tries to access the bugtask edit page will be
 redirected to the login page.
 
     >>> browser.open("http://launchpad.test/thunderbird/+bug/9/+editstatus";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
@@ -23,7 +22,6 @@ Even when the product has a bug supervisor, see bug #49891.
     >>> logout()
 
     >>> browser.open("http://launchpad.test/firefox/+bug/1/+editstatus";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/bugs/stories/bugtask-searches/xx-unexpected-form-data.txt b/lib/lp/bugs/stories/bugtask-searches/xx-unexpected-form-data.txt
index aefde8b..07c8a85 100644
--- a/lib/lp/bugs/stories/bugtask-searches/xx-unexpected-form-data.txt
+++ b/lib/lp/bugs/stories/bugtask-searches/xx-unexpected-form-data.txt
@@ -4,14 +4,12 @@ is raised.
 
     >>> browser.open(
     ...     "http://localhost/ubuntu/+bugs?search=Search&field.status=Fred";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.errors.UnexpectedFormData: Unexpected value for field 'status'...
 
     >>> browser.open(
     ...     "http://localhost/ubuntu/+bugs?search=Search&orderby=foobar";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.errors.UnexpectedFormData: Unknown sort column 'foobar'
@@ -19,7 +17,6 @@ is raised.
     >>> browser.open(
     ...     "http://launchpad.test/firefox/+bugs?";
     ...     "field.status_upstream=hide_open")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.errors.UnexpectedFormData: Unexpected value for field 'status_upstream'...
diff --git a/lib/lp/bugs/stories/bugtracker/xx-bugtracker-handshake-tokens.txt b/lib/lp/bugs/stories/bugtracker/xx-bugtracker-handshake-tokens.txt
index 7857961..7d7561c 100644
--- a/lib/lp/bugs/stories/bugtracker/xx-bugtracker-handshake-tokens.txt
+++ b/lib/lp/bugs/stories/bugtracker/xx-bugtracker-handshake-tokens.txt
@@ -21,7 +21,6 @@ error if we attempt it as a GET request.
     ...     token_string)
 
     >>> anon_browser.open(token_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     urllib.error.HTTPError: HTTP Error 405: Method Not Allowed
diff --git a/lib/lp/bugs/stories/bugtracker/xx-bugtracker-remote-bug.txt b/lib/lp/bugs/stories/bugtracker/xx-bugtracker-remote-bug.txt
index 0e9753f..81fdee9 100644
--- a/lib/lp/bugs/stories/bugtracker/xx-bugtracker-remote-bug.txt
+++ b/lib/lp/bugs/stories/bugtracker/xx-bugtracker-remote-bug.txt
@@ -40,7 +40,6 @@ Found page is generated:
 
     >>> browser.handleErrors = True
     >>> browser.open('http://launchpad.test/bugs/bugtrackers/mozilla.org/99999')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     urllib.error.HTTPError: HTTP Error 404: Not Found
@@ -96,7 +95,6 @@ user logs in):
 
     >>> anon_browser.open(
     ...     'http://bugs.launchpad.test/bugs/bugtrackers/mozilla.org/2000')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/bugs/stories/cve/cve-linking.txt b/lib/lp/bugs/stories/cve/cve-linking.txt
index bdd98f7..2967f58 100644
--- a/lib/lp/bugs/stories/cve/cve-linking.txt
+++ b/lib/lp/bugs/stories/cve/cve-linking.txt
@@ -16,7 +16,6 @@ This link is only available to registered user:
 
     >>> anon_browser.open('http://launchpad.test/bugs/cve/2005-2737')
     >>> anon_browser.getLink(url='+linkbug').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/bugs/stories/feeds/xx-bug-atom.txt b/lib/lp/bugs/stories/feeds/xx-bug-atom.txt
index 86f2876..2d615ed 100644
--- a/lib/lp/bugs/stories/feeds/xx-bug-atom.txt
+++ b/lib/lp/bugs/stories/feeds/xx-bug-atom.txt
@@ -509,7 +509,6 @@ performance problem in production.
     ...     """
     >>> config.push('bug_search_feed_data', bug_search_feed_data)
     >>> browser.open(url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: Bug search feed deactivated
diff --git a/lib/lp/bugs/stories/feeds/xx-bug-html.txt b/lib/lp/bugs/stories/feeds/xx-bug-html.txt
index ccf57cb..510e91a 100644
--- a/lib/lp/bugs/stories/feeds/xx-bug-html.txt
+++ b/lib/lp/bugs/stories/feeds/xx-bug-html.txt
@@ -201,7 +201,7 @@ performance problem in production.
     ...     is_bug_search_feed_active: False
     ...     """
     >>> config.push('bug_search_feed_data', bug_search_feed_data)
-    >>> browser.open(url)  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> browser.open(url)
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: Bug search feed deactivated
diff --git a/lib/lp/bugs/stories/patches-view/patches-view.txt b/lib/lp/bugs/stories/patches-view/patches-view.txt
index d8fd8f6..6644208 100644
--- a/lib/lp/bugs/stories/patches-view/patches-view.txt
+++ b/lib/lp/bugs/stories/patches-view/patches-view.txt
@@ -201,7 +201,6 @@ importance and status.
 But we can't sort by things that aren't validated by the view.
 
     >>> anon_browser.open('http://bugs.launchpad.test/patchy-product-1/+patches?orderby=star-sign')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: Unexpected value for field 'orderby': 'star-sign'
diff --git a/lib/lp/bugs/stories/upstream-bugprivacy/xx-upstream-bug-privacy.txt b/lib/lp/bugs/stories/upstream-bugprivacy/xx-upstream-bug-privacy.txt
index 6160429..adfcedf 100644
--- a/lib/lp/bugs/stories/upstream-bugprivacy/xx-upstream-bug-privacy.txt
+++ b/lib/lp/bugs/stories/upstream-bugprivacy/xx-upstream-bug-privacy.txt
@@ -71,7 +71,6 @@ fails, because we pretend that inaccessible private bugs do not exist.
     >>> browser = setupBrowser()
     >>> browser.open(
     ...     "http://launchpad.test/firefox/+bug/%s/+editstatus"; % bug_id)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
@@ -82,7 +81,6 @@ on which the no-privs is not an explicit subscriber.
     >>> browser = setupBrowser(auth="Basic no-priv@xxxxxxxxxxxxx:test")
     >>> browser.open(
     ...     "http://launchpad.test/firefox/+bug/%s/+editstatus"; % bug_id)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt b/lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt
index 52f4fb7..3ebcac5 100644
--- a/lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt
+++ b/lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt
@@ -216,7 +216,6 @@ Note that the "CVE reports" link is not shown above; distribution
 source packages do not have a CVE reports page.
 
     >>> print(user_browser.getLink('CVE report').url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -289,7 +288,6 @@ Note that the "CVE reports" link is not shown above; source packages
 do not have a CVE reports page.
 
     >>> print(user_browser.getLink('CVE report').url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -362,7 +360,6 @@ Note that the "CVE reports" link is not shown above; project groups do
 not have a CVE reports page.
 
     >>> print(user_browser.getLink('CVE report').url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/bugs/tests/buglinktarget.txt b/lib/lp/bugs/tests/buglinktarget.txt
index 119c94e..305fa6a 100644
--- a/lib/lp/bugs/tests/buglinktarget.txt
+++ b/lib/lp/bugs/tests/buglinktarget.txt
@@ -78,7 +78,7 @@ Of course, if no new link is created, no events should be fired:
 Anonymous users cannot use linkBug():
 
     >>> login(ANONYMOUS)
-    >>> target.linkBug(bug2)  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> target.linkBug(bug2)
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
@@ -91,7 +91,6 @@ if they are an administrator:
     >>> private_bug.setPrivate(True, factory.makePerson())
     True
     >>> target.linkBug(private_bug, factory.makePerson())
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
@@ -121,7 +120,6 @@ This method is only available to registered users:
 
     >>> login(ANONYMOUS)
     >>> target.unlinkBug(bug2, None)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
@@ -164,7 +162,6 @@ A user can only remove a link to a private bug if they are subscribed to
 the bug or if they are an administrator.
 
     >>> target.unlinkBug(private_bug)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/bugs/tests/bugs-emailinterface.txt b/lib/lp/bugs/tests/bugs-emailinterface.txt
index b3e2402..452b6bf 100644
--- a/lib/lp/bugs/tests/bugs-emailinterface.txt
+++ b/lib/lp/bugs/tests/bugs-emailinterface.txt
@@ -430,7 +430,6 @@ IWeaklyAuthenticatedPrincipal was provided by the current principal, no
 changes was made to the bug, and the comment wasn't added.
 
     >>> added_message = getUtility(IMessageSet).get('<yada-yada-test2>')[0]
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...
@@ -465,7 +464,6 @@ The same will happen if we send the same email without signing it:
     >>> transaction.commit()
 
     >>> added_message = getUtility(IMessageSet).get('<yada-yada-test2>')[0]
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...
diff --git a/lib/lp/bugs/tests/bugzilla-api-xmlrpc-transport.txt b/lib/lp/bugs/tests/bugzilla-api-xmlrpc-transport.txt
index 2d3cad2..ce0f317 100644
--- a/lib/lp/bugs/tests/bugzilla-api-xmlrpc-transport.txt
+++ b/lib/lp/bugs/tests/bugzilla-api-xmlrpc-transport.txt
@@ -52,7 +52,6 @@ an error being raised.
 
     >>> server.User.login(
     ...     {'login': 'test@xxxxxxxxxxxxx', 'password': 'test'})
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     xmlrpc.client.Fault: <Fault 300: 'The username or password you entered is not valid.'>
@@ -455,7 +454,6 @@ add_comment() requires authentication.
 
     >>> bugzilla_transport.expireCookie(bugzilla_transport.auth_cookie)
     >>> server.Bug.add_comment({'id': 1, 'comment': "This won't work"})
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     xmlrpc.client.Fault: <Fault 410: 'Login Required'>
@@ -492,7 +490,6 @@ If add_comment is called on a bug that doesn't exist a fault will be
 raised.
 
     >>> server.Bug.add_comment({'id': 42, 'comment': "This breaks"})
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     xmlrpc.client.Fault: <Fault 101: 'Bug #42 does not exist.'>
@@ -545,7 +542,6 @@ Trying to add a non Bugzilla or Launchpad URL will raise a Fault.
 
     >>> server.Bug.update_see_also({
     ...     'ids': [1], 'add': ['http://example.com/fail']});
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     xmlrpc.client.Fault: <Fault 112: 'Bug URL http://example.com/fail is invalid.'>
diff --git a/lib/lp/bugs/tests/bugzilla-xmlrpc-transport.txt b/lib/lp/bugs/tests/bugzilla-xmlrpc-transport.txt
index f7f7027..445dbc6 100644
--- a/lib/lp/bugs/tests/bugzilla-xmlrpc-transport.txt
+++ b/lib/lp/bugs/tests/bugzilla-xmlrpc-transport.txt
@@ -51,7 +51,6 @@ Authentication
 Some methods require authentication.
 
     >>> server.Test.login_required()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     xmlrpc.client.Fault: <Fault 410: 'Login Required'>
@@ -439,7 +438,6 @@ add_comment() requires authentication.
 
     >>> bugzilla_transport.expireCookie(bugzilla_transport.auth_cookie)
     >>> server.Launchpad.add_comment({'id': 1, 'comment': "This won't work"})
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     xmlrpc.client.Fault: <Fault 410: 'Login Required'>
@@ -471,7 +469,6 @@ If add_comment is called on a bug that doesn't exist a fault will be
 raised.
 
     >>> server.Launchpad.add_comment({'id': 42, 'comment': "This won't work"})
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     xmlrpc.client.Fault: <Fault 101: 'Bug #42 does not exist.'>
@@ -489,7 +486,6 @@ Launchpad.set_link() requires authentication.
 
     >>> bugzilla_transport.expireCookie(bugzilla_transport.auth_cookie)
     >>> server.Launchpad.set_link({'id': 1, 'launchpad_id': 1})
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     xmlrpc.client.Fault: <Fault 410: 'Login Required'>
diff --git a/lib/lp/bugs/tests/externalbugtracker-xmlrpc-transport.txt b/lib/lp/bugs/tests/externalbugtracker-xmlrpc-transport.txt
index a18a9fd..53305fb 100644
--- a/lib/lp/bugs/tests/externalbugtracker-xmlrpc-transport.txt
+++ b/lib/lp/bugs/tests/externalbugtracker-xmlrpc-transport.txt
@@ -89,7 +89,6 @@ If an error occurs trying to make the request, an
     ...     requests_mock.add(
     ...         'POST', 'http://www.example.com/xmlrpc', status=500)
     ...     transport.request('www.example.com', 'xmlrpc', request_body)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     xmlrpc.client.ProtocolError: <ProtocolError for http://www.example.com/xmlrpc: 500 Internal Server Error>
diff --git a/lib/lp/bugs/tests/trac-xmlrpc-transport.txt b/lib/lp/bugs/tests/trac-xmlrpc-transport.txt
index 7f52f95..8703cb3 100644
--- a/lib/lp/bugs/tests/trac-xmlrpc-transport.txt
+++ b/lib/lp/bugs/tests/trac-xmlrpc-transport.txt
@@ -16,7 +16,6 @@ installed implement.
 All the methods need an authentication cookie to be sent.
 
     >>> server.launchpad.bugtracker_version()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     xmlrpc.client.ProtocolError: <... 403 Forbidden>
@@ -315,7 +314,6 @@ Calling `launchpad.get_launchpad_bug()` on a remote bug that doesn't
 exist will result in a Fault being raised.
 
     >>> trac_transport.get_launchpad_bug('12345')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     xmlrpc.client.Fault: <Fault 1001: 'Ticket does not exist'>
@@ -341,7 +339,6 @@ Trying to call `launchpad.set_launchpad_bug()` on a remote bug that
 doesn't exist will result in a Fault.
 
     >>> trac_transport.set_launchpad_bug('12345', 1)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     xmlrpc.client.Fault: <Fault 1001: 'Ticket does not exist'>
diff --git a/lib/lp/buildmaster/doc/builder.txt b/lib/lp/buildmaster/doc/builder.txt
index e3620e9..af1c423 100644
--- a/lib/lp/buildmaster/doc/builder.txt
+++ b/lib/lp/buildmaster/doc/builder.txt
@@ -64,7 +64,6 @@ And also by ID.
     >>> print(builderset.get(2).name)
     frog
     >>> print(builderset.get(100).name)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: 100
diff --git a/lib/lp/buildmaster/stories/xx-builder-page.txt b/lib/lp/buildmaster/stories/xx-builder-page.txt
index 65ded43..3082ddb 100644
--- a/lib/lp/buildmaster/stories/xx-builder-page.txt
+++ b/lib/lp/buildmaster/stories/xx-builder-page.txt
@@ -266,7 +266,6 @@ Farm list. Celso cannot see the link to it.
     386          1        empty
 
     >>> cprov_browser.getLink('bob').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -286,7 +285,6 @@ Change details link.
 
     >>> user_browser.open("http://localhost/+builds/bob";)
     >>> user_browser.getLink('Change details')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     zope.testbrowser.browser.LinkNotFoundError
 
@@ -299,7 +297,6 @@ Nor is the toggle mode control included on the index page.
 Nor can they access the edit page directly via URL.
 
     >>> user_browser.open("http://localhost/+builds/bob/+edit";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -308,7 +305,6 @@ The same is true for the anonymous user:
 
     >>> anon_browser.open("http://localhost/+builds/bob";)
     >>> anon_browser.getLink('Change details')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     zope.testbrowser.browser.LinkNotFoundError
 
@@ -318,7 +314,6 @@ The same is true for the anonymous user:
     ...
 
     >>> anon_browser.open("http://localhost/+builds/bob/+edit";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/buildmaster/stories/xx-buildfarm-index.txt b/lib/lp/buildmaster/stories/xx-buildfarm-index.txt
index 16932a5..9b77408 100644
--- a/lib/lp/buildmaster/stories/xx-buildfarm-index.txt
+++ b/lib/lp/buildmaster/stories/xx-buildfarm-index.txt
@@ -110,13 +110,11 @@ and are not permitted if they go directly to the URL.
 
     >>> anon_browser.open("http://launchpad.test/+builds/+index";)
     >>> anon_browser.getLink("Register a new build machine")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> anon_browser.open("http://launchpad.test/+builds/+new";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ..., 'launchpad.Admin')
diff --git a/lib/lp/code/doc/branch.txt b/lib/lp/code/doc/branch.txt
index 9f8e8aa..0334752 100644
--- a/lib/lp/code/doc/branch.txt
+++ b/lib/lp/code/doc/branch.txt
@@ -120,7 +120,6 @@ are writable, but the owner can be set using the `setOwner` method.
 
     >>> login('admin@xxxxxxxxxxxxx')
     >>> new_branch.registrant = factory.makePerson()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.ForbiddenAttribute: ('registrant', <Branch ...>)
@@ -140,7 +139,6 @@ and -, +, _ and @ are allowed after that.
     >>> namespace.createBranch(
     ...     branch_type=BranchType.HOSTED, name='invalid name!',
     ...     registrant=registrant)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.validators.LaunchpadValidationError: Invalid branch name &#x27;invalid name!&#x27;.  Branch ...
diff --git a/lib/lp/code/doc/codeimport-machine.txt b/lib/lp/code/doc/codeimport-machine.txt
index e24d9b6..6a963e6 100644
--- a/lib/lp/code/doc/codeimport-machine.txt
+++ b/lib/lp/code/doc/codeimport-machine.txt
@@ -107,7 +107,6 @@ permitted.
     OFFLINE
 
     >>> new_machine.state = CodeImportMachineState.ONLINE
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.ForbiddenAttribute: ...
diff --git a/lib/lp/code/doc/codeimport.txt b/lib/lp/code/doc/codeimport.txt
index c12d96b..f6770f0 100644
--- a/lib/lp/code/doc/codeimport.txt
+++ b/lib/lp/code/doc/codeimport.txt
@@ -430,7 +430,6 @@ When you ask for an id that is not present ICodeImportSet.get() raises
 lp.app.errors.NotFoundError, rather than some internal database exception.
 
     >>> code_import_set.get(-10)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.errors.NotFoundError: -10
@@ -471,7 +470,6 @@ on those objects.
     >>> print(svn_import.url)
     svn://svn.example.com/trunk
     >>> svn_import.url = 'svn://svn.example.com/branch/1.0'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.ForbiddenAttribute: ('url', <CodeImport ...>)
@@ -497,7 +495,6 @@ The launchpad.Edit privilege is required to use CodeImport.updateFromData.
 
     >>> login(ANONYMOUS)
     >>> svn_import.updateFromData({}, nopriv)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (<CodeImport ...>, 'updateFromData', 'launchpad.Moderate')
diff --git a/lib/lp/code/stories/branches/xx-branch-edit.txt b/lib/lp/code/stories/branches/xx-branch-edit.txt
index f493201..7498979 100644
--- a/lib/lp/code/stories/branches/xx-branch-edit.txt
+++ b/lib/lp/code/stories/branches/xx-branch-edit.txt
@@ -32,7 +32,6 @@ owner, Launchpad administrators or members of the Bazaar Experts team.
     >>> nopriv_browser.open(
     ...     'http://code.launchpad.test/~name12/gnome-terminal/klingon')
     >>> link = nopriv_browser.getLink('Change branch details')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     zope.testbrowser.browser.LinkNotFoundError
 
diff --git a/lib/lp/code/stories/branches/xx-branch-reference.txt b/lib/lp/code/stories/branches/xx-branch-reference.txt
index 31fba80..a308c33 100644
--- a/lib/lp/code/stories/branches/xx-branch-reference.txt
+++ b/lib/lp/code/stories/branches/xx-branch-reference.txt
@@ -56,7 +56,6 @@ a 404 error:
 
     >>> anon_browser.open('http://launchpad.test/'
     ...                   'firefox/1.0/.bzr/branch/location')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ... '.bzr'
@@ -80,7 +79,6 @@ associated with it, we get a 404 error:
 
     >>> anon_browser.open('http://launchpad.test/'
     ...                   'firefox/.bzr/branch/location')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.publisher.interfaces.NotFound: ... '.bzr'
diff --git a/lib/lp/code/stories/branches/xx-branchmergeproposals.txt b/lib/lp/code/stories/branches/xx-branchmergeproposals.txt
index 798c6d0..882a87e 100644
--- a/lib/lp/code/stories/branches/xx-branchmergeproposals.txt
+++ b/lib/lp/code/stories/branches/xx-branchmergeproposals.txt
@@ -196,7 +196,6 @@ People not logged in cannot perform reviews.
 
     >>> anon_browser.open(klingon_proposal)
     >>> link = anon_browser.getLink('[Review]')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     zope.testbrowser.browser.LinkNotFoundError
 
@@ -529,7 +528,6 @@ shown for junk branches.
     >>> nopriv_browser.open(
     ...     'http://code.launchpad.test/~mark/+junk/testdoc')
     >>> nopriv_browser.getLink('Propose for merging').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -539,7 +537,6 @@ they'll get a 404.
 
     >>> nopriv_browser.open(
     ...     'http://code.launchpad.test/~mark/+junk/testdoc/+register-merge')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/code/stories/branches/xx-bug-branch-links.txt b/lib/lp/code/stories/branches/xx-bug-branch-links.txt
index f7462e8..3661261 100644
--- a/lib/lp/code/stories/branches/xx-bug-branch-links.txt
+++ b/lib/lp/code/stories/branches/xx-bug-branch-links.txt
@@ -19,7 +19,6 @@ if the user is not logged in, they will be asked to log in.
     >>> anon_browser.open(
     ...     'http://code.launchpad.test/~name12/gnome-terminal/klingon')
     >>> anon_browser.getLink('Link a bug report').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (...launchpad.AnyPerson')
@@ -106,7 +105,6 @@ links to a page restricted with the launchpad.AnyPerson permission.
     >>> anon_browser.open(
     ...     'http://launchpad.test/bugs/11')
     >>> anon_browser.getLink('Link a related branch').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (...launchpad.AnyPerson')
diff --git a/lib/lp/code/stories/branches/xx-code-review-comments.txt b/lib/lp/code/stories/branches/xx-code-review-comments.txt
index 9cc4178..0d075f6 100644
--- a/lib/lp/code/stories/branches/xx-code-review-comments.txt
+++ b/lib/lp/code/stories/branches/xx-code-review-comments.txt
@@ -55,7 +55,6 @@ The person's name links back to the main site for that person.
 Reply link is displayed even if the user isn't logged in.
 
     >>> anon_browser.getLink('Reply').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     zope.security.interfaces.Unauthorized: ...
 
diff --git a/lib/lp/code/stories/branches/xx-subscribing-branches.txt b/lib/lp/code/stories/branches/xx-subscribing-branches.txt
index f240f47..1974c42 100644
--- a/lib/lp/code/stories/branches/xx-subscribing-branches.txt
+++ b/lib/lp/code/stories/branches/xx-subscribing-branches.txt
@@ -28,7 +28,6 @@ In order to subscribe to a branch, the user must be logged in.
     >>> anon_browser.open(
     ...     'http://code.launchpad.test/~name12/gnome-terminal/main')
     >>> anon_browser.getLink('Subscribe')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -148,7 +147,6 @@ You need to be logged in to see the link.
     >>> anon_browser.open(
     ...     'http://code.launchpad.test/~name12/gnome-terminal/main')
     >>> anon_browser.getLink('Subscribe someone else')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/code/stories/branches/xx-upgrading-branches.txt b/lib/lp/code/stories/branches/xx-upgrading-branches.txt
index a824a94..042804c 100644
--- a/lib/lp/code/stories/branches/xx-upgrading-branches.txt
+++ b/lib/lp/code/stories/branches/xx-upgrading-branches.txt
@@ -32,7 +32,6 @@ Only those with edit permissions on a branch can request an upgrade.
     ...     auth='Basic nopriv@xxxxxxxxxxxxx:test')
     >>> nopriv_browser.open(branch_url)
     >>> link = nopriv_browser.getLink('Upgrade this branch')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     zope.testbrowser.browser.LinkNotFoundError
 
diff --git a/lib/lp/code/stories/codeimport/xx-create-codeimport.txt b/lib/lp/code/stories/codeimport/xx-create-codeimport.txt
index 93de21b..9f338f0 100644
--- a/lib/lp/code/stories/codeimport/xx-create-codeimport.txt
+++ b/lib/lp/code/stories/codeimport/xx-create-codeimport.txt
@@ -32,7 +32,6 @@ link on the main branch listing page for the product.
 
     >>> browser.open('http://code.launchpad.test/firefox')
     >>> browser.getLink('Import a branch').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/code/stories/codeimport/xx-edit-codeimport.txt b/lib/lp/code/stories/codeimport/xx-edit-codeimport.txt
index 622a63f..f11fc01 100644
--- a/lib/lp/code/stories/codeimport/xx-edit-codeimport.txt
+++ b/lib/lp/code/stories/codeimport/xx-edit-codeimport.txt
@@ -54,7 +54,6 @@ do not get an Edit link.
 Because it's an svn:// URL, it doesn't get linkified:
 
     >>> anon_browser.getLink("svn://svn.example.com/fooix/trunk")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -68,12 +67,10 @@ they will get a not authorised page if the branch has a code import,
 and a 404 if the branch doesn't have an import.
 
     >>> anon_browser.open(svn_import_location + '/+edit-import')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     zope.security.interfaces.Unauthorized: (... 'launchpad.Edit')
 
     >>> admin_browser.open(hosted_branch_location + '/+edit-import')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     lp.app.errors.NotFoundError
 
diff --git a/lib/lp/coop/answersbugs/stories/question-buglink.txt b/lib/lp/coop/answersbugs/stories/question-buglink.txt
index c5c71f8..764bbd2 100644
--- a/lib/lp/coop/answersbugs/stories/question-buglink.txt
+++ b/lib/lp/coop/answersbugs/stories/question-buglink.txt
@@ -17,7 +17,6 @@ This link is only available to registered user:
     >>> anon_browser.open(
     ...     'http://launchpad.test/firefox/+question/2')
     >>> anon_browser.getLink(url='+linkbug').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/coop/answersbugs/stories/question-makebug.txt b/lib/lp/coop/answersbugs/stories/question-makebug.txt
index 34bf516..0399135 100644
--- a/lib/lp/coop/answersbugs/stories/question-makebug.txt
+++ b/lib/lp/coop/answersbugs/stories/question-makebug.txt
@@ -66,7 +66,6 @@ to it.
     >>> browser.contents
     '...<h3>Related bugs</h3>...'
     >>> browser.getLink('Create bug report')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/browser/tests/gpg-views.txt b/lib/lp/registry/browser/tests/gpg-views.txt
index 7682722..dcb4257 100644
--- a/lib/lp/registry/browser/tests/gpg-views.txt
+++ b/lib/lp/registry/browser/tests/gpg-views.txt
@@ -133,7 +133,6 @@ validation.
 In some unknown way, the action sent to the form can be None (see bug 520476).
 
     >>> view = post_fingerprint(good_fingerprint, action=None)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     lp.app.errors.UnexpectedFormData: Action not permitted: None
diff --git a/lib/lp/registry/browser/tests/product-views.txt b/lib/lp/registry/browser/tests/product-views.txt
index 0f567b4..fca5d24 100644
--- a/lib/lp/registry/browser/tests/product-views.txt
+++ b/lib/lp/registry/browser/tests/product-views.txt
@@ -126,7 +126,6 @@ cannot access the page.
     >>> view = create_initialized_view(firefox, name='+index')
 
     >>> view = create_initialized_view(firefox, name='+review-license')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (<Product..., 'project_reviewed', 'launchpad.Moderate')
diff --git a/lib/lp/registry/browser/tests/team-views.txt b/lib/lp/registry/browser/tests/team-views.txt
index 07232ef..9af0adb 100644
--- a/lib/lp/registry/browser/tests/team-views.txt
+++ b/lib/lp/registry/browser/tests/team-views.txt
@@ -61,7 +61,6 @@ Posting malformed data to the team home page raises an error.
     >>> team_home = getMultiAdapter(
     ...     (ubuntu_team, broken_request), name='+index')
     >>> team_home.initialize()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: The mailing list form did not receive the expected form fields.
diff --git a/lib/lp/registry/doc/announcement.txt b/lib/lp/registry/doc/announcement.txt
index 0287d58..e916ec3 100644
--- a/lib/lp/registry/doc/announcement.txt
+++ b/lib/lp/registry/doc/announcement.txt
@@ -187,17 +187,14 @@ modify() method.
 
     >>> login('mark@xxxxxxxxxxx')
     >>> kubuntu_release.title = 'Foo'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.ForbiddenAttribute: ...
     >>> kubuntu_release.summary = 'Foo'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.ForbiddenAttribute: ...
     >>> kubuntu_release.url = 'http://Foo.com/foo'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.ForbiddenAttribute: ...
diff --git a/lib/lp/registry/doc/commercialsubscription.txt b/lib/lp/registry/doc/commercialsubscription.txt
index 3a60b44..851b264 100644
--- a/lib/lp/registry/doc/commercialsubscription.txt
+++ b/lib/lp/registry/doc/commercialsubscription.txt
@@ -357,7 +357,6 @@ No Privileges Person cannot access 'forReview'.
     >>> check_permission('launchpad.Moderate', product_set)
     False
     >>> gnome =  product_set.forReview(commercial_member, search_text='gnome')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ... 'forReview', 'launchpad.Moderate'...
diff --git a/lib/lp/registry/doc/distribution-mirror.txt b/lib/lp/registry/doc/distribution-mirror.txt
index c9f1a6c..0b39afc 100644
--- a/lib/lp/registry/doc/distribution-mirror.txt
+++ b/lib/lp/registry/doc/distribution-mirror.txt
@@ -912,7 +912,6 @@ Only mirrors which have never been probed can be deleted this way.
 
     >>> ignored = login_person(cdimage_mirror.owner)
     >>> cdimage_mirror.destroySelf()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -960,7 +959,6 @@ for the status, however, they may not change it:
     >>> de_archive_mirror.canTransitionToCountryMirror()
     True
     >>> de_archive_mirror.transitionToCountryMirror(True)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (<DistributionMirror at ...>, 'transitionToCountryMirror', 'launchpad.Admin')
@@ -1002,7 +1000,6 @@ There cannot be multiple country mirrors of one type for one country:
 
     >>> davis_station_archive.transitionToCountryMirror(True)
     >>> archive_mirror2.transitionToCountryMirror(True)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.registry.errors.CountryMirrorAlreadySet: Antarctica already has a country Archive mirror set.
@@ -1015,7 +1012,6 @@ Mirrors which have not been probed may not be marked as country mirrors:
     ...     official_candidate=True)
     >>> linux_au_mirror.status = MirrorStatus.OFFICIAL
     >>> linux_au_mirror.transitionToCountryMirror(True)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.registry.errors.MirrorNotProbed: This mirror may not be set as a country mirror as it has not been probed.
@@ -1036,13 +1032,11 @@ country mirrors:
     False
 
     >>> osuosl_mirror.transitionToCountryMirror(None)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     storm.exceptions.NoneError: None isn't acceptable as a value for DistributionMirror.country_dns_mirror
 
     >>> osuosl_mirror.transitionToCountryMirror(True)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.registry.errors.MirrorHasNoHTTPURL: This mirror may not be set as a country mirror as it does not have an HTTP URL set.
diff --git a/lib/lp/registry/doc/distribution.txt b/lib/lp/registry/doc/distribution.txt
index d9dcd94..dc2941b 100644
--- a/lib/lp/registry/doc/distribution.txt
+++ b/lib/lp/registry/doc/distribution.txt
@@ -308,7 +308,6 @@ Distribution can do that for us.
 
 If we ask for a totally unknown distroseries, we raise NotFoundError
     >>> ubuntu.getDistroSeriesAndPocket('unknown')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...'unknown'
@@ -339,7 +338,6 @@ Find the backports pocket, too:
 If we ask for a valid distroseries which doesn't have a given pocket it should
 raise NotFoundError for us
     >>> ubuntu.getDistroSeriesAndPocket('hoary-bullshit')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...'hoary-bullshit'
@@ -469,15 +467,12 @@ But others can't.
 
     >>> login('no-priv@xxxxxxxxxxxxx')
     >>> debian.blueprints_usage = ServiceUsage.LAUNCHPAD
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     zope.security.interfaces.Unauthorized: (..., 'blueprints_usage', 'launchpad.Edit')
     >>> debian.official_malone = True
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     zope.security.interfaces.Unauthorized: (..., 'official_malone', 'launchpad.Edit')
     >>> debian.translations_usage = ServiceUsage.LAUNCHPAD
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     zope.security.interfaces.Unauthorized: (..., 'translations_usage', 'launchpad.TranslationsAdmin')
 
@@ -595,7 +590,6 @@ Milestones for distros can only be created by distro owners or admins.
     >>> login('no-priv@xxxxxxxxxxxxx')
     >>> woody.newMilestone(
     ...     name='impossible', dateexpected=datetime(2028, 10, 1))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (<DistroSeries ...'woody'>, 'newMilestone', 'launchpad.Edit')
diff --git a/lib/lp/registry/doc/distroseries.txt b/lib/lp/registry/doc/distroseries.txt
index b69d655..225c66d 100644
--- a/lib/lp/registry/doc/distroseries.txt
+++ b/lib/lp/registry/doc/distroseries.txt
@@ -680,7 +680,6 @@ Ubuntu driver can not create series.
     ...     name='finch', display_name='Finch', title='Ubuntu Finch',
     ...     summary='summary', description='description', version='9.06',
     ...     previous_series=warty, owner=ubuntu.driver)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/doc/karmacache.txt b/lib/lp/registry/doc/karmacache.txt
index 13c7d9f..6f367f0 100644
--- a/lib/lp/registry/doc/karmacache.txt
+++ b/lib/lp/registry/doc/karmacache.txt
@@ -55,7 +55,6 @@ NotFoundError.
 
     >>> karmacachemanager.updateKarmaValue(
     ...     new_value, person.id, bugs.id, product_id=9999)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...
diff --git a/lib/lp/registry/doc/launchpadlib/project-registry.txt.disabled b/lib/lp/registry/doc/launchpadlib/project-registry.txt.disabled
index 08aefe1..7cb5aa3 100644
--- a/lib/lp/registry/doc/launchpadlib/project-registry.txt.disabled
+++ b/lib/lp/registry/doc/launchpadlib/project-registry.txt.disabled
@@ -276,7 +276,7 @@ Attributes can be edited, but not by the anonymous user.
 
     >>> mark = lp_anon.people['mark']
     >>> firefox.driver = mark
-    >>> firefox.lp_save()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> firefox.lp_save()
     Traceback (most recent call last):
       ...
     urllib.error.HTTPError: HTTP Error 401: Unauthorized...
@@ -328,7 +328,7 @@ Changing the owner of a project can change other attributes as well.
 Read-only attributes cannot be changed.
 
     >>> firefox.registrant = nopriv
-    >>> firefox.lp_save()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> firefox.lp_save()
     Traceback (most recent call last):
       ...
     urllib.error.HTTPError: HTTP Error 400: Bad Request ... registrant_link: You tried to modify a read-only attribute...
diff --git a/lib/lp/registry/doc/milestone.txt b/lib/lp/registry/doc/milestone.txt
index 8cc820e..cd5c253 100644
--- a/lib/lp/registry/doc/milestone.txt
+++ b/lib/lp/registry/doc/milestone.txt
@@ -127,7 +127,7 @@ Now, lets test all of that for DistroSeriess too!
 Trying to retrieve a milestone that doesn't exist will raise a
 zope.exceptions.NotFoundError:
 
-    >>> milestoneset.get(-1)  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> milestoneset.get(-1)
     Traceback (most recent call last):
       ...
     lp.app.errors.NotFoundError: 'Milestone with ID -1 does not exist'
diff --git a/lib/lp/registry/doc/person-account.txt b/lib/lp/registry/doc/person-account.txt
index 3e62d40..576ab7d 100644
--- a/lib/lp/registry/doc/person-account.txt
+++ b/lib/lp/registry/doc/person-account.txt
@@ -33,7 +33,6 @@ the profile. Sample Person cannot claim it.
 
     >>> login('test@xxxxxxxxxxxxx')
     >>> matsubara.account.reactivate(comment="test")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...'launchpad.View')
@@ -138,7 +137,6 @@ even launchpad admins can use it.
 
     >>> login('mark@xxxxxxxxxxx')
     >>> foobar.deactivate(comment=comment)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...'launchpad.Special')
diff --git a/lib/lp/registry/doc/person.txt b/lib/lp/registry/doc/person.txt
index 686ef2b..21312ce 100644
--- a/lib/lp/registry/doc/person.txt
+++ b/lib/lp/registry/doc/person.txt
@@ -352,13 +352,11 @@ Non-administrators may not change a person's standing.
 
     >>> login('test@xxxxxxxxxxxxx')
     >>> lifeless.personal_standing = PersonalStanding.POOR
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
 
     >>> lifeless.personal_standing_reason = 'Such a cool guy!'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -437,7 +435,6 @@ If the given name is already in use by another team/person, an exception
 is raised.
 
     >>> personset.newTeam(ddaa, 'ddaa', 'Just a new team')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.registry.errors.NameAlreadyTaken: ...
@@ -531,7 +528,6 @@ account_status is NOACCOUNT, though.
     AssertionError: Only Person entries whose account_status is NOACCOUNT...
 
     >>> not_a_person.convertToTeam(team_owner=landscape_devs)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.registry.interfaces.person.AlreadyConvertedException: foo-... has already been converted to a team.
@@ -1443,7 +1439,6 @@ error will be raised.
     >>> person_set._newPerson(
     ...     'new-name', 'New Person', True,
     ...     PersonCreationRationale.BUGIMPORT)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.registry.errors.NameAlreadyTaken: The name 'new-name' is already taken.
@@ -1454,7 +1449,6 @@ be raised.
     >>> person_set._newPerson(
     ...     "ThisIsn'tValid", 'New Person', True,
     ...     PersonCreationRationale.BUGIMPORT)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.registry.errors.InvalidName: ThisIsn'tValid is not a valid name for a person.
diff --git a/lib/lp/registry/doc/pillar-aliases-field.txt b/lib/lp/registry/doc/pillar-aliases-field.txt
index 9ccf329..f26605e 100644
--- a/lib/lp/registry/doc/pillar-aliases-field.txt
+++ b/lib/lp/registry/doc/pillar-aliases-field.txt
@@ -29,7 +29,6 @@ to be a valid alias for that pillar, but only for that pillar.
     >>> bound_field.validate(u'iceweasel')
 
     >>> field.bind(getUtility(IProductSet)['bzr']).validate(u'iceweasel')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.validators.LaunchpadValidationError: iceweasel is already used by another project
@@ -54,13 +53,11 @@ If an empty string (or None) is given, all aliases will be removed.
 Each of these aliases must be valid names and must be unique.
 
     >>> bound_field.validate(u'names_cannot_have_underscores')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.validators.LaunchpadValidationError: Invalid name...
 
     >>> bound_field.validate(u'ubuntu')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.validators.LaunchpadValidationError: ubuntu is already used by another project
@@ -68,7 +65,6 @@ Each of these aliases must be valid names and must be unique.
 Also, they must not be identical to the pillar's own name.
 
     >>> bound_field.validate(firefox.name)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.validators.LaunchpadValidationError: This is your name: firefox
@@ -76,7 +72,6 @@ Also, they must not be identical to the pillar's own name.
 Black-listed names are not accepted as aliases either.
 
     >>> bound_field.validate(u'blacklisted')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.validators.LaunchpadValidationError: The name &#x27;blacklisted&#x27; has been blocked...
diff --git a/lib/lp/registry/doc/pillar.txt b/lib/lp/registry/doc/pillar.txt
index f27c34f..a471c21 100644
--- a/lib/lp/registry/doc/pillar.txt
+++ b/lib/lp/registry/doc/pillar.txt
@@ -36,7 +36,6 @@ share their name namespace are Product, ProjectGroup and Distribution.
     >>> 'fnord' in pillar_set
     False
     >>> pillar_set['fnord']
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...'fnord'
@@ -54,7 +53,6 @@ pillars.
     >>> 'gimp' in pillar_set
     False
     >>> pillar_set['gimp']
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...'gimp'
@@ -71,7 +69,6 @@ It also works if you use Unicode strings.
     >>> u'launchpad' in pillar_set
     False
     >>> pillar_set[u'launchpad']
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...'launchpad'
@@ -134,12 +131,10 @@ Also, if the pillar is inactive, it can't be retrieved through any of its
 aliases, in the same way that it can't be retrieved through its name.
 
     >>> pillar_set['iceweasel']
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...
     >>> pillar_set['firefox']
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...
@@ -158,7 +153,6 @@ to be able to set its aliases.
     >>> check_permission('launchpad.Edit', firefox)
     True
     >>> firefox.setAliases(['iceweasel'])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -169,7 +163,6 @@ Ditto for the Mozilla project.
     >>> check_permission('launchpad.Edit', mozilla)
     True
     >>> mozilla.setAliases(['moz'])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -181,7 +174,6 @@ And the same is true for Colin Watson on the Guadalinex distribution.
     >>> check_permission('launchpad.Edit', guadalinex)
     True
     >>> guadalinex.setAliases(['guada'])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/doc/private-team-roles.txt b/lib/lp/registry/doc/private-team-roles.txt
index 0595e4c..c764699 100644
--- a/lib/lp/registry/doc/private-team-roles.txt
+++ b/lib/lp/registry/doc/private-team-roles.txt
@@ -197,7 +197,6 @@ or private, can be the project registrant.
     >>> product = factory.makeProduct(registrant=team_owner)
     >>> product = factory.makeProduct(registrant=public_team)
     >>> product = factory.makeProduct(registrant=priv_team)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.registry.errors.PrivatePersonLinkageError: Cannot link person (name=private-team, visibility=PRIVATE) to <Product at...
diff --git a/lib/lp/registry/doc/productrelease-file-download.txt b/lib/lp/registry/doc/productrelease-file-download.txt
index 034c8ef..c1323ff 100644
--- a/lib/lp/registry/doc/productrelease-file-download.txt
+++ b/lib/lp/registry/doc/productrelease-file-download.txt
@@ -90,7 +90,6 @@ The alias can be retrieved by name.
 Attempting to retrieve an alias that does not exist is an error.
 
     >>> file_alias = rel.getFileAliasByName('bar.txt')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...'bar.txt'
@@ -105,7 +104,6 @@ Attempting to retrieve a ProductReleaseFile  that does not exist is an
 error.
 
     >>> prf = rel.getProductReleaseFileByName('bar.txt')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...'bar.txt'
@@ -116,7 +114,6 @@ delete a product file.
 
     >>> login(ANONYMOUS)
     >>> rel.files[0].destroySelf()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (<ProductReleaseFile...>, 'destroySelf', 'launchpad.Edit')
@@ -143,7 +140,6 @@ Deleting files via a GET method is not allowed.
     >>> firefox = getUtility(IProductSet).getByName('firefox')
     >>> view = getMultiAdapter((firefox,request), name='+download')
     >>> view.initialize()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     lp.services.webapp.interfaces.UnsafeFormGetSubmissionError: Delete Files
@@ -196,7 +192,6 @@ Only the product owner can create a new release.
     >>> owner_email = firefox.owner.preferredemail.email
     >>> login(ANONYMOUS)
     >>> trunk.milestones[0].createProductRelease(firefox.owner, now)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (<Milestone ...>, 'createProductRelease', 'launchpad.Edit')
diff --git a/lib/lp/registry/doc/productseries.txt b/lib/lp/registry/doc/productseries.txt
index dad7d3e..1ffd422 100644
--- a/lib/lp/registry/doc/productseries.txt
+++ b/lib/lp/registry/doc/productseries.txt
@@ -70,7 +70,6 @@ owner or driver can call Product.newSeries().
     >>> series_driver = factory.makePerson(name="driver")
     >>> summary = "Port of Firefox to the Emacs operating system."
     >>> emacs = firefox.newSeries(series_driver , 'emacs', summary)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (..., 'newSeries', 'launchpad.Driver')
@@ -166,13 +165,11 @@ that the url uses one of the supported schemes (ftp, http, http).
 Invalid URLs and unsupported schemes raise a LaunchpadValidationError.
 
     >>> validate_release_glob('ftp.gnu.org/gnu/emacs/emacs-21.*.gz')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     lp.app.validators.LaunchpadValidationError: ...
 
     >>> validate_release_glob('wais://ftp.gnu.org/gnu/emacs/emacs-21.*.gz')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     lp.app.validators.LaunchpadValidationError: ...
@@ -180,7 +177,6 @@ Invalid URLs and unsupported schemes raise a LaunchpadValidationError.
 The URL must contain a glob (*) or , and may contain more than one.
 
     >>> validate_release_glob('http://ftp.gnu.org/gnu/emacs/emacs-21.10.1.gz')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     lp.app.validators.LaunchpadValidationError: ...
diff --git a/lib/lp/registry/doc/projectgroup.txt b/lib/lp/registry/doc/projectgroup.txt
index e880792..1eb00f9 100644
--- a/lib/lp/registry/doc/projectgroup.txt
+++ b/lib/lp/registry/doc/projectgroup.txt
@@ -79,7 +79,6 @@ If there is no project with the specified name, a NotFoundError will be
 raised.
 
     >>> projectset['non-existant']
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...
@@ -96,7 +95,6 @@ the project.
 
 
     >>> gnome = getUtility(IProjectGroupSet)['gnome']
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...
diff --git a/lib/lp/registry/doc/teammembership-email-notification.txt b/lib/lp/registry/doc/teammembership-email-notification.txt
index 218334c..3a60458 100644
--- a/lib/lp/registry/doc/teammembership-email-notification.txt
+++ b/lib/lp/registry/doc/teammembership-email-notification.txt
@@ -1008,7 +1008,6 @@ membership statues silently.
 
     >>> setStatus(stevea_ubuntu_team_membership,
     ...     TeamMembershipStatus.DEACTIVATED, reviewer=kamion, silent=True)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     lp.registry.errors.UserCannotChangeMembershipSilently: ...
 
diff --git a/lib/lp/registry/doc/teammembership.txt b/lib/lp/registry/doc/teammembership.txt
index 58cffd2..e55a1d6 100644
--- a/lib/lp/registry/doc/teammembership.txt
+++ b/lib/lp/registry/doc/teammembership.txt
@@ -99,7 +99,6 @@ given team.
     True
     >>> ignored = login_person(salgado)
     >>> salgado.join(launchpad)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.registry.errors.JoinNotAllowed: This is a restricted team
@@ -153,7 +152,6 @@ to a team.
     >>> mark = personset.getByName('mark')
     >>> t3.addMember(salgado, reviewer=mark,
     ...     status=TeamMembershipStatus.ADMIN)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -512,13 +510,11 @@ an extra check to ensure that doesn't happen.
     >>> ignored = login_person(foobar)
     >>> membership = foobar.team_memberships[0]
     >>> membership.status = None
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ...
 
     >>> membership.dateexpires = None
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ...
@@ -726,7 +722,6 @@ The member themselves can't change the expiration date of their membership.
 
     >>> ignored = login_person(karl)
     >>> karl_on_mirroradmins.setExpirationDate(tomorrow, karl)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/doc/vocabularies.txt b/lib/lp/registry/doc/vocabularies.txt
index 127ad1a..9bc4dc0 100644
--- a/lib/lp/registry/doc/vocabularies.txt
+++ b/lib/lp/registry/doc/vocabularies.txt
@@ -150,7 +150,6 @@ display name.
 You cannot get a term by an other object, such as a team.
 
     >>> list_vocabulary.getTerm(team_one)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ...
@@ -183,7 +182,6 @@ You are not allowed to ask whether a non-mailing list object is
 contained in this vocabulary.
 
     >>> team_three in list_vocabulary
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ...
diff --git a/lib/lp/registry/model/projectgroup.py b/lib/lp/registry/model/projectgroup.py
index b56499a..433851f 100644
--- a/lib/lp/registry/model/projectgroup.py
+++ b/lib/lp/registry/model/projectgroup.py
@@ -543,7 +543,6 @@ class ProjectGroupSet:
         apache
         >>> getUtility(IProjectGroupSet).get(-1)
         ... # doctest: +NORMALIZE_WHITESPACE
-        ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
         Traceback (most recent call last):
         ...
         lp.app.errors.NotFoundError: -1
diff --git a/lib/lp/registry/stories/announcements/xx-announcements.txt b/lib/lp/registry/stories/announcements/xx-announcements.txt
index 9296fb6..c683ffe 100644
--- a/lib/lp/registry/stories/announcements/xx-announcements.txt
+++ b/lib/lp/registry/stories/announcements/xx-announcements.txt
@@ -42,28 +42,24 @@ page.
 
     >>> anon_browser.open('http://launchpad.test/firefox')
     >>> anon_browser.getLink('Make announcement')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> anon_browser.getLink('Read all announcements').click()
     >>> anon_browser.getLink('Make announcement')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> anon_browser.open('http://launchpad.test/ubuntu')
     >>> anon_browser.getLink('Make announcement')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> anon_browser.getLink('Read all announcements').click()
     >>> anon_browser.getLink('Make announcement')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -75,14 +71,12 @@ pillar.
     >>> nopriv_browser = setupBrowser(auth="Basic no-priv@xxxxxxxxxxxxx:test")
     >>> nopriv_browser.open('http://launchpad.test/firefox')
     >>> nopriv_browser.getLink('Make announcement')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> nopriv_browser.getLink('Read all announcements').click()
     >>> nopriv_browser.getLink('Make announcement')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -260,7 +254,6 @@ anon_browser.
     >>> priv_browser.getLink('Kubuntu announcement headline').click()
     >>> link_url = priv_browser.url
     >>> anon_browser.open(link_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/distribution/xx-distribution-launchpad-usage.txt b/lib/lp/registry/stories/distribution/xx-distribution-launchpad-usage.txt
index d3b4045..5a06d50 100644
--- a/lib/lp/registry/stories/distribution/xx-distribution-launchpad-usage.txt
+++ b/lib/lp/registry/stories/distribution/xx-distribution-launchpad-usage.txt
@@ -9,17 +9,14 @@ details.
 
     >>> user_browser.open('http://launchpad.test/ubuntu')
     >>> user_browser.getLink('Change details')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.getLink('Configure publisher')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.open('http://launchpad.test/ubuntu/+edit')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/distribution/xx-distribution-overview.txt b/lib/lp/registry/stories/distribution/xx-distribution-overview.txt
index 2734a8c..26d217a 100644
--- a/lib/lp/registry/stories/distribution/xx-distribution-overview.txt
+++ b/lib/lp/registry/stories/distribution/xx-distribution-overview.txt
@@ -124,7 +124,6 @@ If there is a development series alias, it becomes a redirect.
     >>> from zope.component import getUtility
 
     >>> anon_browser.open("http://launchpad.test/ubuntu/devel";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: Object: <Distribution ...>, name: 'devel'
@@ -177,13 +176,11 @@ term) or an unavailable name (only 'primary' and 'partner' exist)
 results in a NotFound error.
 
     >>> anon_browser.open("http://launchpad.test/ubuntu/+archive";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: Object: <Distribution ...>, name: '+archive'
 
     >>> anon_browser.open("http://launchpad.test/ubuntu/+archive/boing";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: Object: <Distribution ...>, name: 'boing'
diff --git a/lib/lp/registry/stories/distributionmirror/xx-distribution-countrymirrors.txt b/lib/lp/registry/stories/distributionmirror/xx-distribution-countrymirrors.txt
index 9ddcf14..b6bcddd 100644
--- a/lib/lp/registry/stories/distributionmirror/xx-distribution-countrymirrors.txt
+++ b/lib/lp/registry/stories/distributionmirror/xx-distribution-countrymirrors.txt
@@ -61,7 +61,6 @@ Also, the +countrymirrors-archive page is only available for the Ubuntu
 distribution.
 
     >>> browser.open('http://launchpad.test/debian/+countrymirrors-archive')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     urllib.error.HTTPError: HTTP Error 404: Not Found
diff --git a/lib/lp/registry/stories/distributionmirror/xx-distribution-mirrors.txt b/lib/lp/registry/stories/distributionmirror/xx-distribution-mirrors.txt
index bdeeb63..48068d4 100644
--- a/lib/lp/registry/stories/distributionmirror/xx-distribution-mirrors.txt
+++ b/lib/lp/registry/stories/distributionmirror/xx-distribution-mirrors.txt
@@ -80,7 +80,6 @@ they were out of date, missing some content, etc). This list can only be
 seen by distro owners, mirror admins of the distro or launchpad admins.
 
     >>> user_browser.open('http://launchpad.test/ubuntu/+disabledmirrors')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -103,7 +102,6 @@ It's only visible to distro owners, mirror admins of the distro or
 launchpad admins.
 
     >>> user_browser.open('http://launchpad.test/ubuntu/+unofficialmirrors')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -126,7 +124,6 @@ type of mirror is shown.  Also the freshness is not visible since
 pending mirrors have never been probed.
 
     >>> user_browser.open('http://launchpad.test/ubuntu/+pendingreviewmirrors')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/distributionmirror/xx-distributionmirror-prober-logs.txt b/lib/lp/registry/stories/distributionmirror/xx-distributionmirror-prober-logs.txt
index c48105d..157fb8f 100644
--- a/lib/lp/registry/stories/distributionmirror/xx-distributionmirror-prober-logs.txt
+++ b/lib/lp/registry/stories/distributionmirror/xx-distributionmirror-prober-logs.txt
@@ -23,7 +23,6 @@ A random logged in user won't have the rights to see that page.
     >>> user_browser.open(
     ...     'http://launchpad.test/ubuntu/+mirror/archive-mirror2/')
     >>> user_browser.getLink('Content check logs')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -31,7 +30,6 @@ A random logged in user won't have the rights to see that page.
     >>> user_browser.open(
     ...     'http://launchpad.test/ubuntu/+mirror/archive-mirror2/'
     ...     '+prober-logs')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/distributionmirror/xx-reassign-distributionmirror.txt b/lib/lp/registry/stories/distributionmirror/xx-reassign-distributionmirror.txt
index 75a5cd3..bef3699 100644
--- a/lib/lp/registry/stories/distributionmirror/xx-reassign-distributionmirror.txt
+++ b/lib/lp/registry/stories/distributionmirror/xx-reassign-distributionmirror.txt
@@ -15,12 +15,10 @@ permission on them. Mark is the owner of the archive-mirror.
 
     >>> user_browser.open(context_url)
     >>> user_browser.getLink('Change')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.open(context_url + "/+reassign")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/distroseries/distroseries-admin.txt b/lib/lp/registry/stories/distroseries/distroseries-admin.txt
index 051256d..8b7ce57 100644
--- a/lib/lp/registry/stories/distroseries/distroseries-admin.txt
+++ b/lib/lp/registry/stories/distroseries/distroseries-admin.txt
@@ -56,7 +56,6 @@ Registry experts do not have access to the 'Change details' link.
     ...     auth='Basic %s:test' % email)
     >>> registry_browser.open('http://launchpad.test/ubuntu/happy')
     >>> registry_browser.getLink('Change details').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -64,7 +63,6 @@ Registry experts do not have access to the 'Change details' link.
 And navigating directly to +edit is thwarted.
 
     >>> registry_browser.open('http://launchpad.test/ubuntu/happy/+edit')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/distroseries/xx-show-distroseries-packaging.txt b/lib/lp/registry/stories/distroseries/xx-show-distroseries-packaging.txt
index d491f5c..a8d9558 100644
--- a/lib/lp/registry/stories/distroseries/xx-show-distroseries-packaging.txt
+++ b/lib/lp/registry/stories/distroseries/xx-show-distroseries-packaging.txt
@@ -38,7 +38,6 @@ is linked, but the link to this page is not enabled.
       url='http://launchpad.test/ubuntu/hoary/+needs-packaging'>
 
     >>> anon_browser.getLink('All upstream links')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -118,7 +117,6 @@ linked, but the link to this page is not enabled.
       url='http://launchpad.test/ubuntu/hoary/+packaging'>
 
     >>> anon_browser.getLink('Needs upstream links')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/gpg-coc/xx-ubuntu-codeofconduct-signer.txt b/lib/lp/registry/stories/gpg-coc/xx-ubuntu-codeofconduct-signer.txt
index 13cda85..a2e403d 100644
--- a/lib/lp/registry/stories/gpg-coc/xx-ubuntu-codeofconduct-signer.txt
+++ b/lib/lp/registry/stories/gpg-coc/xx-ubuntu-codeofconduct-signer.txt
@@ -25,7 +25,6 @@ A regular user can't see the link to Foo Bar's signed codes of conduct.
     Signed Ubuntu Code of Conduct: Yes
 
     >>> browser.getLink(url='+codesofconduct')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/location/personlocation-edit.txt b/lib/lp/registry/stories/location/personlocation-edit.txt
index 14f336b..89385a5 100644
--- a/lib/lp/registry/stories/location/personlocation-edit.txt
+++ b/lib/lp/registry/stories/location/personlocation-edit.txt
@@ -13,7 +13,6 @@ A user cannot set another user's +editlocation page.
 
     >>> nopriv_browser = setupBrowser(auth="Basic no-priv@xxxxxxxxxxxxx:test")
     >>> nopriv_browser.open('http://launchpad.test/~zzz/+editlocation')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/mailinglists/lifecycle.txt b/lib/lp/registry/stories/mailinglists/lifecycle.txt
index 203f3c2..63d2ff6 100644
--- a/lib/lp/registry/stories/mailinglists/lifecycle.txt
+++ b/lib/lp/registry/stories/mailinglists/lifecycle.txt
@@ -230,7 +230,6 @@ Anonymous users cannot see the link, because they cannot even see the
 private team.
 
     >>> anon_browser.open('http://launchpad.test/~bassists')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: Object: <...>, name: '~bassists'
@@ -238,7 +237,6 @@ private team.
 The same is true for normal users who are not team members.
 
     >>> browser.open('http://launchpad.test/~bassists')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: Object: <...>, name: '~bassists'
@@ -248,7 +246,6 @@ Members who are not owners can see the link.
     >>> cprov_browser = setupBrowser(
     ...     auth='Basic celso.providelo@xxxxxxxxxxxxx:test')
     >>> cprov_browser.open('http://launchpad.test/~bassists')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: Object: <...>, name: '~bassists'
diff --git a/lib/lp/registry/stories/mailinglists/subscriptions.txt b/lib/lp/registry/stories/mailinglists/subscriptions.txt
index 5ab421c..525698e 100644
--- a/lib/lp/registry/stories/mailinglists/subscriptions.txt
+++ b/lib/lp/registry/stories/mailinglists/subscriptions.txt
@@ -377,13 +377,11 @@ does not show either link.
     Create a mailing list
 
     >>> carlos_browser.getLink('Subscribe')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> carlos_browser.getLink('Unsubscribe')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/milestone/xx-create-milestone-on-distribution.txt b/lib/lp/registry/stories/milestone/xx-create-milestone-on-distribution.txt
index a5f6829..cbf71cc 100644
--- a/lib/lp/registry/stories/milestone/xx-create-milestone-on-distribution.txt
+++ b/lib/lp/registry/stories/milestone/xx-create-milestone-on-distribution.txt
@@ -5,7 +5,6 @@ Team (ubuntu-team).
     >>> name12_browser = setupBrowser(auth='Basic test@xxxxxxxxxxxxx:test')
     >>> name12_browser.open(
     ...     'http://launchpad.test/ubuntu/hoary/+addmilestone')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/milestone/xx-milestone-add-and-edit.txt b/lib/lp/registry/stories/milestone/xx-milestone-add-and-edit.txt
index d7cb196..a167369 100644
--- a/lib/lp/registry/stories/milestone/xx-milestone-add-and-edit.txt
+++ b/lib/lp/registry/stories/milestone/xx-milestone-add-and-edit.txt
@@ -31,25 +31,21 @@ see the link to add a milestone nor access the page directly.
 
     >>> user_browser.open('http://launchpad.test/alsa-utils/trunk')
     >>> user_browser.getLink('Create milestone').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.open(
     ...     'http://launchpad.test/alsa-utils/trunk/+addmilestone')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
 
     >>> user_browser.open('http://launchpad.test/ubuntu/hoary')
     >>> user_browser.getLink('Create milestone').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.open('http://launchpad.test/ubuntu/hoary/+addmilestone')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
@@ -86,7 +82,6 @@ But we can't subscribe to project milestones, since they are not real objects.
 
     >>> user_browser.open('http://launchpad.test/mozilla/+milestone/1.0')
     >>> user_browser.getLink('Subscribe to bug mail')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/object/xx-object-branding.txt b/lib/lp/registry/stories/object/xx-object-branding.txt
index e8ee21c..79c75f1 100644
--- a/lib/lp/registry/stories/object/xx-object-branding.txt
+++ b/lib/lp/registry/stories/object/xx-object-branding.txt
@@ -17,7 +17,6 @@ Team branding
 
     >>> browser = setupBrowser(auth='Basic no-priv@xxxxxxxxxxxxx:test')
     >>> browser.open('http://launchpad.test/~ubuntu-team/+branding')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -80,7 +79,6 @@ Distribution branding
 
     >>> browser = setupBrowser(auth='Basic no-priv@xxxxxxxxxxxxx:test')
     >>> browser.open('http://launchpad.test/kubuntu/+edit')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -141,7 +139,6 @@ ProjectGroup branding
 
     >>> browser = setupBrowser(auth='Basic no-priv@xxxxxxxxxxxxx:test')
     >>> browser.open('http://launchpad.test/mozilla/+branding')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -204,7 +201,6 @@ Product branding
 
     >>> browser = setupBrowser(auth='Basic no-priv@xxxxxxxxxxxxx:test')
     >>> browser.open('http://launchpad.test/jokosher/+branding')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -271,7 +267,6 @@ Again, for Sprints, we have not exposed icon editing through the UI.
 
     >>> browser = setupBrowser(auth='Basic no-priv@xxxxxxxxxxxxx:test')
     >>> browser.open('http://launchpad.test/sprints/futurista/+branding')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/person/xx-add-sshkey.txt b/lib/lp/registry/stories/person/xx-add-sshkey.txt
index 3771907..8283d4f 100644
--- a/lib/lp/registry/stories/person/xx-add-sshkey.txt
+++ b/lib/lp/registry/stories/person/xx-add-sshkey.txt
@@ -133,7 +133,6 @@ Launchpad administrators are not allowed to poke at other user's ssh keys.
     >>> logout()
     >>> admin_browser = setupBrowserFreshLogin(foo_bar)
     >>> admin_browser.open('http://launchpad.test/~salgado/+editsshkeys')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -173,7 +172,6 @@ belong to him, it will fail with an error message.
 
     >>> browser.getControl(name='key', index=0).value = '1'
     >>> browser.getControl('Remove', index=0).click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     lp.app.errors.UnexpectedFormData: ...
 
@@ -183,7 +181,6 @@ this case we'll raise an UnexpectedFormData.
     >>> browser.open('http://launchpad.test/~salgado/+editsshkeys')
     >>> browser.getControl(name='key', index=0).value = ''
     >>> browser.getControl('Remove', index=0).click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: ...
diff --git a/lib/lp/registry/stories/person/xx-admin-person-review.txt b/lib/lp/registry/stories/person/xx-admin-person-review.txt
index e191f41..0f38bee 100644
--- a/lib/lp/registry/stories/person/xx-admin-person-review.txt
+++ b/lib/lp/registry/stories/person/xx-admin-person-review.txt
@@ -30,7 +30,6 @@ Registry experts can't change the displayname.
     >>> expert_browser.getControl(
     ...     'Display Name', index=0).value = 'The one and only Salgado'
     >>> expert_browser.getControl('Change').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/person/xx-adminpeoplemerge.txt b/lib/lp/registry/stories/person/xx-adminpeoplemerge.txt
index cf0b6b8..cc9928a 100644
--- a/lib/lp/registry/stories/person/xx-adminpeoplemerge.txt
+++ b/lib/lp/registry/stories/person/xx-adminpeoplemerge.txt
@@ -7,12 +7,10 @@ for merging people and another one for merging teams, which obviously
 are only accessible to LP admins.
 
     >>> user_browser.open('http://launchpad.test/people/+adminpeoplemerge')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
     >>> user_browser.open('http://launchpad.test/people/+adminteammerge')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/person/xx-approve-members.txt b/lib/lp/registry/stories/person/xx-approve-members.txt
index bd55eba..34486c2 100644
--- a/lib/lp/registry/stories/person/xx-approve-members.txt
+++ b/lib/lp/registry/stories/person/xx-approve-members.txt
@@ -73,7 +73,6 @@ as an inactive one.
 And now we see that there are no pending members left.
 
     >>> browser.getLink('Approve or decline members')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/person/xx-deactivate-account.txt b/lib/lp/registry/stories/person/xx-deactivate-account.txt
index dfef5de..43d2c59 100644
--- a/lib/lp/registry/stories/person/xx-deactivate-account.txt
+++ b/lib/lp/registry/stories/person/xx-deactivate-account.txt
@@ -84,7 +84,6 @@ the user themselves --not even Launchpad admins can do that on behalf of other
 people.
 
     >>> admin_browser.open('http://launchpad.test/~cprov/+deactivate-account')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/person/xx-person-claim-merge.txt b/lib/lp/registry/stories/person/xx-person-claim-merge.txt
index 1c8462f..f7cfaa3 100644
--- a/lib/lp/registry/stories/person/xx-person-claim-merge.txt
+++ b/lib/lp/registry/stories/person/xx-person-claim-merge.txt
@@ -9,7 +9,7 @@ exception that will redirect the user to the login page.
     >>> link = anon_browser.getLink("Are you Diogo Matsubara?")
     >>> print(link.url)
     http://launchpad.test/people/+requestmerge?field.dupe_person=matsubara
-    >>> link.click()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> link.click()
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/person/xx-person-home.txt b/lib/lp/registry/stories/person/xx-person-home.txt
index 28a99ab..99fe5cb 100644
--- a/lib/lp/registry/stories/person/xx-person-home.txt
+++ b/lib/lp/registry/stories/person/xx-person-home.txt
@@ -80,7 +80,6 @@ However, when the user visits someone else's page, they see no such URL.
 And there is no helpful link.
 
     >>> print(user_browser.getLink('openid help').url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/pillar/xx-pillar-deactivation.txt b/lib/lp/registry/stories/pillar/xx-pillar-deactivation.txt
index 7e9127f..f55c567 100644
--- a/lib/lp/registry/stories/pillar/xx-pillar-deactivation.txt
+++ b/lib/lp/registry/stories/pillar/xx-pillar-deactivation.txt
@@ -44,24 +44,20 @@ The projects are now no longer publicly visible:
 
     >>> anon_browser.open('http://launchpad.test/projects/+index?text=mozilla')
     >>> anon_browser.getLink(url='/firefox')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> anon_browser.getLink(url='/mozilla')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> anon_browser.open('http://launchpad.test/firefox')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
 
     >>> anon_browser.open('http://launchpad.test/mozilla')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/registry/stories/pillar/xx-pillar-traversal.txt b/lib/lp/registry/stories/pillar/xx-pillar-traversal.txt
index e4b57ec..392b75b 100644
--- a/lib/lp/registry/stories/pillar/xx-pillar-traversal.txt
+++ b/lib/lp/registry/stories/pillar/xx-pillar-traversal.txt
@@ -16,7 +16,6 @@ canonical URL.
     >>> browser.open('http://launchpad.test/firefox')
 
     >>> browser.open('http://launchpad.test/iceweasel')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/registry/stories/product/xx-product-files.txt b/lib/lp/registry/stories/product/xx-product-files.txt
index 04f7fc8..0d99ad7 100644
--- a/lib/lp/registry/stories/product/xx-product-files.txt
+++ b/lib/lp/registry/stories/product/xx-product-files.txt
@@ -191,7 +191,6 @@ Ensure a non-owner doesn't see the 'Add download file' link.
 
     >>> non_owner.open('http://launchpad.test/firefox/+download')
     >>> non_owner.getLink('1.0.0')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -208,7 +207,6 @@ navigating to the product release page.
 
     >>> non_owner.open('http://launchpad.test/firefox/1.0/1.0.0')
     >>> non_owner.getLink('Add download file')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/product/xx-product-package-pages.txt b/lib/lp/registry/stories/product/xx-product-package-pages.txt
index 15b7576..4659d66 100644
--- a/lib/lp/registry/stories/product/xx-product-package-pages.txt
+++ b/lib/lp/registry/stories/product/xx-product-package-pages.txt
@@ -44,7 +44,6 @@ Any logged in users can still see the links to create a packaging link.
 
     >>> anon_browser.open('http://launchpad.test/evolution/+packages')
     >>> anon_browser.getLink(url='/evolution/trunk/+ubuntupkg')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/product/xx-projects-index.txt b/lib/lp/registry/stories/product/xx-projects-index.txt
index 2ccbef5..4ca2e43 100644
--- a/lib/lp/registry/stories/product/xx-projects-index.txt
+++ b/lib/lp/registry/stories/product/xx-projects-index.txt
@@ -5,7 +5,6 @@ Just make sure this page contains the right links:
 This link was removed.
 
     >>> user_browser.getLink("Show all teams").url
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/productrelease/xx-productrelease-basics.txt b/lib/lp/registry/stories/productrelease/xx-productrelease-basics.txt
index 4c2e840..4ece9de 100644
--- a/lib/lp/registry/stories/productrelease/xx-productrelease-basics.txt
+++ b/lib/lp/registry/stories/productrelease/xx-productrelease-basics.txt
@@ -8,13 +8,11 @@ release nor can access the page directly.
 
     >>> user_browser.open('http://launchpad.test/firefox/+milestone/1.0')
     >>> user_browser.getLink('Create release').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.open(
     ...     'http://launchpad.test/firefox/+milestone/1.0/+addrelease')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
@@ -92,7 +90,6 @@ has a productrelease.
 
     >>> browser.open('http://launchpad.test/firefox/+milestone/1.0')
     >>> browser.getLink('Create release').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/productrelease/xx-productrelease-delete.txt b/lib/lp/registry/stories/productrelease/xx-productrelease-delete.txt
index 9bd1066..f33a780 100644
--- a/lib/lp/registry/stories/productrelease/xx-productrelease-delete.txt
+++ b/lib/lp/registry/stories/productrelease/xx-productrelease-delete.txt
@@ -22,12 +22,10 @@ link and cannot access the +delete page.
     0.9.2 "One (secure) Tree Hill" : Mozilla Firefox
 
     >>> user_browser.getLink(url='/firefox/trunk/0.9.2/+delete')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.open('http://launchpad.test/firefox/trunk/0.9.2/+delete')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/productseries/xx-productseries-add-and-edit.txt b/lib/lp/registry/stories/productseries/xx-productseries-add-and-edit.txt
index d8a665b..8ac9740 100644
--- a/lib/lp/registry/stories/productseries/xx-productseries-add-and-edit.txt
+++ b/lib/lp/registry/stories/productseries/xx-productseries-add-and-edit.txt
@@ -10,12 +10,10 @@ Person won't even see the link nor can access the page directly.
 
     >>> user_browser.open('http://launchpad.test/firefox')
     >>> user_browser.getLink('Register a series').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.open('http://launchpad.test/firefox/+addseries')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/productseries/xx-productseries-delete.txt b/lib/lp/registry/stories/productseries/xx-productseries-delete.txt
index 92bfa76..179e316 100644
--- a/lib/lp/registry/stories/productseries/xx-productseries-delete.txt
+++ b/lib/lp/registry/stories/productseries/xx-productseries-delete.txt
@@ -92,7 +92,6 @@ that the series was deleted, and can not see a link to it anymore.
     Series trunk deleted.
 
     >>> owner_browser.getLink('trunk')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/project/xx-project-add.txt b/lib/lp/registry/stories/project/xx-project-add.txt
index 4e6a32a..6f4903e 100644
--- a/lib/lp/registry/stories/project/xx-project-add.txt
+++ b/lib/lp/registry/stories/project/xx-project-add.txt
@@ -4,7 +4,6 @@ Adding new projects
 Normal users should not be able to do this:
 
     >>> user_browser.open("http://launchpad.test/projectgroups/+new";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/project/xx-project-edit.txt b/lib/lp/registry/stories/project/xx-project-edit.txt
index 840697c..e6c0e97 100644
--- a/lib/lp/registry/stories/project/xx-project-edit.txt
+++ b/lib/lp/registry/stories/project/xx-project-edit.txt
@@ -23,7 +23,6 @@ The maintainer of a project can edit its details.
 Regular users can't access the +review page.
 
     >>> browser.getLink('Administer')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -123,7 +122,6 @@ Registry experts are not allowed access to the +edit page.
 
     >>> expert_browser.open('http://launchpad.test/new-name')
     >>> expert_browser.getLink('Change details').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -131,7 +129,6 @@ Registry experts are not allowed access to the +edit page.
 And going directly to the URL is not allowed.
 
     >>> expert_browser.open('http://launchpad.test/new-name/+edit')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/project/xx-project-index.txt b/lib/lp/registry/stories/project/xx-project-index.txt
index 086ce39..b84ce00 100644
--- a/lib/lp/registry/stories/project/xx-project-index.txt
+++ b/lib/lp/registry/stories/project/xx-project-index.txt
@@ -46,14 +46,12 @@ project.
 
     >>> browser.open('http://launchpad.test/mozilla')
     >>> browser.getLink('Register a project in The Mozilla Project')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> browser.addHeader('Authorization', 'Basic no-priv@xxxxxxxxxxxxx:test')
     >>> browser.getLink('Register a project in The Mozilla Project')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -83,17 +81,14 @@ question' or 'Help translate' buttons.
 
     >>> user_browser.open('http://launchpad.test/a-test-group')
     >>> user_browser.getLink('Report a bug')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.getLink('Ask a question')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.getLink('Help translate')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
@@ -102,27 +97,22 @@ Also, the bugs, blueprints, translations and answers facets will be disabled:
 
     >>> user_browser.open('http://launchpad.test/a-test-group')
     >>> user_browser.getLink('Bugs')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.getLink('Blueprints')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.getLink('Answers')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.getLink('Answers')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.getLink('Translations')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/team-polls/create-polls.txt b/lib/lp/registry/stories/team-polls/create-polls.txt
index ed0e1bd..9f8e833 100644
--- a/lib/lp/registry/stories/team-polls/create-polls.txt
+++ b/lib/lp/registry/stories/team-polls/create-polls.txt
@@ -20,7 +20,6 @@ administrator. There's no link leading to the +newpoll page, but the user can
 easily guess it.
 
     >>> no_priv_browser.open('http://launchpad.test/~ubuntu-team/+newpoll')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/team-polls/edit-options.txt b/lib/lp/registry/stories/team-polls/edit-options.txt
index 1cbf715..8610451 100644
--- a/lib/lp/registry/stories/team-polls/edit-options.txt
+++ b/lib/lp/registry/stories/team-polls/edit-options.txt
@@ -13,7 +13,6 @@ team's administrators:
     OptionA     OptionA     Yes
     ...
     >>> user_browser.getLink('[Edit]')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/team/xx-team-add-my-teams.txt b/lib/lp/registry/stories/team/xx-team-add-my-teams.txt
index 4fb0e3a..caadf07 100644
--- a/lib/lp/registry/stories/team/xx-team-add-my-teams.txt
+++ b/lib/lp/registry/stories/team/xx-team-add-my-teams.txt
@@ -103,7 +103,6 @@ your teams as members.
 
     >>> browser.open('http://launchpad.test/~ubuntu-team')
     >>> browser.getLink('Add one of my teams')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -118,7 +117,6 @@ your teams as members.
 The page is restricted to logged in users.
 
     >>> anon_browser.open('http://launchpad.test/~ubuntu-team/+add-my-teams')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     zope.security.interfaces.Unauthorized: ...
 
diff --git a/lib/lp/registry/stories/team/xx-team-home.txt b/lib/lp/registry/stories/team/xx-team-home.txt
index b6f36e0..6ec6b77 100644
--- a/lib/lp/registry/stories/team/xx-team-home.txt
+++ b/lib/lp/registry/stories/team/xx-team-home.txt
@@ -159,7 +159,6 @@ As teams do not have OpenID Logins, there is no link in the Contact
 details section for help.
 
     >>> sample_browser.getLink('OpenID help')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/teammembership/private-team.txt b/lib/lp/registry/stories/teammembership/private-team.txt
index c334281..36b2812 100644
--- a/lib/lp/registry/stories/teammembership/private-team.txt
+++ b/lib/lp/registry/stories/teammembership/private-team.txt
@@ -41,7 +41,6 @@ The page indicates that the team is private.
 A normal user cannot see the team.
 
     >>> user_browser.open('http://launchpad.test/~private-team')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
@@ -49,7 +48,6 @@ A normal user cannot see the team.
 An anonymous user cannot see the team.
 
     >>> anon_browser.open('http://launchpad.test/~private-team')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/registry/stories/teammembership/xx-add-member.txt b/lib/lp/registry/stories/teammembership/xx-add-member.txt
index bdf48f2..f5a2733 100644
--- a/lib/lp/registry/stories/teammembership/xx-add-member.txt
+++ b/lib/lp/registry/stories/teammembership/xx-add-member.txt
@@ -91,7 +91,6 @@ rights to edit the membership in question) can do it.
 
     >>> landscape_admin_browser.open(
     ...    'http://launchpad.test/~launchpad/+invitation/landscape-developers')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/teammembership/xx-member-renewed-membership.txt b/lib/lp/registry/stories/teammembership/xx-member-renewed-membership.txt
index c3b457c..5388662 100644
--- a/lib/lp/registry/stories/teammembership/xx-member-renewed-membership.txt
+++ b/lib/lp/registry/stories/teammembership/xx-member-renewed-membership.txt
@@ -53,7 +53,6 @@ Other users (apart from Karl) can't see that page.
 
     >>> user_browser.open('http://launchpad.test/~karl/+expiringmembership/'
     ...                   'ubuntu-mirror-admins')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -203,7 +202,6 @@ Any user who's not an admin of landscape-developers can't even see that page.
 
     >>> user_browser.open('http://launchpad.test/~landscape-developers'
     ...                   '/+expiringmembership/ubuntu-mirror-admins')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/registry/stories/teammembership/xx-team-leave.txt b/lib/lp/registry/stories/teammembership/xx-team-leave.txt
index b2ee0a6..b2d66d3 100644
--- a/lib/lp/registry/stories/teammembership/xx-team-leave.txt
+++ b/lib/lp/registry/stories/teammembership/xx-team-leave.txt
@@ -71,7 +71,6 @@ team's overview page.
 
     # The 'Leave' link should be gone.
     >>> browser.getLink('Leave the Team')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -87,7 +86,6 @@ Team owners do not have the option to leave.
     ...     find_tag_by_id(browser.contents, 'your-involvement')))
     You own this team...
     >>> browser.getLink('Leave the Team')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/stories/teammembership/xx-teammembership.txt b/lib/lp/registry/stories/teammembership/xx-teammembership.txt
index ff6f13d..4cca381 100644
--- a/lib/lp/registry/stories/teammembership/xx-teammembership.txt
+++ b/lib/lp/registry/stories/teammembership/xx-teammembership.txt
@@ -64,7 +64,6 @@ say that there's no need to join since the user is already a member of that
 team.
 
     >>> browser.getLink('Join the team')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -177,7 +176,6 @@ If it was a restricted team, users wouldn't even see a link to join the team.
     Restricted Team
 
     >>> browser.getLink('Join the team')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/registry/tests/person_from_principal.txt b/lib/lp/registry/tests/person_from_principal.txt
index d414705..04ff03d 100644
--- a/lib/lp/registry/tests/person_from_principal.txt
+++ b/lib/lp/registry/tests/person_from_principal.txt
@@ -10,7 +10,6 @@ raised.
     ...     id = 42
     ...     person = None
     >>> person_from_principal(NoLaunchpadPrincipal())
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.interface.interfaces.ComponentLookupError
diff --git a/lib/lp/services/database/doc/db-policy.txt b/lib/lp/services/database/doc/db-policy.txt
index aa90ed7..48255e9 100644
--- a/lib/lp/services/database/doc/db-policy.txt
+++ b/lib/lp/services/database/doc/db-policy.txt
@@ -38,7 +38,7 @@ a single master.
     False
 
     >>> ro_janitor.display_name = 'Janice the Janitor'
-    >>> transaction.commit()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> transaction.commit()
     Traceback (most recent call last):
     ...
     storm.database.InternalError: ...
@@ -81,7 +81,6 @@ resources.
     >>> with SlaveOnlyDatabasePolicy():
     ...     whoops = IMasterStore(Person).find(
     ...         Person, Person.name == 'janitor').one()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.database.interfaces.DisallowedStore: master
@@ -95,7 +94,6 @@ database transaction.
     >>> with DatabaseBlockedPolicy():
     ...     whoops = IStore(Person).find(
     ...         Person, Person.name == 'janitor').one()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.database.interfaces.DisallowedStore: ('main', 'default')
diff --git a/lib/lp/services/database/doc/multitablecopy.txt b/lib/lp/services/database/doc/multitablecopy.txt
index 618ebd7..f6ffd41 100644
--- a/lib/lp/services/database/doc/multitablecopy.txt
+++ b/lib/lp/services/database/doc/multitablecopy.txt
@@ -327,7 +327,6 @@ which means that the attempt to insert it will violate a unique constraint.
     ...             % numeric_holding_table)
 
     >>> copier.pour(transaction)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     storm.database.IntegrityError: duplicate ... violates unique constraint ...
diff --git a/lib/lp/services/database/doc/storm.txt b/lib/lp/services/database/doc/storm.txt
index abe5dc3..82823a5 100644
--- a/lib/lp/services/database/doc/storm.txt
+++ b/lib/lp/services/database/doc/storm.txt
@@ -72,7 +72,7 @@ from a store other than the correct Master.
     >>> t = transaction.begin()
     >>> person = main_slave.find(Person, name='mark').one()
     >>> person.display_name = 'Cannot change'
-    >>> transaction.commit()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> transaction.commit()
     Traceback (most recent call last):
     ...
     storm.database.InternalError: ...
@@ -94,7 +94,6 @@ similarly wrapped.
     >>> print(person.displayname)
     No Privileges Person
     >>> person.name = 'foo'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -105,7 +104,6 @@ similarly wrapped.
     >>> print(person.displayname)
     No Privileges Person
     >>> person.name = 'foo'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/services/feeds/doc/feeds.txt b/lib/lp/services/feeds/doc/feeds.txt
index 2e313d2..4cf0d54 100644
--- a/lib/lp/services/feeds/doc/feeds.txt
+++ b/lib/lp/services/feeds/doc/feeds.txt
@@ -57,7 +57,6 @@ not be found.
     >>> verifyObject(IThing, thing)
     True
     >>> feed_view = getMultiAdapter((thing, request), name='thing-feed.xml')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.interface.interfaces.ComponentLookupError: ...
@@ -72,12 +71,10 @@ found.
 
     >>> thing = object()
     >>> verifyObject(IThing, thing)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.interface.exceptions.MultipleInvalid: ... Does not declaratively implement the interface The lp.services.feeds.tests.helper.IThing.value attribute was not provided
     >>> feed_view = getMultiAdapter((thing, request), name='thing-feed.atom')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.interface.interfaces.ComponentLookupError: ...
@@ -89,7 +86,6 @@ found.
     >>> verifyObject(IThing, thing)
     True
     >>> feed_view = getMultiAdapter((thing, request), name='thing-feed.xml')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     zope.interface.interfaces.ComponentLookupError: ...
diff --git a/lib/lp/services/feeds/stories/xx-navigation.txt b/lib/lp/services/feeds/stories/xx-navigation.txt
index 185a9fe..48db39e 100644
--- a/lib/lp/services/feeds/stories/xx-navigation.txt
+++ b/lib/lp/services/feeds/stories/xx-navigation.txt
@@ -13,22 +13,18 @@ Trying to view a page which is not registered on the Feeds layer
 returns a 404.
 
     >>> browser.open('http://feeds.launchpad.test/jokosher')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
     >>> browser.open('http://feeds.launchpad.test/bugs')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
     >>> browser.open('http://feeds.launchpad.test/+dims')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
     >>> browser.open('http://feeds.launchpad.test/announcements.atom/foo')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/services/fields/doc/uri-field.txt b/lib/lp/services/fields/doc/uri-field.txt
index 5b60710..0f980d5 100644
--- a/lib/lp/services/fields/doc/uri-field.txt
+++ b/lib/lp/services/fields/doc/uri-field.txt
@@ -36,7 +36,6 @@ valid URI:
     >>> field = IURIFieldTest['field']
     >>> field.validate(u'http://launchpad.net/')
     >>> field.validate(u'not-a-uri')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.validators.LaunchpadValidationError: &quot;not-a-uri&quot; is not a valid URI
@@ -52,7 +51,6 @@ will result in a validation error:
     >>> sftp_only = IURIFieldTest['sftp_only']
     >>> sftp_only.validate(u'sFtp://launchpad.net/')
     >>> sftp_only.validate(u'http://launchpad.net/')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.validators.LaunchpadValidationError: The URI scheme &quot;http&quot; is not allowed. Only URIs with the following schemes may be used: sftp
@@ -67,13 +65,11 @@ product home page, where authentication is not generally required:
 
     >>> no_userinfo = IURIFieldTest['no_userinfo']
     >>> no_userinfo.validate(u'http://launchpad.net:80@127.0.0.1/ubuntu')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.validators.LaunchpadValidationError: A username may not be specified in the URI.
 
     >>> no_userinfo.validate(u'http://launchpad.net@127.0.0.1/ubuntu')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.validators.LaunchpadValidationError: A username may not be specified in the URI.
@@ -87,7 +83,6 @@ URIs.  This can be done with the allow_port option:
 
     >>> no_port = IURIFieldTest['no_port']
     >>> no_port.validate(u'http://launchpad.net:21')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.validators.LaunchpadValidationError: Non-default ports are not allowed.
@@ -107,7 +102,6 @@ reject those URIs:
 
     >>> no_query = IURIFieldTest['no_query']
     >>> no_query.validate(u'http://launchpad.net/?key=value')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.validators.LaunchpadValidationError: URIs with query strings are not allowed.
@@ -120,7 +114,6 @@ The fragment component can also be disallowed:
 
     >>> no_fragment = IURIFieldTest['no_fragment']
     >>> no_fragment.validate(u'http://launchpad.net/#fragment')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.validators.LaunchpadValidationError: URIs with fragment identifiers are not allowed.
@@ -212,7 +205,6 @@ This widget is registered as an input widget:
 Multiple values will cause an UnexpectedFormData exception:
 
     >>> widget._toFieldValue(['http://launchpad.net', 'http://ubuntu.com'])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.errors.UnexpectedFormData: Only a single value is expected
diff --git a/lib/lp/services/gpg/doc/gpg-signatures.txt b/lib/lp/services/gpg/doc/gpg-signatures.txt
index 4f16924..6e09ab9 100644
--- a/lib/lp/services/gpg/doc/gpg-signatures.txt
+++ b/lib/lp/services/gpg/doc/gpg-signatures.txt
@@ -86,7 +86,6 @@ The text below was "clear signed" by 0xDFD20543 master key but tampered with:
     ... """
 
     >>> master_sig = gpghandler.getVerifiedSignature(content)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.gpg.interfaces.GPGVerificationError: (7, 8, ...'Bad signature')
@@ -102,7 +101,6 @@ If no signed content is found, an exception is raised:
     ... """
 
     >>> master_sig = gpghandler.getVerifiedSignature(content)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.gpg.interfaces.GPGVerificationError: No signatures found
@@ -145,7 +143,6 @@ now only gives us a rather less informative "Bad data" exception.  We don't
 care too much about the details as long as it fails.
 
     >>> master_sig = gpghandler.getVerifiedSignature(content)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.gpg.interfaces.GPGVerificationError: ...
@@ -167,7 +164,6 @@ the GPGME error codes (they may be helpful).
     ... -----END PGP SIGNATURE-----
     ... """
     >>> gpghandler.getVerifiedSignature(content)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.gpg.interfaces.GPGKeyDoesNotExistOnServer: GPG key E192C0543B1BB2EB does not exist on the keyserver.
@@ -181,7 +177,6 @@ exception. The exception raised by this method will contain debug
 information for the 3 failures.
 
     >>> gpghandler.getVerifiedSignatureResilient(content)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.gpg.interfaces.GPGVerificationError: Verification failed 3 times: ['GPG key E192C0543B1BB2EB does not exist on the keyserver.', 'GPG key E192C0543B1BB2EB does not exist on the keyserver.', 'GPG key E192C0543B1BB2EB does not exist on the keyserver.']
diff --git a/lib/lp/services/gpg/doc/gpghandler.txt b/lib/lp/services/gpg/doc/gpghandler.txt
index 375ceac..a82283a 100644
--- a/lib/lp/services/gpg/doc/gpghandler.txt
+++ b/lib/lp/services/gpg/doc/gpghandler.txt
@@ -41,7 +41,6 @@ unit tests somewhere else at some point. -- Guilherme Salgado, 2006-08-23
 A GPGKeyNotFoundError is raised if we try to import an empty content.
 
     >>> key = gpghandler.importPublicKey(b'')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.gpg.interfaces.GPGKeyNotFoundError: ...
@@ -49,7 +48,6 @@ A GPGKeyNotFoundError is raised if we try to import an empty content.
 The same happens for bogus content.
 
     >>> key = gpghandler.importPublicKey(b'XXXXXXXXX')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.gpg.interfaces.GPGKeyNotFoundError: ...
@@ -99,7 +97,6 @@ SecretGPGKeyImportDetected exception to be raised.
     >>> with open(filepath, 'rb') as f:
     ...     seckey = f.read()
     >>> key = gpghandler.importPublicKey(seckey)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.gpg.interfaces.SecretGPGKeyImportDetected: ...
@@ -111,7 +108,6 @@ exception to be raised.
     >>> with open(filepath, 'rb') as f:
     ...     pubkey2 = f.read()
     >>> key = gpghandler.importPublicKey(b'\n'.join([pubkey, pubkey2]))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.gpg.interfaces.MoreThanOneGPGKeyFound: ...
@@ -120,7 +116,6 @@ Raise a GPGKeyNotFoundError if we try to import a public key with damaged
 preamble.
 
     >>> key = gpghandler.importPublicKey(pubkey[1:])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.gpg.interfaces.GPGKeyNotFoundError: ...
@@ -138,7 +133,6 @@ But we get an error if the damage is big:
 (what probably happened in bug #2547)
 
     >>> key = gpghandler.importPublicKey(pubkey[:-500])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.gpg.interfaces.GPGKeyNotFoundError: ...
@@ -224,7 +218,6 @@ hit the keyserver and import it automatically.
 An attempt to upload an unknown key will fail.
 
     >>> gpghandler.uploadPublicKey('F' * 40)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.gpg.interfaces.GPGKeyDoesNotExistOnServer: GPG key FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF does not exist on the keyserver.
@@ -239,7 +232,6 @@ in a error.
 
     >>> tac.tearDown()
     >>> gpghandler.uploadPublicKey(new_key.fingerprint)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.gpg.interfaces.GPGUploadFailure: Could not reach keyserver at http://localhost:11371...Connection refused...
diff --git a/lib/lp/services/helpers.py b/lib/lp/services/helpers.py
index 66070c1..e8f98c4 100644
--- a/lib/lp/services/helpers.py
+++ b/lib/lp/services/helpers.py
@@ -138,7 +138,7 @@ def shortlist(sequence, longest_expected=15, hardlimit=None):
     sequences with no more than 2 items.  There were 3 items.
 
     >>> shortlist([1, 2, 3, 4], hardlimit=2)
-    ... # doctest: +NORMALIZE_WHITESPACE,+IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    ... # doctest: +NORMALIZE_WHITESPACE
     Traceback (most recent call last):
     ...
     lp.services.helpers.ShortListTooBigError: Hard limit of 2 exceeded.
@@ -158,7 +158,7 @@ def shortlist(sequence, longest_expected=15, hardlimit=None):
     TypeError: ...
 
     >>> shortlist(iter(range(10)), 5, hardlimit=8)
-    ... # doctest: +ELLIPSIS,+IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    ... # doctest: +ELLIPSIS
     Traceback (most recent call last):
     ...
     lp.services.helpers.ShortListTooBigError: ...
diff --git a/lib/lp/services/identity/doc/emailaddress.txt b/lib/lp/services/identity/doc/emailaddress.txt
index 4163d8f..d1f26cb 100644
--- a/lib/lp/services/identity/doc/emailaddress.txt
+++ b/lib/lp/services/identity/doc/emailaddress.txt
@@ -36,7 +36,6 @@ exception.
     >>> personset = getUtility(IPersonSet)
     >>> foobar = personset.getByName('name16')
     >>> emailset.new(email.email, foobar)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.identity.interfaces.emailaddress.EmailAddressAlreadyTaken: The email address '...' is already registered.
@@ -44,7 +43,6 @@ exception.
 The email address verification is case insensitive as well:
 
     >>> emailset.new(email.email.upper(), foobar)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.identity.interfaces.emailaddress.EmailAddressAlreadyTaken: The email address '...' is already registered.
@@ -95,7 +93,6 @@ or the address of a team's mailing list.
 Otherwise, UndeletableEmailAddress is raised.
 
     >>> foobar.preferredemail.destroySelf()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.identity.model.emailaddress.UndeletableEmailAddress: This is a person's preferred email...
@@ -105,7 +102,6 @@ Otherwise, UndeletableEmailAddress is raised.
     >>> mailing_list = new_list_for_team(guadamen)
     >>> email = emailset.getByEmail(guadamen.mailing_list.address)
     >>> email.destroySelf()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.identity.model.emailaddress.UndeletableEmailAddress: This is the email address of a team's mailing list...
diff --git a/lib/lp/services/librarian/doc/librarian.txt b/lib/lp/services/librarian/doc/librarian.txt
index 598a8b5..f2d2f6f 100644
--- a/lib/lp/services/librarian/doc/librarian.txt
+++ b/lib/lp/services/librarian/doc/librarian.txt
@@ -364,13 +364,11 @@ If you try to retrieve this file through the standard ILibrarianClient,
 you'll get a DownloadFailed error.
 
     >>> client.getFileByAlias(private_file_id)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.services.librarian.interfaces.client.DownloadFailed: Alias ... cannot be downloaded from this client.
 
     >>> client.getURLForAlias(private_file_id)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.services.librarian.interfaces.client.DownloadFailed: Alias ... cannot be downloaded from this client.
@@ -391,7 +389,6 @@ Trying to access that file directly on the normal librarian will fail
     ...     config.librarian.restricted_download_url,
     ...     config.librarian.download_url)
     >>> urlopen(sneaky_url).read()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     urllib.error.HTTPError: HTTP Error 404: Not Found
@@ -415,13 +412,11 @@ also fails:
     >>> transaction.commit()
 
     >>> restricted_client.getURLForAlias(public_file_id)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.services.librarian.interfaces.client.DownloadFailed: ...
 
     >>> restricted_client.getFileByAlias(public_file_id)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.services.librarian.interfaces.client.DownloadFailed: ...
@@ -482,7 +477,6 @@ An UploadFailed will be raised if you try to create a file with no
 content
 
     >>> client.addFile('test.txt', 0, io.BytesIO(b'hello'), 'text/plain')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
         [...]
     lp.services.librarian.interfaces.client.UploadFailed: Invalid length: 0
@@ -638,7 +632,6 @@ The count starts at 0, and cannot be changed directly.
     0
 
     >>> public_file.hits = 10
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ...
diff --git a/lib/lp/services/mail/doc/emailauthentication.txt b/lib/lp/services/mail/doc/emailauthentication.txt
index 897984c..dbefd7d 100644
--- a/lib/lp/services/mail/doc/emailauthentication.txt
+++ b/lib/lp/services/mail/doc/emailauthentication.txt
@@ -99,7 +99,6 @@ InvalidSignature will be raised:
     >>> name, addr = email.utils.parseaddr(msg['From'])
     >>> from_user = getUtility(IPersonSet).getByEmail(addr)
     >>> principal = authenticateEmail(msg, accept_any_timestamp)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.services.mail.incoming.InvalidSignature: ...
@@ -123,7 +122,6 @@ message.
     >>> from lp.services.gpg.interfaces import IGPGHandler
     >>> getUtility(IGPGHandler).getVerifiedSignature(
     ...     msg.signedContent, msg.signature)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.gpg.interfaces.GPGVerificationError: (7, 8, ...'Bad signature')
diff --git a/lib/lp/services/mail/doc/mailbox.txt b/lib/lp/services/mail/doc/mailbox.txt
index 40702a0..aa9ac88 100644
--- a/lib/lp/services/mail/doc/mailbox.txt
+++ b/lib/lp/services/mail/doc/mailbox.txt
@@ -62,7 +62,7 @@ Before we can use it, it has to be opened.
 To prevent two threads opening it the same time, if it's already open,
 we can't open it again:
 
-    >>> mailbox.open()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> mailbox.open()
     Traceback (most recent call last):
     ...
     lp.services.mail.mailbox.MailBoxError: The mail box is already open.
@@ -103,7 +103,7 @@ Let's delete all mails in the mail box:
 
 If we try to delete a mail that doesn't exist we get an error:
 
-    >>> mailbox.delete(-1)  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> mailbox.delete(-1)
     Traceback (most recent call last):
     ...
     lp.services.mail.mailbox.MailBoxError: No such id: -1
diff --git a/lib/lp/services/mail/doc/notification-recipient-set.txt b/lib/lp/services/mail/doc/notification-recipient-set.txt
index 059cd7b..d06e7c4 100644
--- a/lib/lp/services/mail/doc/notification-recipient-set.txt
+++ b/lib/lp/services/mail/doc/notification-recipient-set.txt
@@ -116,13 +116,11 @@ Requesting the reason for somebody that is not a recipient raises a
 UnknownRecipientError:
 
     >>> recipients.getReason(no_priv)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.services.mail.interfaces.UnknownRecipientError: ...
 
     >>> recipients.getReason(six.ensure_str('no-priv@xxxxxxxxxxxxx'))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.services.mail.interfaces.UnknownRecipientError: 'no-priv@xxxxxxxxxxxxx'
diff --git a/lib/lp/services/mail/tests/incomingmail.txt b/lib/lp/services/mail/tests/incomingmail.txt
index 6731b61..d139c02 100644
--- a/lib/lp/services/mail/tests/incomingmail.txt
+++ b/lib/lp/services/mail/tests/incomingmail.txt
@@ -368,7 +368,7 @@ reporting in the web interface, are not ignored in the email interface.
     ... doesn't matter
     ... """)
     >>> msgid = sendmail(msg, ['edit@malone-domain'])
-    >>> handleMailForTest()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> handleMailForTest()
     ERROR:process-mail:An exception was raised inside the handler:
     ...
     twisted.cred.error.Unauthorized
@@ -481,7 +481,7 @@ logged.
     >>> len(stub.test_emails)
     2
 
-    >>> handleMailForTest()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> handleMailForTest()
     ERROR:...:Upload to Librarian failed...
     ...
     lp.services.librarian.interfaces.client.UploadFailed: ...Connection refused...
diff --git a/lib/lp/services/messages/doc/message.txt b/lib/lp/services/messages/doc/message.txt
index 75a22e2..76f95a1 100644
--- a/lib/lp/services/messages/doc/message.txt
+++ b/lib/lp/services/messages/doc/message.txt
@@ -389,7 +389,6 @@ explicitly told to do so:
     ...
     ... Foo Bar
     ... ''')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
         [...]
     lp.services.messages.interfaces.message.UnknownSender: ...'invalid@xxxxxxxxxxx'
@@ -423,7 +422,6 @@ passed through a broken MTA and we have no choice but to bounce them.
     ...
     ... Moo
     ... ''')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
         [...]
     lp.services.messages.interfaces.message.InvalidEmailMessage: Missing Message-Id
@@ -435,7 +433,6 @@ passed through a broken MTA and we have no choice but to bounce them.
     ...
     ... Moo
     ... ''')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
         [...]
     lp.services.messages.interfaces.message.InvalidEmailMessage: No From: or Reply-To: header
@@ -449,7 +446,6 @@ Also, we generally insist that a message has a date associated with it.
     ...
     ... Moo
     ... ''')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
         [...]
     lp.services.messages.interfaces.message.InvalidEmailMessage: Invalid date...
diff --git a/lib/lp/services/oauth/doc/oauth-pages.txt b/lib/lp/services/oauth/doc/oauth-pages.txt
index 0b6090c..65d5515 100644
--- a/lib/lp/services/oauth/doc/oauth-pages.txt
+++ b/lib/lp/services/oauth/doc/oauth-pages.txt
@@ -156,7 +156,6 @@ package, it must specify the distribution and the package's name.
 An error is raised if the context is not found.
 
     >>> view, token = get_view_with_fresh_token({'lp.context': 'fooooo'})
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: ...
@@ -165,7 +164,6 @@ Or if the user gives us a package in a non-existing distribution.
 
     >>> view, token = get_view_with_fresh_token(
     ...     {'lp.context': 'firefox/evolution'})
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: ...
diff --git a/lib/lp/services/oauth/stories/access-token.txt b/lib/lp/services/oauth/stories/access-token.txt
index d445ded..a56ee3c 100644
--- a/lib/lp/services/oauth/stories/access-token.txt
+++ b/lib/lp/services/oauth/stories/access-token.txt
@@ -37,7 +37,6 @@ will fail because request tokens can be used only once.
 
     >>> anon_browser.open(
     ...     'http://launchpad.test/+access-token', data=urlencode(data))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     urllib.error.HTTPError: HTTP Error 401: Unauthorized
diff --git a/lib/lp/services/oauth/stories/authorize-token.txt b/lib/lp/services/oauth/stories/authorize-token.txt
index a734ee1..dbce4e8 100644
--- a/lib/lp/services/oauth/stories/authorize-token.txt
+++ b/lib/lp/services/oauth/stories/authorize-token.txt
@@ -36,7 +36,6 @@ it involves OpenID, which would complicate this test quite a bit.)
     ...     oauth_token=token.key, oauth_callback='http://launchpad.test/bzr')
     >>> url = "http://launchpad.test/+authorize-token?%s"; % urlencode(params)
     >>> browser.open(url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -126,7 +125,6 @@ integration has its own section, below.)
     >>> browser.open(
     ...     "http://launchpad.test/+authorize-token?%s&%s";
     ...         % (urlencode(params), allow_permission))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: Consumer "foobar123451432" asked for desktop integration, but didn't say what kind of desktop it is, or name the computer being integrated.
@@ -365,14 +363,12 @@ DESKTOP_INTEGRATION, since the whole point is to have a permission
 level that specifically applies across the entire desktop.
 
     >>> print_access_levels_for('allow_permission=WRITE_PRIVATE')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: Desktop integration token requested a permission ("Change Anything") not supported for desktop-wide use.
 
     >>> print_access_levels_for(
     ...     'allow_permission=WRITE_PUBLIC&' + allow_desktop)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: Desktop integration token requested a permission ("Change Non-Private Data") not supported for desktop-wide use.
@@ -383,7 +379,6 @@ websites into Launchpad.
 
     >>> params['oauth_callback'] = 'http://launchpad.test/bzr'
     >>> print_access_levels_for(allow_desktop)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: A desktop integration may not specify an OAuth callback URL.
@@ -392,7 +387,6 @@ This is true even if the desktop token isn't asking for the
 DESKTOP_INTEGRATION permission.
 
     >>> print_access_levels_for('allow_permission=WRITE_PRIVATE')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: A desktop integration may not specify an OAuth callback URL.
diff --git a/lib/lp/services/oauth/stories/managing-tokens.txt b/lib/lp/services/oauth/stories/managing-tokens.txt
index 0dc7253..936a63d 100644
--- a/lib/lp/services/oauth/stories/managing-tokens.txt
+++ b/lib/lp/services/oauth/stories/managing-tokens.txt
@@ -131,7 +131,6 @@ That page is protected with the launchpad.Edit permission, for obvious
 reasons, so users can only access their own.
 
     >>> user_browser.open('http://launchpad.test/~salgado/+oauth-tokens')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...launchpad.Edit...
diff --git a/lib/lp/services/temporaryblobstorage/doc/temporaryblobstorage.txt b/lib/lp/services/temporaryblobstorage/doc/temporaryblobstorage.txt
index d8b67fd..52b734e 100644
--- a/lib/lp/services/temporaryblobstorage/doc/temporaryblobstorage.txt
+++ b/lib/lp/services/temporaryblobstorage/doc/temporaryblobstorage.txt
@@ -52,7 +52,6 @@ Size limits can be enforced, although this is turned off by default:
     ...     """
     >>> config.push('max_blob_size', max_blob_size)
     >>> uuid = tsm.new(data)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.temporaryblobstorage.interfaces.BlobTooLarge: 7
diff --git a/lib/lp/services/webapp/doc/canonical_url.txt b/lib/lp/services/webapp/doc/canonical_url.txt
index 16d9a94..54b8803 100644
--- a/lib/lp/services/webapp/doc/canonical_url.txt
+++ b/lib/lp/services/webapp/doc/canonical_url.txt
@@ -113,7 +113,6 @@ mistyped 'countryOopsTypo', and there is no such name in ITown.
     ...       />
     ... </configure>
     ... """.format(module_name=module.__name__))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.configuration.xmlconfig.ZopeXMLConfigurationError: File "<string>", line ... AttributeError: The name "countryOopsTypo" is not in ....ITown
@@ -277,7 +276,6 @@ itself be adapted to ICanonicalUrlData.
 
     >>> object_that_has_no_url = object()
     >>> canonical_url(object_that_has_no_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.webapp.interfaces.NoCanonicalUrl: No url for <...object at ...> because <...object at ...> broke the chain.
@@ -292,7 +290,6 @@ ICanonicalUrlData, but its parent or its parent's parent (and so on) cannot.
     ...         self.inside = parent
     >>> unrooted_object = ObjectThatHasUrl('unrooted', object_that_has_no_url)
     >>> canonical_url(unrooted_object)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.webapp.interfaces.NoCanonicalUrl: No url for <...ObjectThatHasUrl...> because <...object...> broke the chain.
@@ -339,7 +336,7 @@ to work properly.
     >>> iterator = canonical_url_iterator(object_that_has_no_url)
     >>> next(iterator).__class__.__name__
     'object'
-    >>> next(iterator)  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> next(iterator)
     Traceback (most recent call last):
     ...
     lp.services.webapp.interfaces.NoCanonicalUrl: No url for <...object...> because <...object...> broke the chain.
@@ -349,7 +346,7 @@ to work properly.
     'ObjectThatHasUrl'
     >>> next(iterator).__class__.__name__
     'object'
-    >>> next(iterator)  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> next(iterator)
     Traceback (most recent call last):
     ...
     lp.services.webapp.interfaces.NoCanonicalUrl: No url for <...ObjectThatHasUrl...> because <...object...> broke the chain.
diff --git a/lib/lp/services/webapp/doc/menus.txt b/lib/lp/services/webapp/doc/menus.txt
index 7c09640..b2f9619 100644
--- a/lib/lp/services/webapp/doc/menus.txt
+++ b/lib/lp/services/webapp/doc/menus.txt
@@ -820,7 +820,6 @@ We also report when the selected facet does not exist with a
 LocationError exception:
 
     >>> test_tales('view/menu:broken/bar', view=view)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.location.interfaces.LocationError: ..., 'broken')
@@ -856,7 +855,6 @@ When there is no menu for a thing, we get an empty iterator.
 And thus, we don't have a facet to navigate to:
 
     >>> test_tales('view/menu:foo/+first', view=view)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.location.interfaces.LocationError: ..., 'foo')
diff --git a/lib/lp/services/webapp/doc/navigation.txt b/lib/lp/services/webapp/doc/navigation.txt
index b9f15bd..19ee42f 100644
--- a/lib/lp/services/webapp/doc/navigation.txt
+++ b/lib/lp/services/webapp/doc/navigation.txt
@@ -223,7 +223,6 @@ The name doesn't begin with a 't', so it isn't found.
     >>> INewLayer.providedBy(request)
     False
     >>> navigation.publishTraverse(request, 'xxx')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...ThingSet...name: 'xxx'
@@ -338,12 +337,10 @@ Let's create a subclass of ThingSetNavigation, and add a 'stepto'.
     >>> print(navigation2.publishTraverse(request, 'thistle'))
     A little thistle
     >>> navigation2.publishTraverse(request, 'neverthere')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...ThingSet..., name: 'neverthere'
     >>> navigation2.publishTraverse(request, 'neverthere2')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...ThingSet..., name: 'neverthere2'
@@ -390,14 +387,12 @@ Let's create another subclass and add a stepthrough.
     >>> request.traversal_stack = ['prince', 'charming']
     >>> navigation3 = ThingSetNavigation3(thingset, request)
     >>> navigation3.publishTraverse(request, 'neverland')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...ThingSet..., name: 'charming'
     >>> request.traversal_stack = ['prince', 'charming']
     >>> navigation3 = ThingSetNavigation3(thingset, request)
     >>> navigation3.publishTraverse(request, 'neverland2')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...ThingSet..., name: 'charming'
diff --git a/lib/lp/services/webapp/doc/renamed-view.txt b/lib/lp/services/webapp/doc/renamed-view.txt
index 6e2805f..19f5b7a 100644
--- a/lib/lp/services/webapp/doc/renamed-view.txt
+++ b/lib/lp/services/webapp/doc/renamed-view.txt
@@ -91,7 +91,6 @@ raise an error. e.g. http://launchpad.test/ubuntu/+tickets/foo
     >>> request = LaunchpadTestRequest()
     >>> view = RenamedView(ubuntu, request, '+tickets')
     >>> view.publishTraverse(request, u'foo')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
      ...
     zope.publisher.interfaces.NotFound: Object: <Distribution 'Ubuntu' (ubuntu)>, name: 'foo'
diff --git a/lib/lp/services/webapp/doc/test_adapter.txt b/lib/lp/services/webapp/doc/test_adapter.txt
index f74065a..b115f8e 100644
--- a/lib/lp/services/webapp/doc/test_adapter.txt
+++ b/lib/lp/services/webapp/doc/test_adapter.txt
@@ -212,7 +212,6 @@ timeout by sleeping for 200ms with a 100ms statement timeout:
     >>> print(current_statement_timeout(store))
     100ms
     >>> store.execute(six.ensure_str('SELECT pg_sleep(0.200)'), noresult=True)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.services.webapp.adapter.LaunchpadTimeoutError: Statement: 'SELECT pg_sleep(0.200)' Parameters:() Original error: QueryCanceledError('canceling statement due to statement timeout\n',)
@@ -283,7 +282,6 @@ This final invokation, we will actually sleep to ensure that the
 timeout being reported by PostgreSQL is actually working:
 
     >>> store.execute(six.ensure_str('SELECT pg_sleep(0.2)'), noresult=True)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.services.webapp.adapter.LaunchpadTimeoutError: Statement: 'SELECT pg_sleep(0.2)' Parameters:() Original error: QueryCanceledError('canceling statement due to statement timeout\n',)
@@ -342,7 +340,6 @@ another query:
 
     >>> set_request_started(time.time() - 60)
     >>> store.execute('SELECT 2', noresult=True)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.webapp.adapter.RequestExpired: request expired.
@@ -362,7 +359,6 @@ transaction will be doomed:
     >>> transaction.get().isDoomed()
     True
     >>> transaction.commit()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     transaction.interfaces.DoomedTransaction: transaction doomed, cannot commit
@@ -406,7 +402,6 @@ remove the timout:
     >>> thread.start()
     >>> _ = started_request.wait()
     >>> store.execute('SELECT 1', noresult=True)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.webapp.adapter.RequestExpired: request expired.
@@ -447,7 +442,6 @@ config section.  By default we connect as "launchpad"
     >>> store.execute("""
     ...     INSERT INTO SourcePackageName(name) VALUES ('fnord4')
     ...     """, noresult=True)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     storm.database.ProgrammingError: permission denied for relation sourcepackagename
@@ -460,7 +454,6 @@ This is not reset at the end of the transaction:
     >>> store.execute("""
     ...     INSERT INTO SourcePackageName(name) VALUES ('fnord4')
     ...     """, noresult=True)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     storm.database.ProgrammingError: permission denied for relation sourcepackagename
diff --git a/lib/lp/services/webapp/doc/test_adapter_permissions.txt b/lib/lp/services/webapp/doc/test_adapter_permissions.txt
index 17423b5..f86b958 100644
--- a/lib/lp/services/webapp/doc/test_adapter_permissions.txt
+++ b/lib/lp/services/webapp/doc/test_adapter_permissions.txt
@@ -20,7 +20,7 @@ If a SLAVE_FLAVOR store is requested, it should trap all writes.
     >>> main_slave = getUtility(IStoreSelector).get(MAIN_STORE, SLAVE_FLAVOR)
     >>> janitor = main_slave.find(Person, name='janitor').one()
     >>> janitor.display_name = 'Ben Dover'
-    >>> transaction.commit()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> transaction.commit()
     Traceback (most recent call last):
     ...
     storm.database.InternalError: ...
@@ -30,7 +30,7 @@ Test this once more to ensure the settings stick across transactions.
     >>> transaction.abort()
     >>> t = transaction.begin()
     >>> main_slave.find(Person, name='janitor').one().display_name = 'BenD'
-    >>> transaction.commit()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> transaction.commit()
     Traceback (most recent call last):
     ...
     storm.database.InternalError: ...
diff --git a/lib/lp/services/webapp/doc/test_adapter_timeout.txt.disabled b/lib/lp/services/webapp/doc/test_adapter_timeout.txt.disabled
index c1955cf..dbf7a36 100644
--- a/lib/lp/services/webapp/doc/test_adapter_timeout.txt.disabled
+++ b/lib/lp/services/webapp/doc/test_adapter_timeout.txt.disabled
@@ -84,7 +84,6 @@ Now we actually demonstrate the behaviour.  The view did raise a TimeoutError.
 
     >>> browser = setupBrowser()
     >>> browser.open('http://launchpad.test/doom_test')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.timeout.TimeoutError: ...
diff --git a/lib/lp/services/webapp/doc/timeout.txt b/lib/lp/services/webapp/doc/timeout.txt
index 1494852..f3a55d2 100644
--- a/lib/lp/services/webapp/doc/timeout.txt
+++ b/lib/lp/services/webapp/doc/timeout.txt
@@ -50,7 +50,7 @@ If the timeout is already expired, a RequestExpired error is raised:
     >>> from lp.services.webapp.adapter import clear_request_started
     >>> clear_request_started()
     >>> adapter.set_request_started(time.time()-12)
-    >>> timeout_func()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> timeout_func()
     Traceback (most recent call last):
       ...
     lp.services.webapp.adapter.RequestExpired: request expired.
@@ -61,7 +61,7 @@ Same thing if a function decorated using @with_timeout is called.
     >>> @with_timeout()
     ... def wait_a_little():
     ...     time.sleep(1)
-    >>> wait_a_little()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> wait_a_little()
     Traceback (most recent call last):
       ...
     lp.services.webapp.adapter.RequestExpired: request expired.
diff --git a/lib/lp/services/webapp/doc/webapp-publication.txt b/lib/lp/services/webapp/doc/webapp-publication.txt
index 75497a1..157d674 100644
--- a/lib/lp/services/webapp/doc/webapp-publication.txt
+++ b/lib/lp/services/webapp/doc/webapp-publication.txt
@@ -530,7 +530,6 @@ UnexpectedFormData is raised if more than one value was submitted for
 the field:
 
     >>> request.form_ng.getOne('items_field')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lp.app.errors.UnexpectedFormData: ...
@@ -790,7 +789,6 @@ the Talisker logging context.
     ... except:
     ...     publication.handleException(
     ...         None, request, sys.exc_info(), retry_allowed=True)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.Retry: foo
@@ -820,7 +818,6 @@ the Talisker logging context.
     ...     exc_info = sys.exc_info()
     >>> publication.handleException(
     ...     None, request, exc_info, retry_allowed=True)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.Retry: foo DisconnectionError
@@ -854,7 +851,6 @@ WSGI env.
     ... except:
     ...     publication.handleException(
     ...         None, request, sys.exc_info(), retry_allowed=True)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.Retry: foo
@@ -1183,7 +1179,6 @@ raised, though.
     >>> form2['oauth_nonce'] = '1764572616e48616d6d65724c61686'
     >>> test_request = LaunchpadTestRequest(form=form2)
     >>> publication.getPrincipal(test_request)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.oauth.interfaces.TokenException: Expired token...
@@ -1195,7 +1190,6 @@ raised, though.
     >>> form2['oauth_nonce'] = '4572616e48616d6d65724c61686176'
     >>> test_request = LaunchpadTestRequest(form=form2)
     >>> publication.getPrincipal(test_request)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.oauth.interfaces.TokenException: Unknown access token...
@@ -1207,7 +1201,6 @@ correct.
     >>> form2['oauth_consumer_key'] += 'z'
     >>> test_request = LaunchpadTestRequest(form=form2)
     >>> publication.getPrincipal(test_request)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: Unknown consumer (foobar123451432z).
@@ -1217,7 +1210,6 @@ correct.
     >>> form2['oauth_nonce'] = '2616e48616d6d65724c61686176457'
     >>> test_request = LaunchpadTestRequest(form=form2)
     >>> publication.getPrincipal(test_request)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.oauth.interfaces.TokenException: Invalid signature.
@@ -1232,7 +1224,6 @@ The user's account must be active.
     >>> login('salgado@xxxxxxxxxx')
     >>> test_request = LaunchpadTestRequest(form=form)
     >>> publication.getPrincipal(test_request)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.services.oauth.interfaces.TokenException: Inactive account.
diff --git a/lib/lp/services/webservice/doc/launchpadlib.txt b/lib/lp/services/webservice/doc/launchpadlib.txt
index b0537fe..25d2e0b 100644
--- a/lib/lp/services/webservice/doc/launchpadlib.txt
+++ b/lib/lp/services/webservice/doc/launchpadlib.txt
@@ -17,7 +17,6 @@ if a specific user exists...
     '/'
 
     >>> browser.open('%s/~stimpy' % root_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     urllib.error.HTTPError: HTTP Error 404: Not Found
diff --git a/lib/lp/services/webservice/stories/launchpadlib.txt b/lib/lp/services/webservice/stories/launchpadlib.txt
index 41381f4..6dc5ee5 100644
--- a/lib/lp/services/webservice/stories/launchpadlib.txt
+++ b/lib/lp/services/webservice/stories/launchpadlib.txt
@@ -79,7 +79,6 @@ But trying to access information that requires a logged in user
 results in an error.
 
     >>> print(lp_anon.me.name)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ...
     lazr.restfulclient.errors.Unauthorized: HTTP Error 401: Unauthorized...
diff --git a/lib/lp/soyuz/browser/tests/archive-views.txt b/lib/lp/soyuz/browser/tests/archive-views.txt
index 7d90cf0..d59c774 100644
--- a/lib/lp/soyuz/browser/tests/archive-views.txt
+++ b/lib/lp/soyuz/browser/tests/archive-views.txt
@@ -1341,7 +1341,6 @@ value is submitted.
     PPA for No Privileges Person [~no-priv/ubuntu/ppa]
 
     >>> print(archive_widget.getInputValue())
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.formlib.interfaces.WidgetInputError: ('destination_archive', ...'Destination PPA', RequiredMissing('destination_archive'))
diff --git a/lib/lp/soyuz/browser/tests/distroseriesqueue-views.txt b/lib/lp/soyuz/browser/tests/distroseriesqueue-views.txt
index 0816c39..7045fd8 100644
--- a/lib/lp/soyuz/browser/tests/distroseriesqueue-views.txt
+++ b/lib/lp/soyuz/browser/tests/distroseriesqueue-views.txt
@@ -79,7 +79,6 @@ If a invalid integer is posted it raises.
     >>> warty = ubuntu['warty']
     >>> queue_view = queryMultiAdapter((warty, request), name="+queue")
     >>> queue_view.setupQueueList()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: No suitable status found for value "10"
diff --git a/lib/lp/soyuz/doc/archive.txt b/lib/lp/soyuz/doc/archive.txt
index e3799c7..01b4bdf 100644
--- a/lib/lp/soyuz/doc/archive.txt
+++ b/lib/lp/soyuz/doc/archive.txt
@@ -89,7 +89,6 @@ build dependencies on the context PPA.  Its default value is None:
 Amending it as an unprivileged user results in failure:
 
     >>> cprov_archive.external_dependencies = "test"
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (..., 'external_dependencies', 'launchpad.Admin')
@@ -116,7 +115,6 @@ once a IArchive is created. Changing those values would affect the way
 archives are published on disk.
 
     >>> cprov_archive.purpose = ArchivePurpose.COPY
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ('purpose', <Archive at ...>)
@@ -137,7 +135,6 @@ It is only editable by someone with launchpad.Edit permissions:
 
     >>> login(ANONYMOUS)
     >>> cprov_archive.status = ArchiveStatus.ACTIVE
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -154,7 +151,6 @@ deleted.
     >>> login("celso.providelo@xxxxxxxxxxxxx")
 
     >>> cprov_archive.name = 'no-it-will-not-change-yet'
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (..., 'name', 'launchpad.Admin')
@@ -345,14 +341,12 @@ filter is not passed too.
 
     >>> moz_version_lookup = cprov_archive.getAllPublishedBinaries(
     ...     version='1.0')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.VersionRequiresName: The 'version' parameter can be used only together with the 'name' parameter.
 
     >>> moz_version_lookup = cprov_archive.getPublishedOnDiskBinaries(
     ...     version='1.0')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.VersionRequiresName: The 'version' parameter can be used only together with the 'name' parameter.
@@ -827,7 +821,6 @@ dependency is published in Mark's PPA.
 
     >>> no_priv.archive.addArchiveDependency(
     ...     cprov.archive, release_pocket, main_component)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.ArchiveDependencyError: This dependency is already registered.
@@ -836,7 +829,6 @@ dependency is published in Mark's PPA.
 
     >>> no_priv.archive.addArchiveDependency(
     ...     no_priv.archive, release_pocket, main_component)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.ArchiveDependencyError: An archive should not depend on itself.
@@ -869,7 +861,6 @@ Only one dependency per archive can be added.
     >>> no_priv.archive.addArchiveDependency(
     ...     ubuntu.main_archive, PackagePublishingPocket.RELEASE,
     ...     getUtility(IComponentSet)['main'])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.ArchiveDependencyError: This dependency is already registered.
@@ -899,7 +890,6 @@ RELEASE or other components than 'main'.
     >>> no_priv.archive.addArchiveDependency(
     ...     mark.archive, PackagePublishingPocket.UPDATES,
     ...     main_component)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.ArchiveDependencyError: Non-primary archives only support the RELEASE pocket.
@@ -907,7 +897,6 @@ RELEASE or other components than 'main'.
     >>> no_priv.archive.addArchiveDependency(
     ...     mark.archive, release_pocket,
     ...     getUtility(IComponentSet)['universe'])
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.ArchiveDependencyError: Non-primary archives only support the 'main' component.
@@ -1680,7 +1669,6 @@ anacronism can be removed.
 
     >>> joes_ppa.newComponentUploader(
     ...     carlos, "universe")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.InvalidComponent: Component for PPAs should be 'main'
@@ -1690,7 +1678,6 @@ You'll get the same error if you use a component object that's not main.
     >>> universe = getUtility(IComponentSet)['universe']
     >>> joes_ppa.newComponentUploader(
     ...     carlos, universe)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.InvalidComponent: Component for PPAs should be 'main'
@@ -1902,7 +1889,6 @@ release pocket, but to do so we must have edit permissions on the archive.
     >>> sources = ["package1", "package2"]
     >>> mark.archive.syncSources(
     ...     sources, cprov.archive, "release", person=None)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -1928,7 +1914,6 @@ Repeating this source copy gives an error:
 
     >>> mark.archive.syncSources(
     ...     sources, cprov.archive, "release", person=mark)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.CannotCopy: package1 1.1 in hoary (same version already building in the destination archive for Hoary) package2 1.0 in hoary (same version already building in the destination archive for Hoary)
@@ -1938,7 +1923,6 @@ Repeating this copy with binaries also gives an error:
     >>> mark.archive.syncSources(
     ...     sources, cprov.archive, "release", include_binaries=True,
     ...     person=mark)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.CannotCopy: package1 1.1 in hoary (source has no binaries to be copied) package2 1.0 in hoary (source has no binaries to be copied)
@@ -1948,14 +1932,12 @@ all result in a NotFound exception:
 
     >>> mark.archive.syncSources(["bogus"], cprov.archive, "release",
     ...     person=mark)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.registry.errors.NoSuchSourcePackageName: No such source package: 'bogus'.
 
     >>> mark.archive.syncSources(sources, cprov.archive, "badpocket",
     ...     person=mark)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.PocketNotFound: No such pocket: 'BADPOCKET'.
@@ -1963,7 +1945,6 @@ all result in a NotFound exception:
     >>> mark.archive.syncSources(
     ...     sources, cprov.archive, "release", to_series="badseries",
     ...     person=mark)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.registry.errors.NoSuchDistroSeries: No such distribution series: 'badseries'.
@@ -1971,7 +1952,6 @@ all result in a NotFound exception:
 If a package exists but not in the source archive, we get an error:
 
     >>> mark.archive.syncSources(["pack"], mark.archive, "release")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.CannotCopy: None of the supplied package names are published in PPA for Mark Shuttleworth.
@@ -2021,7 +2001,6 @@ As with syncSources() you need to have edit permission on the archive.
     >>> login(ANONYMOUS)
     >>> mark.archive.syncSource("pack", "1.0", cprov.archive, "release",
     ...     person=None)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -2039,7 +2018,6 @@ Login as mark to continue.
 If the supplied package exists but not in the source archive, we get an error:
 
     >>> mark.archive.syncSource("package3", "1.0", mark.archive, "release")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.CannotCopy: package3 is not published in PPA for Mark Shuttleworth.
@@ -2087,7 +2065,6 @@ or a CannotCopy exception is thrown.
 
     >>> mark.archive.syncSource(
     ...     "package3", "1.2", cprov.archive, "updates", person=mark)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.CannotCopy: PPA uploads must be for the RELEASE pocket.
diff --git a/lib/lp/soyuz/doc/archiveauthtoken.txt b/lib/lp/soyuz/doc/archiveauthtoken.txt
index 6dfabcd..88cb9c2 100644
--- a/lib/lp/soyuz/doc/archiveauthtoken.txt
+++ b/lib/lp/soyuz/doc/archiveauthtoken.txt
@@ -44,7 +44,6 @@ Create a subscription for Team Brad to joe's archive:
 It is not possible to create a token for the subscribed team.
 
     >>> joe_private_ppa.newAuthToken(teambrad)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.NoTokensForTeams: Subscription tokens can be created for individuals only.
@@ -61,7 +60,6 @@ By default the tokens are 20 characters long.
 It is not possible to create a second token when one already exists:
 
     >>> new_token = joe_private_ppa.newAuthToken(bradsmith)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archivesubscriber.ArchiveSubscriptionError: Brad Smith already has a token for PPA for Joe Smith.
@@ -118,7 +116,6 @@ which applies to the person in the token and launchpad admins.
     >>> login("no-priv@xxxxxxxxxxxxx")
 
     >>> token =  token_set.get(new_token.id)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -217,7 +214,6 @@ IArchive launchpad.Append (as for creating new tokens) or an admin.
 
     >>> login("no-priv@xxxxxxxxxxxxx")
     >>> new_token.deactivate()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/soyuz/doc/archivepermission.txt b/lib/lp/soyuz/doc/archivepermission.txt
index f3219d4..e32e39e 100644
--- a/lib/lp/soyuz/doc/archivepermission.txt
+++ b/lib/lp/soyuz/doc/archivepermission.txt
@@ -146,7 +146,6 @@ If the string is not a valid component, a NotFound exception is thrown:
 
     >>> uploaders = permission_set.uploadersForComponent(
     ...     ubuntu.main_archive, "badcomponent")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.ComponentNotFound: No such component: 'badcomponent'.
@@ -194,7 +193,6 @@ NoSuchSourcePackageName to be thrown.
 
     >>> uploaders = permission_set.uploadersForPackage(
     ...     ubuntu.main_archive, "fakepackage")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.registry.errors.NoSuchSourcePackageName: No such source package: 'fakepackage'.
diff --git a/lib/lp/soyuz/doc/archivesubscriber.txt b/lib/lp/soyuz/doc/archivesubscriber.txt
index 858a0f2..62db1c2 100644
--- a/lib/lp/soyuz/doc/archivesubscriber.txt
+++ b/lib/lp/soyuz/doc/archivesubscriber.txt
@@ -42,7 +42,6 @@ log in as an unprivileged user.
 We can create a new subscription for joesmith to access cprov's PPA like this:
 
     >>> new_sub = cprov.archive.newSubscription(joesmith, cprov)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -54,7 +53,6 @@ Users cannot create their own subscriptions either.  Log in as joesmith:
 
     >>> login("joe@xxxxxxxxxxx")
     >>> new_token = cprov.archive.newSubscription(joesmith, cprov)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -65,7 +63,6 @@ public:
     >>> login("celso.providelo@xxxxxxxxxxxxx")
     >>> new_sub = cprov.archive.newSubscription(
     ...     joesmith, cprov, description=u"subscription for joesmith")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.ArchiveNotPrivate: Only private archives can have subscriptions.
@@ -181,7 +178,6 @@ cannot be created:
 
     >>> new_sub = cprov_private_ppa.newSubscription(
     ...     joesmith, cprov, description=u"subscription for joesmith")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.archive.AlreadySubscribed: Joe Smith already has a current subscription for 'PPA named p3a for Celso Providelo'.
@@ -246,7 +242,6 @@ admins.
     >>> login("no-priv@xxxxxxxxxxxxx")
 
     >>> sub = sub_set.getBySubscriber(new_sub.subscriber)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -359,7 +354,6 @@ IPerson:
 
     >>> login("no-priv@xxxxxxxxxxxxx")
     >>> urls = joesmith.getArchiveSubscriptionURLs(no_priv)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized
@@ -388,7 +382,6 @@ Trying to set the properties as the subscribed person will fail:
 
     >>> from lp.services.database.constants import UTC_NOW
     >>> new_sub.date_expires = UTC_NOW
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -408,13 +401,11 @@ We can also do this as an admin.
 The subscriber and registrant properties are not editable.
 
     >>> new_sub.subscriber = cprov
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ...
 
     >>> new_sub.registrant = joesmith
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.ForbiddenAttribute: ...
@@ -429,7 +420,6 @@ IArchive launchpad.Append (as for creating new tokens) or an admin.
 
     >>> login("no-priv@xxxxxxxxxxxxx")
     >>> new_sub.cancel()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -462,7 +452,6 @@ We can cancel subscriptions in bulk:
     ...     cprov_private_ppa.newSubscription(factory.makePerson(), cprov)
     ...     for _ in range(3)]
     >>> sub_set.cancel([subs[0].id, subs[1].id], cprov)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/soyuz/doc/build-files.txt b/lib/lp/soyuz/doc/build-files.txt
index 8a3a19c..8c20bf8 100644
--- a/lib/lp/soyuz/doc/build-files.txt
+++ b/lib/lp/soyuz/doc/build-files.txt
@@ -36,7 +36,6 @@ following file type in its context.
 Unsupported filename lookups also result in a `NotFoundError`.
 
     >>> build.getFileByName('biscuit.cookie')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...'biscuit.cookie'
@@ -44,7 +43,6 @@ Unsupported filename lookups also result in a `NotFoundError`.
 And unreachable files in `NotFoundError`.
 
     >>> build.getFileByName('boing.changes')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...'boing.changes'
diff --git a/lib/lp/soyuz/doc/distroseriesqueue.txt b/lib/lp/soyuz/doc/distroseriesqueue.txt
index 12393e2..29a4c67 100644
--- a/lib/lp/soyuz/doc/distroseriesqueue.txt
+++ b/lib/lp/soyuz/doc/distroseriesqueue.txt
@@ -393,7 +393,7 @@ the look up code won't be able to identify any duplications:
 As expected the second item acceptance will fail and the item will
 remain in the original queue
 
-    >>> dup_two.setAccepted()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> dup_two.setAccepted()
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.queue.QueueInconsistentStateError: The source cnews - 1.0 is already accepted in ubuntu/breezy-autotest and you cannot upload the same version within the same distribution. You have to modify the source version and re-upload.
@@ -423,7 +423,7 @@ test after the former accepted item was published (DONE queue)
 
 The protection code should also identify dups with items in DONE queue
 
-    >>> dup_two.setAccepted()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> dup_two.setAccepted()
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.queue.QueueInconsistentStateError: The source cnews - 1.0 is already accepted in ubuntu/breezy-autotest and you cannot upload the same version within the same distribution. You have to modify the source version and re-upload.
@@ -592,7 +592,6 @@ an error:
     >>> print(item.overrideSource(
     ...     new_component=restricted, new_section=web,
     ...     allowed_components=(universe,)))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.queue.QueueAdminUnauthorizedError: No rights to override to restricted
@@ -603,7 +602,6 @@ is "main":
     >>> print(item.overrideSource(
     ...     new_component=restricted, new_section=web,
     ...     allowed_components=(restricted,)))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.queue.QueueAdminUnauthorizedError: No rights to override from main
@@ -640,14 +638,12 @@ Similarly for binaries:
     ...     }]
     >>> print(item.overrideBinaries(
     ...     binary_changes, allowed_components=(universe,)))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.queue.QueueAdminUnauthorizedError: No rights to override to restricted
 
     >>> print(item.overrideBinaries(
     ...     binary_changes, allowed_components=(restricted,)))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.queue.QueueAdminUnauthorizedError: No rights to override from main
diff --git a/lib/lp/soyuz/doc/package-diff.txt b/lib/lp/soyuz/doc/package-diff.txt
index aaeb81d..5bea8f8 100644
--- a/lib/lp/soyuz/doc/package-diff.txt
+++ b/lib/lp/soyuz/doc/package-diff.txt
@@ -102,7 +102,6 @@ error:
 
     >>> dup_diff = pmount_from.requestDiffTo(
     ...     requester=cprov, to_sourcepackagerelease=pmount_to)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.soyuz.interfaces.packagediff.PackageDiffAlreadyRequested: diff from 0.1-1 to 0.1-2 has already been requested
diff --git a/lib/lp/soyuz/doc/publishing-security.txt b/lib/lp/soyuz/doc/publishing-security.txt
index 37ec800..4e5406e 100644
--- a/lib/lp/soyuz/doc/publishing-security.txt
+++ b/lib/lp/soyuz/doc/publishing-security.txt
@@ -46,13 +46,11 @@ But when querying the private PPA, anonymous access will be refused:
 
     >>> login(ANONYMOUS)
     >>> source_pub = private_ppa.getPublishedSources().first()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
 
     >>> binary_pub = private_ppa.getAllPublishedBinaries()[0]
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -61,13 +59,11 @@ As is for a regular user.
 
     >>> login('no-priv@xxxxxxxxxxxxx')
     >>> source_pub = private_ppa.getPublishedSources().first()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
 
     >>> binary_pub = private_ppa.getAllPublishedBinaries()[0]
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/soyuz/stories/distroseries/add-architecture.txt b/lib/lp/soyuz/stories/distroseries/add-architecture.txt
index 81a9a18..29ca1d9 100644
--- a/lib/lp/soyuz/stories/distroseries/add-architecture.txt
+++ b/lib/lp/soyuz/stories/distroseries/add-architecture.txt
@@ -41,12 +41,10 @@ registered.
 
     >>> user_browser.open('http://launchpad.test/ubuntu/hoary')
     >>> user_browser.getLink('Add architecture')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> user_browser.open('http://launchpad.test/ubuntu/hoary/+addport')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/soyuz/stories/ppa/xx-copy-packages.txt b/lib/lp/soyuz/stories/ppa/xx-copy-packages.txt
index de0f257..95f1b67 100644
--- a/lib/lp/soyuz/stories/ppa/xx-copy-packages.txt
+++ b/lib/lp/soyuz/stories/ppa/xx-copy-packages.txt
@@ -33,14 +33,12 @@ access 'Copy package' page from any PPA.
     >>> anon_browser.open(
     ...     'http://launchpad.test/~cprov/+archive/ppa/+packages')
     >>> anon_browser.getLink('Copy packages').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> anon_browser.open(
     ...     'http://launchpad.test/~cprov/+archive/ppa/+copy-packages')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ... 'launchpad.AnyPerson')
@@ -308,7 +306,6 @@ Hence the archive's title does not link back to the source archive
 (as would be the case with a source PPA).
 
     >>> jblack_browser.getLink("Primary Archive for Ubuntu Linux")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/soyuz/stories/ppa/xx-delete-packages.txt b/lib/lp/soyuz/stories/ppa/xx-delete-packages.txt
index 9a8b620..6f44763 100644
--- a/lib/lp/soyuz/stories/ppa/xx-delete-packages.txt
+++ b/lib/lp/soyuz/stories/ppa/xx-delete-packages.txt
@@ -11,14 +11,12 @@ console, even if they try the URL directly.
     >>> anon_browser.open(
     ...     'http://launchpad.test/~cprov/+archive/ppa/+packages')
     >>> anon_browser.getLink('Delete packages').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> anon_browser.open(
     ...     'http://launchpad.test/~cprov/+archive/ppa/+delete-packages')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ..., 'launchpad.Edit')
@@ -26,14 +24,12 @@ console, even if they try the URL directly.
     >>> user_browser.open(
     ...     'http://launchpad.test/~cprov/+archive/ppa/+packages')
     >>> user_browser.getLink('Delete packages').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> user_browser.open(
     ...    'http://launchpad.test/~cprov/+archive/ppa/+delete-packages')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ..., 'launchpad.Edit')
@@ -289,7 +285,6 @@ the 'Delete packages' link.
     >>> admin_browser.open(
     ...     'http://launchpad.test/~no-priv/+archive/ppa/+packages')
     >>> admin_browser.getLink('Delete packages').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/soyuz/stories/ppa/xx-edit-dependencies.txt b/lib/lp/soyuz/stories/ppa/xx-edit-dependencies.txt
index 7d2f61a..8467076 100644
--- a/lib/lp/soyuz/stories/ppa/xx-edit-dependencies.txt
+++ b/lib/lp/soyuz/stories/ppa/xx-edit-dependencies.txt
@@ -11,28 +11,24 @@ edit dependencies, even if they try the URL directly.
 
     >>> anon_browser.open('http://launchpad.test/~cprov/+archive/ubuntu/ppa')
     >>> anon_browser.getLink('Edit PPA dependencies').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> anon_browser.open(
     ...     'http://launchpad.test/~cprov/+archive/ubuntu/ppa/+edit-dependencies')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ..., 'launchpad.Edit')
 
     >>> user_browser.open('http://launchpad.test/~cprov/+archive/ubuntu/ppa')
     >>> user_browser.getLink('Edit PPA dependencies').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> user_browser.open(
     ...    'http://launchpad.test/~cprov/+archive/ubuntu/ppa/+edit-dependencies')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ..., 'launchpad.Edit')
@@ -194,7 +190,6 @@ aware of this condition.
     PPA for No Privileges Person (included ... ago)
 
     >>> anon_browser.getLink('PPA for Mark Shuttleworth')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/soyuz/stories/ppa/xx-ppa-files.txt b/lib/lp/soyuz/stories/ppa/xx-ppa-files.txt
index ca2e9a1..00fef87 100644
--- a/lib/lp/soyuz/stories/ppa/xx-ppa-files.txt
+++ b/lib/lp/soyuz/stories/ppa/xx-ppa-files.txt
@@ -244,7 +244,6 @@ Retrieve file information for using the direct HTTP browsing API.
 Sample Person can't access the file.
 
     >>> browser.open(dsc_file_lp_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized
@@ -268,7 +267,6 @@ Binary files are served via '+files' rather than '+sourcefiles'.
     ...     deb_file.filename)
     >>> logout()
     >>> browser.open(deb_file_lp_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized
@@ -325,7 +323,6 @@ binaries across to no-priv's public ppa.
 The filename must be at the end of the URL. No further segments are permitted.
 
     >>> browser.open(file_lp_url + '/foo')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/soyuz/stories/ppa/xx-ppa-navigation.txt b/lib/lp/soyuz/stories/ppa/xx-ppa-navigation.txt
index d8e0b49..605f805 100644
--- a/lib/lp/soyuz/stories/ppa/xx-ppa-navigation.txt
+++ b/lib/lp/soyuz/stories/ppa/xx-ppa-navigation.txt
@@ -143,14 +143,12 @@ inactive:
     >>> 'Previous' in anon_browser.contents
     True
     >>> anon_browser.getLink('Previous')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
     >>> 'First' in anon_browser.contents
     True
     >>> anon_browser.getLink('First')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
@@ -170,14 +168,12 @@ This is the last page, so the next and last links are inactive.
     >>> 'Next' in anon_browser.contents
     True
     >>> anon_browser.getLink('Next')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
     >>> 'Last' in anon_browser.contents
     True
     >>> anon_browser.getLink('Last')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
       ..
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/soyuz/stories/ppa/xx-ppa-packages.txt b/lib/lp/soyuz/stories/ppa/xx-ppa-packages.txt
index 21cd1a5..536ff72 100644
--- a/lib/lp/soyuz/stories/ppa/xx-ppa-packages.txt
+++ b/lib/lp/soyuz/stories/ppa/xx-ppa-packages.txt
@@ -223,7 +223,6 @@ But Joe himself will not see the link.
     ...     auth="Basic joe@xxxxxxxxxxx:test")
     >>> joe_browser.open(expander_url)
     >>> joe_browser.getLink("PPA named p3a for Celso Providelo")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -232,7 +231,6 @@ And neither can an anonymous user.
 
     >>> anon_browser.open(expander_url)
     >>> anon_browser.getLink("PPA named p3a for Celso Providelo")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -242,7 +240,6 @@ pagelet isn't publicly available.
 
     >>> anon_browser.open(
     ...     "http://launchpad.test/~cprov/+archive/ubuntu/p3a/+repository-size";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (..., 'launchpad.View')
diff --git a/lib/lp/soyuz/stories/ppa/xx-ppa-workflow.txt b/lib/lp/soyuz/stories/ppa/xx-ppa-workflow.txt
index 3bb0154..6c5f10f 100644
--- a/lib/lp/soyuz/stories/ppa/xx-ppa-workflow.txt
+++ b/lib/lp/soyuz/stories/ppa/xx-ppa-workflow.txt
@@ -167,7 +167,6 @@ Even if we try the URL directly:
 
     >>> cprov_browser.open(
     ...    "http://launchpad.test/~landscape-developers/+activate-ppa";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (..., 'launchpad.Edit')
@@ -320,7 +319,6 @@ virtualisation settings, and so on.
 
     >>> sample_browser.open("http://launchpad.test/~jblack/+archive";)
     >>> print(sample_browser.getLink("Administer archive"))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -352,7 +350,6 @@ Trying to shortcut the URL as a non-privileged user does not work:
 
     >>> sample_browser.open(
     ...     "http://launchpad.test/~jblack/+archive/ppa/+admin";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -678,13 +675,11 @@ required.
 And direct access to the PPA page is also denied.
 
     >>> anon_browser.open("http://launchpad.test/~cprov/+archive/edge";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
 
     >>> browser.open("http://launchpad.test/~cprov/+archive/edge";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -758,7 +753,6 @@ navigation menu.
 
     >>> anon_browser.open("http://launchpad.test/~no-priv/+archive/ppa";)
     >>> print(anon_browser.getLink("Delete PPA"))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -812,20 +806,17 @@ However, most of the action links are removed for deleted PPAs, so you can
 no longer "Delete packages", "Edit PPA dependencies", or "Change details".
 
     >>> print(no_priv_browser.getLink("Change details"))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> print(no_priv_browser.getLink("Edit PPA dependencies"))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> no_priv_browser.getLink("View package details").click()
     >>> print(no_priv_browser.getLink("Delete packages"))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/soyuz/stories/ppa/xx-private-ppa-subscriptions.txt b/lib/lp/soyuz/stories/ppa/xx-private-ppa-subscriptions.txt
index 61bc7a9..b47dc6a 100644
--- a/lib/lp/soyuz/stories/ppa/xx-private-ppa-subscriptions.txt
+++ b/lib/lp/soyuz/stories/ppa/xx-private-ppa-subscriptions.txt
@@ -13,7 +13,6 @@ Public PPAs do not have an option for managing subscriptions:
     ...     auth="Basic celso.providelo@xxxxxxxxxxxxx:test")
     >>> cprov_browser.open("http://launchpad.test/~cprov/+archive/ppa";)
     >>> cprov_browser.getLink("Manage subscriptions")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -145,7 +144,6 @@ create tokens.
 
     >>> joe_browser.open(
     ...     "http://launchpad.test/~teamjoe/+archivesubscriptions";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
@@ -223,7 +221,6 @@ Attempting to browse directly to a subscription
 
     >>> joe_browser.open(
     ...     "http://launchpad.test/~joesmith/+archivesubscriptions/foo";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/soyuz/stories/ppa/xx-private-ppas.txt b/lib/lp/soyuz/stories/ppa/xx-private-ppas.txt
index 41ed42b..51e0d79 100644
--- a/lib/lp/soyuz/stories/ppa/xx-private-ppas.txt
+++ b/lib/lp/soyuz/stories/ppa/xx-private-ppas.txt
@@ -105,13 +105,11 @@ Accessing the Archive Pages
 A non-privileged user cannot access the private PPA pages.
 
     >>> browser.open("http://launchpad.test/~cprov/+archive/p3a";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
 
     >>> browser.open("http://launchpad.test/~landscape-developers/+archive";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -140,7 +138,6 @@ link to the PPA page is not present.
     None
 
     >>> browser.getLink("PPA for Landscape Developers").click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/soyuz/stories/ppa/xx-ubuntu-ppas.txt b/lib/lp/soyuz/stories/ppa/xx-ubuntu-ppas.txt
index 1c714d2..159f003 100644
--- a/lib/lp/soyuz/stories/ppa/xx-ubuntu-ppas.txt
+++ b/lib/lp/soyuz/stories/ppa/xx-ubuntu-ppas.txt
@@ -63,7 +63,6 @@ Currently we only support PPAs for a limited number of distros. The
 
     >>> anon_browser.open("http://launchpad.test/debian";)
     >>> anon_browser.getLink("Personal Package Archives")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -689,13 +688,11 @@ either via the new-style URL or the compatibility redirection, will
 result in a NotFound error.
 
     >>> admin_browser.open("http://launchpad.test/~name16/+archive/ppa";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: Object: <Person at ... name16 (Foo Bar)>, name: '+archive'
 
     >>> admin_browser.open("http://launchpad.test/~name16/+archive";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: Object: <Person at ... name16 (Foo Bar)>, name: '+archive'
diff --git a/lib/lp/soyuz/stories/soyuz/xx-build-record.txt b/lib/lp/soyuz/stories/soyuz/xx-build-record.txt
index 637821e..9cb475d 100644
--- a/lib/lp/soyuz/stories/soyuz/xx-build-record.txt
+++ b/lib/lp/soyuz/stories/soyuz/xx-build-record.txt
@@ -298,7 +298,6 @@ retrying the build is not a possibility anymore.
     Build score:... Rescore build (What's this?)
 
     >>> admin_browser.getLink("Retry this build").click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -354,7 +353,6 @@ linkified. That's because its `DistroArchSeriesBinaryPackageRelease`
 page does not exist yet.
 
     >>> print(anon_browser.getLink('testing-bin-1.0'))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -383,7 +381,6 @@ Binary upload can also be awaiting approval in UNAPPROVED queue
     testing-bin-1.0
 
     >>> print(anon_browser.getLink('testing-bin-1.0'))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -408,7 +405,6 @@ xx-queue-pages.txt) this condition is presented in the build page.
     testing-bin-1.0
 
     >>> print(anon_browser.getLink('testing-bin-1.0'))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -497,7 +493,6 @@ packages, since they do not exist.
     Component: main
 
     >>> print(anon_browser.getLink('ppa-test - 1.0').url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -520,7 +515,6 @@ section for PPA builds.
     ppa-test-bin-1.0
 
     >>> print(anon_browser.getLink('ppa-test-bin-1.0').url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt b/lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt
index beb1430..c7cb750 100644
--- a/lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt
+++ b/lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt
@@ -277,7 +277,6 @@ code is prepared to raise the correct exception:
 
     >>> anon_browser.open(
     ...     "http://launchpad.test/+builds/bob/+history?build_state=foo";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: No suitable state found for value "foo"
@@ -289,7 +288,6 @@ form values are submitted:
     ...     "http://launchpad.test/ubuntu/+builds";
     ...     "?build_text=binutils&build_state=building"
     ...     "&build_text=binutils&build_state=all")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: No suitable state found for value "[...'building', ...'all']"
diff --git a/lib/lp/soyuz/stories/soyuz/xx-distribution-add.txt b/lib/lp/soyuz/stories/soyuz/xx-distribution-add.txt
index d635589..42fac4c 100644
--- a/lib/lp/soyuz/stories/soyuz/xx-distribution-add.txt
+++ b/lib/lp/soyuz/stories/soyuz/xx-distribution-add.txt
@@ -6,7 +6,6 @@ the distributions page:
 
     >>> user_browser.open("http://launchpad.test/distros";)
     >>> user_browser.getLink("Register a distribution")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -20,7 +19,6 @@ A launchpad admin sees the link to create a new distribution:
 A launchpad admin can create a new distribution:
 
     >>> user_browser.open("http://launchpad.test/distros/+add";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/soyuz/stories/soyuz/xx-distribution-archives.txt b/lib/lp/soyuz/stories/soyuz/xx-distribution-archives.txt
index e99db32..d779b95 100644
--- a/lib/lp/soyuz/stories/soyuz/xx-distribution-archives.txt
+++ b/lib/lp/soyuz/stories/soyuz/xx-distribution-archives.txt
@@ -161,7 +161,6 @@ when it's accessed anonymously.
 
     >>> anon_browser.open(
     ...     "http://launchpad.test/ubuntu/+archive/disabled-security-rebuild";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ... 'launchpad.SubscriberView')
diff --git a/lib/lp/soyuz/stories/soyuz/xx-distributionsourcepackagerelease-pages.txt b/lib/lp/soyuz/stories/soyuz/xx-distributionsourcepackagerelease-pages.txt
index 83d8a0b..b05ef78 100644
--- a/lib/lp/soyuz/stories/soyuz/xx-distributionsourcepackagerelease-pages.txt
+++ b/lib/lp/soyuz/stories/soyuz/xx-distributionsourcepackagerelease-pages.txt
@@ -85,7 +85,6 @@ in Launchpad if it exists.
     celso.providelo@xxxxxxxxxxxxx
 
     >>> user_browser.getLink('biscuit@xxxxxxxxxxxxx')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/soyuz/stories/soyuz/xx-distroarchseries-binpackages.txt b/lib/lp/soyuz/stories/soyuz/xx-distroarchseries-binpackages.txt
index ab9dc39..8f5d03a 100644
--- a/lib/lp/soyuz/stories/soyuz/xx-distroarchseries-binpackages.txt
+++ b/lib/lp/soyuz/stories/soyuz/xx-distroarchseries-binpackages.txt
@@ -54,7 +54,6 @@ link to the source package will not be present:
     >>> browser.open(
     ...     'http://launchpad.test/debian/woody/i386/pmount')
     >>> print(browser.getLink(id="source_package"))
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/soyuz/stories/soyuz/xx-distroarchseries.txt b/lib/lp/soyuz/stories/soyuz/xx-distroarchseries.txt
index 9178ed8..7a4ce27 100644
--- a/lib/lp/soyuz/stories/soyuz/xx-distroarchseries.txt
+++ b/lib/lp/soyuz/stories/soyuz/xx-distroarchseries.txt
@@ -98,7 +98,6 @@ Non privileged access to the admin page results in a 'Unauthorized'
 error.
 
     >>> user_browser.open("http://launchpad.test/ubuntu/warty/i386/+admin";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/soyuz/stories/soyuz/xx-package-diff.txt b/lib/lp/soyuz/stories/soyuz/xx-package-diff.txt
index e71f46e..2d89766 100644
--- a/lib/lp/soyuz/stories/soyuz/xx-package-diff.txt
+++ b/lib/lp/soyuz/stories/soyuz/xx-package-diff.txt
@@ -150,7 +150,6 @@ and "(pending)" is appended to the text as a further hint that it's not
 ready yet.
 
     >>> anon_browser.getLink('diff from 1.0-2 to 1.0-3')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/soyuz/stories/soyuz/xx-person-packages.txt b/lib/lp/soyuz/stories/soyuz/xx-person-packages.txt
index d4e2382..c6936d2 100644
--- a/lib/lp/soyuz/stories/soyuz/xx-person-packages.txt
+++ b/lib/lp/soyuz/stories/soyuz/xx-person-packages.txt
@@ -431,7 +431,6 @@ Please note also that disabled archives are not viewable by anonymous users.
     >>> update_cached_records()
     >>> logout()
     >>> anon_browser.open("http://launchpad.test/~cprov/+archive/ppa";)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: (..., 'browserDefault', 'launchpad.SubscriberView')
diff --git a/lib/lp/soyuz/stories/soyuz/xx-private-builds.txt b/lib/lp/soyuz/stories/soyuz/xx-private-builds.txt
index 205b77d..c27ccad 100644
--- a/lib/lp/soyuz/stories/soyuz/xx-private-builds.txt
+++ b/lib/lp/soyuz/stories/soyuz/xx-private-builds.txt
@@ -108,7 +108,6 @@ users:
     >>> anon_browser.open(
     ...     "http://launchpad.test/~cprov/+archive/ubuntu/p3a/+build/%s"; %
     ...     private_build_id)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/soyuz/stories/soyuz/xx-sourcepackage-changelog.txt b/lib/lp/soyuz/stories/soyuz/xx-sourcepackage-changelog.txt
index 74850ba..a78f610 100644
--- a/lib/lp/soyuz/stories/soyuz/xx-sourcepackage-changelog.txt
+++ b/lib/lp/soyuz/stories/soyuz/xx-sourcepackage-changelog.txt
@@ -53,7 +53,6 @@ The LP: #<number> entries are also linkified:
     'http://launchpad.test/bugs/999'
 
     >>> user_browser.getLink('#badid').url
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/soyuz/stories/webservice/xx-builders.txt b/lib/lp/soyuz/stories/webservice/xx-builders.txt
index c7503c1..c2de65d 100644
--- a/lib/lp/soyuz/stories/webservice/xx-builders.txt
+++ b/lib/lp/soyuz/stories/webservice/xx-builders.txt
@@ -57,7 +57,7 @@ have permission to save changes:
     >>> print(bob.active)
     True
     >>> bob.active = False
-    >>> bob.lp_save()  # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
+    >>> bob.lp_save()
     Traceback (most recent call last):
     ...
     lazr.restfulclient.errors.Unauthorized: ...
diff --git a/lib/lp/testing/doc/pagetest-helpers.txt b/lib/lp/testing/doc/pagetest-helpers.txt
index 1ebdeef..dfe3603 100644
--- a/lib/lp/testing/doc/pagetest-helpers.txt
+++ b/lib/lp/testing/doc/pagetest-helpers.txt
@@ -132,7 +132,6 @@ exception.
     ... </body>
     ... '''
     >>> find_tag_by_id(duplicate_id_content, 'duplicate')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.testing.pages.DuplicateIdError: Found 2 elements with id 'duplicate'
diff --git a/lib/lp/translations/browser/tests/pofile-views.txt b/lib/lp/translations/browser/tests/pofile-views.txt
index b120180..45b4751 100644
--- a/lib/lp/translations/browser/tests/pofile-views.txt
+++ b/lib/lp/translations/browser/tests/pofile-views.txt
@@ -443,7 +443,6 @@ The traversal value should be an integer.
 
     >>> request.method = 'GET'
     >>> navigation.traverse('foo')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...
@@ -451,7 +450,6 @@ The traversal value should be an integer.
 Also, translation message sequence numbers are always >= 1.
 
     >>> navigation.traverse('0')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...
@@ -460,7 +458,6 @@ The given sequence number, we also need that is part of the available ones,
 if we use a high one, we should detect it.
 
     >>> navigation.traverse('30')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: ...
diff --git a/lib/lp/translations/doc/browser-helpers.txt b/lib/lp/translations/doc/browser-helpers.txt
index 075ff13..924441e 100644
--- a/lib/lp/translations/doc/browser-helpers.txt
+++ b/lib/lp/translations/doc/browser-helpers.txt
@@ -135,7 +135,6 @@ parse_cformat_string
     >>> print(pretty(parse_cformat_string('%sfoo%%bar%s')))
     [('interpolation', '%s'), ('string', 'foo%%bar'), ('interpolation', '%s')]
     >>> parse_cformat_string('%')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.translations.browser.browser_helpers.UnrecognisedCFormatString: %
@@ -190,7 +189,6 @@ Test bad format strings are caught and passed through.
 
     >>> text = u'foo %z bar'
     >>> parse_cformat_string(text)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.translations.browser.browser_helpers.UnrecognisedCFormatString: foo %z bar
diff --git a/lib/lp/translations/doc/potranslation.txt b/lib/lp/translations/doc/potranslation.txt
index be0a5ff..55756d6 100644
--- a/lib/lp/translations/doc/potranslation.txt
+++ b/lib/lp/translations/doc/potranslation.txt
@@ -20,7 +20,6 @@ To get hold of a PO translation, use POTranslation.getByTranslation.
 However, if the translation doesn't already exist, you'll get an error.
 
     >>> got = POTranslation.getByTranslation("In Xanadu did Kubla Khan")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.NotFoundError: 'In Xanadu did Kubla Khan'
diff --git a/lib/lp/translations/doc/translationmessage-destroy.txt b/lib/lp/translations/doc/translationmessage-destroy.txt
index e32a113..0ce0770 100644
--- a/lib/lp/translations/doc/translationmessage-destroy.txt
+++ b/lib/lp/translations/doc/translationmessage-destroy.txt
@@ -22,7 +22,6 @@ Select an existing ITranslationMessage and try to remove it.
 It should not exist now.
 
     >>> translationmessage = TranslationMessage.get(1)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     storm.sqlobject.SQLObjectNotFound: ...
diff --git a/lib/lp/translations/stories/distribution/xx-distribution-change-language-pack-admins.txt b/lib/lp/translations/stories/distribution/xx-distribution-change-language-pack-admins.txt
index ff72214..1ad4304 100644
--- a/lib/lp/translations/stories/distribution/xx-distribution-change-language-pack-admins.txt
+++ b/lib/lp/translations/stories/distribution/xx-distribution-change-language-pack-admins.txt
@@ -9,14 +9,12 @@ owner, on the +select-language-pack-admin page.
     >>> browser = setupBrowser(auth='Basic test@xxxxxxxxxxxxx:test')
     >>> browser.open('http://translations.launchpad.test/ubuntu/')
     >>> browser.getLink('Set language pack administrator')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> browser.open(
     ...     'http://translations.launchpad.test/ubuntu/'
     ...     '+select-language-pack-admin')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/translations/stories/distribution/xx-distribution-translations.txt b/lib/lp/translations/stories/distribution/xx-distribution-translations.txt
index 01d5dde..f941a65 100644
--- a/lib/lp/translations/stories/distribution/xx-distribution-translations.txt
+++ b/lib/lp/translations/stories/distribution/xx-distribution-translations.txt
@@ -80,7 +80,6 @@ But we are already showing the status for the translation focus one,
 we should not have a link to it.
 
     >>> browser.getLink('5.04 The Hoary Hedgehog Release')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -131,7 +130,6 @@ But we are already showing the status for the translation focus one,
 we should not have a link to it.
 
     >>> browser.getLink('3.1 Sarge')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/translations/stories/distroseries/xx-distroseries-translations.txt b/lib/lp/translations/stories/distroseries/xx-distroseries-translations.txt
index f56e903..b90a663 100644
--- a/lib/lp/translations/stories/distroseries/xx-distroseries-translations.txt
+++ b/lib/lp/translations/stories/distroseries/xx-distroseries-translations.txt
@@ -11,7 +11,6 @@ In this case, we're asking for the translation overview for Hoary.
 The system is not showing non visible languages:
 
     >>> anon_browser.getLink('Spanish (Spain)')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -19,7 +18,6 @@ The system is not showing non visible languages:
 The system will not show English because it is not translatable:
 
     >>> anon_browser.getLink('English')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -33,7 +31,6 @@ Launchpad has an option to hide all of the translations for a distribution
 series.  The link to hide translations is not available to anonymous users:
 
     >>> anon_browser.getLink('Change settings')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -43,7 +40,6 @@ And the page is not available either:
     >>> anon_browser.open(
     ...     'http://translations.launchpad.test/ubuntu/hoary/'
     ...     '+translations-admin')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -74,7 +70,6 @@ Now, the translation status page will no longer display any languages to
 regular users.
 
     >>> user_browser.open('http://translations.launchpad.test/ubuntu/hoary')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.TranslationUnavailable: ...
@@ -85,7 +80,6 @@ the system tells them that they're not allowed to see those pages.
     >>> user_browser.handleErrors = True
     >>> user_browser.open(
     ...     'http://translations.launchpad.test/ubuntu/hoary/+lang/es')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     urllib.error.HTTPError: HTTP Error 503: Service Unavailable
@@ -106,14 +100,12 @@ should not viewed
 
     >>> user_browser.open(
     ...     'http://translations.launchpad.test/ubuntu/hoary/+lang/notexists')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
 
     >>> user_browser.open(
     ...     'http://translations.launchpad.test/ubuntu/hoary/+lang/en')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
@@ -124,7 +116,6 @@ non-administrative users.
     >>> user_browser.open(
     ...     'http://translations.launchpad.test/ubuntu/hoary/'
     ...     '+sources/evolution/+pots/evolution-2.2')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.TranslationUnavailable: ...
diff --git a/lib/lp/translations/stories/importqueue/xx-translation-import-queue-filtering.txt b/lib/lp/translations/stories/importqueue/xx-translation-import-queue-filtering.txt
index 042a14c..89435b9 100644
--- a/lib/lp/translations/stories/importqueue/xx-translation-import-queue-filtering.txt
+++ b/lib/lp/translations/stories/importqueue/xx-translation-import-queue-filtering.txt
@@ -262,7 +262,6 @@ An attempt to filter for an undefined status is an UnexpectedFormData.
     >>> browser.open(
     ...     'http://translations.launchpad.test/+imports?'
     ...     'field.filter_status=boguscode')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: Invalid status parameter.
@@ -400,7 +399,6 @@ mistyped URL, an UnexpectedFormData is raised.
     >>> browser.open(
     ...     'http://translations.launchpad.test/+imports?'
     ...     'field.filter_target=bogus/target')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: Unknown target.
diff --git a/lib/lp/translations/stories/productseries/xx-productseries-export-to-branch.txt b/lib/lp/translations/stories/productseries/xx-productseries-export-to-branch.txt
index 3473b45..11f209e 100644
--- a/lib/lp/translations/stories/productseries/xx-productseries-export-to-branch.txt
+++ b/lib/lp/translations/stories/productseries/xx-productseries-export-to-branch.txt
@@ -148,7 +148,6 @@ And of course, setting the translations branch requires edit privileges
 on the release series.
 
     >>> user_browser.open(link_page)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/translations/stories/productseries/xx-productseries-translation-export.txt b/lib/lp/translations/stories/productseries/xx-productseries-translation-export.txt
index 1d4ee93..337a29b 100644
--- a/lib/lp/translations/stories/productseries/xx-productseries-translation-export.txt
+++ b/lib/lp/translations/stories/productseries/xx-productseries-translation-export.txt
@@ -37,7 +37,6 @@ not available to anonymous visitors.
 
     >>> anon_browser.open('http://translations.launchpad.test/evolution/trunk/')
     >>> anon_browser.getLink('download')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -102,7 +101,6 @@ link for "Download translations" is hidden.
 
     >>> user_browser.open('http://translations.launchpad.test/bzr/')
     >>> user_browser.getLink('download')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/translations/stories/project/xx-project-translations.txt b/lib/lp/translations/stories/project/xx-project-translations.txt
index ffd8fe1..ab78c63 100644
--- a/lib/lp/translations/stories/project/xx-project-translations.txt
+++ b/lib/lp/translations/stories/project/xx-project-translations.txt
@@ -59,7 +59,6 @@ shouldn't appear in GNOME project translations page.
 
     >>> browser.open('http://translations.launchpad.test/gnome')
     >>> browser.getLink('alsa-utils')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -73,7 +72,6 @@ Let's confirm what we just stated.
 alsa-utils does not belong to GNOME project.
 
     >>> browser.getLink('alsa-utils')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/translations/stories/standalone/custom-language-codes.txt b/lib/lp/translations/stories/standalone/custom-language-codes.txt
index da03bda..350e052 100644
--- a/lib/lp/translations/stories/standalone/custom-language-codes.txt
+++ b/lib/lp/translations/stories/standalone/custom-language-codes.txt
@@ -149,7 +149,6 @@ This can be convenient for debugging.
 However all they get is a read-only version of the page.
 
     >>> user_browser.getLink("Add a custom language code").click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -157,7 +156,6 @@ However all they get is a read-only version of the page.
 The page for adding custom language codes is not accessible to them.
 
     >>> user_browser.open(add_page)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -179,13 +177,11 @@ unprivileged user can't remove it.
 
     >>> user_browser.getLink("no").click()
     >>> user_browser.getLink("remove custom language code")
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> user_browser.open(remove_page)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/translations/stories/standalone/xx-language.txt b/lib/lp/translations/stories/standalone/xx-language.txt
index 0606191..25dfa68 100644
--- a/lib/lp/translations/stories/standalone/xx-language.txt
+++ b/lib/lp/translations/stories/standalone/xx-language.txt
@@ -55,7 +55,6 @@ the system detects it and warns the user.
 But, with a new language, it will succeed.
 
     >>> browser.open('http://translations.launchpad.test/+languages/foos')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
@@ -76,14 +75,12 @@ A normal user will not be able to see or use the url to add languages.
     http://translations.launchpad.test/+languages
 
     >>> user_browser.getLink('Add new language')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> user_browser.open(
     ...     'http://translations.launchpad.test/+languages/+add')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -204,14 +201,12 @@ Finally, there is the edit form to change language basic information.
 A plain user is not able to reach it.
 
     >>> user_browser.getLink('Administer')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> user_browser.open(
     ...     'http://translations.launchpad.test/+languages/es/+admin')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -310,7 +305,6 @@ That was a renaming action, which means that language code 'es' doesn't
 exist anymore.
 
     >>> browser.open('http://translations.launchpad.test/+languages/es')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
diff --git a/lib/lp/translations/stories/standalone/xx-licensing.txt b/lib/lp/translations/stories/standalone/xx-licensing.txt
index 5f2ef92..7bb6794 100644
--- a/lib/lp/translations/stories/standalone/xx-licensing.txt
+++ b/lib/lp/translations/stories/standalone/xx-licensing.txt
@@ -97,7 +97,6 @@ no link to change Karl's licensing choice.
 
     >>> user_browser.open('http://translations.launchpad.test/~karl/')
     >>> user_browser.getLink('Translations licensing')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -106,7 +105,6 @@ Typing in the URL directly doesn't work either.
 
     >>> user_browser.open(
     ...     'http://translations.launchpad.test/~karl/+licensing')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/translations/stories/standalone/xx-person-editlanguages.txt b/lib/lp/translations/stories/standalone/xx-person-editlanguages.txt
index e0e4fa8..398cd0b 100644
--- a/lib/lp/translations/stories/standalone/xx-person-editlanguages.txt
+++ b/lib/lp/translations/stories/standalone/xx-person-editlanguages.txt
@@ -131,7 +131,6 @@ The launchpad.AnyPerson permission means that when an anonymous user goes
 to that page, they'll be asked to login.
 
     >>> anon_browser.open('http://launchpad.test/+editmylanguages')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/translations/stories/standalone/xx-pofile-export.txt b/lib/lp/translations/stories/standalone/xx-pofile-export.txt
index 30c77c3..3968ef5 100644
--- a/lib/lp/translations/stories/standalone/xx-pofile-export.txt
+++ b/lib/lp/translations/stories/standalone/xx-pofile-export.txt
@@ -7,7 +7,6 @@ Not logged in users can't access the +export page.
     ...     'http://translations.launchpad.test/ubuntu/hoary'
     ...     '/+source/evolution/+pots/evolution-2.2/es/')
     >>> anon_browser.getLink('Download').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/translations/stories/standalone/xx-pofile-translate-alternative-language.txt b/lib/lp/translations/stories/standalone/xx-pofile-translate-alternative-language.txt
index cfb9b5b..d663762 100644
--- a/lib/lp/translations/stories/standalone/xx-pofile-translate-alternative-language.txt
+++ b/lib/lp/translations/stories/standalone/xx-pofile-translate-alternative-language.txt
@@ -242,7 +242,6 @@ get an UnexpectedFormData exception:
     ...     'http://translations.launchpad.test/ubuntu/hoary/+source/'
     ...     'evolution/+pots/evolution-2.2/es/+translate'
     ...     '?field.alternative_language=ja&field.alternative_language=aj')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: You specified...
diff --git a/lib/lp/translations/stories/standalone/xx-pofile-translate.txt b/lib/lp/translations/stories/standalone/xx-pofile-translate.txt
index 21f81b8..439b6ef 100644
--- a/lib/lp/translations/stories/standalone/xx-pofile-translate.txt
+++ b/lib/lp/translations/stories/standalone/xx-pofile-translate.txt
@@ -115,7 +115,6 @@ in the past.
     >>> browser.open(
     ...     'http://translations.launchpad.test/ubuntu/hoary/+source/'
     ...     'evolution/+pots/evolution-2.2/en/+translate')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: Object: ... name: 'en'
diff --git a/lib/lp/translations/stories/standalone/xx-potemplate-admin.txt b/lib/lp/translations/stories/standalone/xx-potemplate-admin.txt
index 6b831d8..76cbb80 100644
--- a/lib/lp/translations/stories/standalone/xx-potemplate-admin.txt
+++ b/lib/lp/translations/stories/standalone/xx-potemplate-admin.txt
@@ -13,7 +13,6 @@ An unprivileged user cannot reach the POTemplate administration page.
     >>> user_browser.open(
     ...     'http://translations.launchpad.test/evolution/trunk/+pots/'
     ...     'evolution-2.2/+admin')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/translations/stories/standalone/xx-potemplate-edit.txt b/lib/lp/translations/stories/standalone/xx-potemplate-edit.txt
index be44260..96af20f 100644
--- a/lib/lp/translations/stories/standalone/xx-potemplate-edit.txt
+++ b/lib/lp/translations/stories/standalone/xx-potemplate-edit.txt
@@ -11,7 +11,6 @@ An unpriviledged user cannot reach this page.
     >>> browser.open(
     ...     'http://translations.launchpad.test/evolution/trunk/+pots/'
     ...     'evolution-2.2/+edit')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -22,7 +21,6 @@ In fact, the "Change details" option won't even appear for them.
     ...     'http://translations.launchpad.test/evolution/trunk/+pots/'
     ...     'evolution-2.2/')
     >>> browser.getLink('Change details').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/translations/stories/standalone/xx-potemplate-export.txt b/lib/lp/translations/stories/standalone/xx-potemplate-export.txt
index 584e023..54dfa56 100644
--- a/lib/lp/translations/stories/standalone/xx-potemplate-export.txt
+++ b/lib/lp/translations/stories/standalone/xx-potemplate-export.txt
@@ -7,7 +7,6 @@ Not logged in users can't access the +export page.
     ...     'http://translations.launchpad.test/ubuntu/hoary'
     ...     '/+source/evolution/+pots/evolution-2.2/')
     >>> anon_browser.getLink('download').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/translations/stories/standalone/xx-potemplate-index.txt b/lib/lp/translations/stories/standalone/xx-potemplate-index.txt
index 8b1a394..2accf44 100644
--- a/lib/lp/translations/stories/standalone/xx-potemplate-index.txt
+++ b/lib/lp/translations/stories/standalone/xx-potemplate-index.txt
@@ -282,13 +282,11 @@ administration or download/upload links.
     ...     'http://translations.launchpad.test/'
     ...     'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
     >>> anon_browser.getLink('upload')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> anon_browser.getLink('download').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -300,7 +298,6 @@ but not the one for uploading file to this potemplate.
     ...     'http://translations.launchpad.test/'
     ...     'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
     >>> user_browser.getLink('upload')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/translations/stories/standalone/xx-product-export.txt b/lib/lp/translations/stories/standalone/xx-product-export.txt
index 75eb760..e327a81 100644
--- a/lib/lp/translations/stories/standalone/xx-product-export.txt
+++ b/lib/lp/translations/stories/standalone/xx-product-export.txt
@@ -49,7 +49,6 @@ Use the DB classes directly to avoid having to setup a zope interaction
     >>> product.sync()
     >>> user_browser.open('http://translations.launchpad.test/evolution')
     >>> user_browser.getLink('download')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -70,7 +69,6 @@ Only logged-in users get the option to request downloads.
 
     >>> anon_browser.open('http://translations.launchpad.test/evolution/')
     >>> anon_browser.getLink('download').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -92,7 +90,6 @@ We can't see its placeholder in non-development mode:
 Even "hacking the URL" to the download option will fail.
 
     >>> anon_browser.open(download_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/translations/stories/standalone/xx-product-translations.txt b/lib/lp/translations/stories/standalone/xx-product-translations.txt
index 2850738..6c4b830 100644
--- a/lib/lp/translations/stories/standalone/xx-product-translations.txt
+++ b/lib/lp/translations/stories/standalone/xx-product-translations.txt
@@ -85,12 +85,10 @@ are not being used, and provides access to help.
 It omits the registrant-only links ...
 
     >>> unprivileged.getLink(url='/gnomebaker/trunk/+translations-upload')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> unprivileged.getLink(url='/gnomebaker/+packages')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -100,7 +98,6 @@ It omits the registrant-only links ...
     >>> unprivileged.open(
     ...     'http://translations.launchpad.test/gnomebaker/trunk/'
     ...     '+translations-upload')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/translations/stories/standalone/xx-series-templates.txt b/lib/lp/translations/stories/standalone/xx-series-templates.txt
index c2a7bcc..3fe1eeb 100644
--- a/lib/lp/translations/stories/standalone/xx-series-templates.txt
+++ b/lib/lp/translations/stories/standalone/xx-series-templates.txt
@@ -96,7 +96,6 @@ Administration page is inaccessible.
     ...     'http://translations.launchpad.test/ubuntu/hoary/+templates')
     >>> utc_browser.getLink(
     ...     url='+source/evolution/+pots/evolution-2.2/+admin')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -116,7 +115,6 @@ Administration page is inaccessible.
     ...     'http://translations.launchpad.test/ubuntu/hoary/+templates')
     >>> utc_browser.getLink(
     ...     url='+source/evolution/+pots/disabled-template/+admin')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt b/lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt
index 88763ad..c049b94 100644
--- a/lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt
+++ b/lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt
@@ -76,13 +76,11 @@ right ones.
     ...     'evolution/+pots/evolution-2.2/es/1/+translate')
 
     >>> browser.getLink('First')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> browser.getLink('Prev')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -133,13 +131,11 @@ And the last one.
     http://.../hoary/+source/evolution/+pots/evolution-2.2/es/21/+translate
 
     >>> browser.getLink('Next')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> browser.getLink('Last')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -372,7 +368,6 @@ UnexpectedFormData exception:
     ...  'http://translations.launchpad.test/ubuntu/hoary/+source/evolution/'
     ...  '+pots/evolution-2.2/es/14/+translate?field.alternative_language=ca&'
     ...  'field.alternative_language=es')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.app.errors.UnexpectedFormData: You specified...
diff --git a/lib/lp/translations/stories/translationgroups/xx-change-translation-policy.txt b/lib/lp/translations/stories/translationgroups/xx-change-translation-policy.txt
index 6a701fd..5ee857a 100644
--- a/lib/lp/translations/stories/translationgroups/xx-change-translation-policy.txt
+++ b/lib/lp/translations/stories/translationgroups/xx-change-translation-policy.txt
@@ -58,7 +58,6 @@ to translations policy page.
     >>> dtc_browser.open(
     ...     'http://translations.launchpad.test/chestii')
     >>> dtc_browser.getLink('Configure Translations')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -68,7 +67,6 @@ An attempt to access the translations policy url will not be authorized.
     >>> browser.open(
     ...     'http://translations.launchpad.test/'
     ...     'chestii/+configure-translations')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/translations/stories/translationgroups/xx-translationgroups.txt b/lib/lp/translations/stories/translationgroups/xx-translationgroups.txt
index 75d8725..cd31e56 100644
--- a/lib/lp/translations/stories/translationgroups/xx-translationgroups.txt
+++ b/lib/lp/translations/stories/translationgroups/xx-translationgroups.txt
@@ -20,7 +20,6 @@ page.
 
     >>> anon_browser.open(
     ...     'http://translations.launchpad.test/+groups/+new')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -29,7 +28,6 @@ Same for a regular, unprivileged user.
 
     >>> user_browser.open(
     ...     'http://translations.launchpad.test/+groups/+new')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -266,13 +264,11 @@ Other users cannot access this page, nor see the menu link to it.
 
     >>> user_browser.open(anon_browser.url)
     >>> user_browser.getLink('Configure Translations').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> user_browser.open(ubuntu_owner_browser.url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -365,13 +361,11 @@ leads to.
 
     >>> user_browser.open(translations_page_url)
     >>> user_browser.getLink('Configure Translations').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> user_browser.open(change_translators_url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -413,13 +407,11 @@ to access the page it leads to.
 
     >>> user_browser.open(translations_page_url)
     >>> user_browser.getLink('Change permissions').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
 
     >>> user_browser.open(gnome_owner_browser.url)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
@@ -614,7 +606,6 @@ Normal users, however, are not.
     'http://translations.launchpad.test/+groups/polyglot/'
 
     >>> user_browser.getLink('Appoint a new translation team')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -625,7 +616,6 @@ Normal users, however, are not.
     'http://translations.launchpad.test/+groups/polyglot/'
 
     >>> user_browser.getLink('Change details').click()
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -700,7 +690,6 @@ instance Welsh (cy), the change will work.
 
     >>> admin_browser.open(
     ...     'http://translations.launchpad.test/+groups/polyglot/cy')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.publisher.interfaces.NotFound: ...
@@ -1092,7 +1081,6 @@ Try to get the page when unauthenticated.
     >>> browser.open(
     ...     'http://translations.launchpad.test/ubuntu/hoary/+source/' +
     ...         'evolution/+pots/evolution-2.2/af/+upload')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.security.interfaces.Unauthorized: ...
diff --git a/lib/lp/translations/stories/translations/xx-translations.txt b/lib/lp/translations/stories/translations/xx-translations.txt
index baec745..e212791 100644
--- a/lib/lp/translations/stories/translations/xx-translations.txt
+++ b/lib/lp/translations/stories/translations/xx-translations.txt
@@ -101,7 +101,6 @@ page, and that it has all the data we are expecting, in terms of languages.
     >>> print(browser.getLink('Xhosa').url)
     http://translations.launchpad.test/ubuntu/hoary/+lang/xh
     >>> browser.getLink('Afrihili')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
@@ -144,12 +143,10 @@ pmount and pkgconf-mozilla are not in this page, because it belongs to the
 next batch.
 
     >>> browser.getLink('pkgconf-mozilla')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
     >>> browser.getLink('pmount')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     zope.testbrowser.browser.LinkNotFoundError
diff --git a/lib/lp/translations/utilities/doc/gettext_mo_exporter.txt b/lib/lp/translations/utilities/doc/gettext_mo_exporter.txt
index 366d9a5..bce7a5d 100644
--- a/lib/lp/translations/utilities/doc/gettext_mo_exporter.txt
+++ b/lib/lp/translations/utilities/doc/gettext_mo_exporter.txt
@@ -133,7 +133,6 @@ get an export error exception:
     >>> mofile = compiler.compile(b'''
     ... blah
     ... ''')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.translations.interfaces.translationexporter.UnknownTranslationExporterError: ...
diff --git a/lib/lp/translations/utilities/doc/gettext_po_parser.txt b/lib/lp/translations/utilities/doc/gettext_po_parser.txt
index 835b05a..09f370d 100644
--- a/lib/lp/translations/utilities/doc/gettext_po_parser.txt
+++ b/lib/lp/translations/utilities/doc/gettext_po_parser.txt
@@ -17,7 +17,6 @@ PO files with empty headers are not allowed.
 
     >>> parser = POParser()
     >>> parser.parse(b'msgid "foo"\nmsgstr ""\n')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.translations.interfaces.translationimporter.TranslationFormatSyntaxError: ...
@@ -26,7 +25,6 @@ PO files with context after msgids are reported as broken.
 
     >>> parser.parse(b'msgid ""\nmsgstr ""\n'
     ...              b'msgid "blah"\nmsgctxt "foo"\nmsgstr "bar"\n')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.translations.interfaces.translationimporter.TranslationFormatSyntaxError: ...
@@ -36,7 +34,6 @@ And a msgctxt followed by msgctxt is caught as well.
     >>> parser.parse(b'msgid ""\nmsgstr ""\n'
     ...              b'msgctxt "foo"\nmsgctxt "foo1"\n'
     ...              b'msgid "blah"\nmsgstr "bar"\n')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.translations.interfaces.translationimporter.TranslationFormatSyntaxError: ...
@@ -46,7 +43,6 @@ as an error.
 
     >>> parser.parse(b'msgid ""\nmsgstr "something"\n'
     ...              b'"foo"  whatever\n')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.translations.interfaces.translationimporter.TranslationFormatSyntaxError: ...Extra content found after string...
@@ -54,7 +50,6 @@ as an error.
 Unrecognized escape sequences are caught as well.
 
     >>> parser.parse(b'msgid "\!"\nmsgstr ""\n')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.translations.interfaces.translationimporter.TranslationFormatSyntaxError: ...Unknown escape sequence...
@@ -62,7 +57,6 @@ Unrecognized escape sequences are caught as well.
 Unclosed strings (missing closing quotes) are caught.
 
     >>> parser.parse(b'msgid ""\nmsgstr "\n')
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.translations.interfaces.translationimporter.TranslationFormatSyntaxError: ...String not terminated...
@@ -329,7 +323,6 @@ errors occur:
     ... """  # noqa
 
     >>> parser.parse(content + chunk2)
-    ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
     Traceback (most recent call last):
     ...
     lp.translations.interfaces.translationimporter.TranslationFormatInvalidInputError: Line 13: Could not decode input from UTF-8
diff --git a/lib/lp/translations/utilities/gettext_po_parser.py b/lib/lp/translations/utilities/gettext_po_parser.py
index 4756050..4dcc630 100644
--- a/lib/lp/translations/utilities/gettext_po_parser.py
+++ b/lib/lp/translations/utilities/gettext_po_parser.py
@@ -753,7 +753,6 @@ class POParser(object):
           >>> utf8_string = u'"view \\302\\253${version_title}\\302\\273"'
           >>> parser._parseQuotedString(utf8_string)
           ... # doctest: +NORMALIZE_WHITESPACE
-          ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
           Traceback (most recent call last):
           ...
           lp.translations.interfaces.translationimporter.TranslationFormatInvalidInputError: Could not decode escaped string: (\302\253)
@@ -775,7 +774,6 @@ class POParser(object):
           >>> iso8859_1_string = u'"foo \\xf9"'
           >>> parser._parseQuotedString(iso8859_1_string)
           ... # doctest: +NORMALIZE_WHITESPACE
-          ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
           Traceback (most recent call last):
           ...
           lp.translations.interfaces.translationimporter.TranslationFormatInvalidInputError: Could not decode escaped string as UTF-8: (\xf9)
@@ -785,19 +783,16 @@ class POParser(object):
 
           >>> parser._parseQuotedString(u'abc')
           ... # doctest: +NORMALIZE_WHITESPACE
-          ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
           Traceback (most recent call last):
             ...
           lp.translations.interfaces.translationimporter.TranslationFormatSyntaxError: String is not quoted
           >>> parser._parseQuotedString(u'\"ab')
           ... # doctest: +NORMALIZE_WHITESPACE
-          ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
           Traceback (most recent call last):
             ...
           lp.translations.interfaces.translationimporter.TranslationFormatSyntaxError: String not terminated
           >>> parser._parseQuotedString(u'\"ab\"x')
           ... # doctest: +NORMALIZE_WHITESPACE
-          ... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
           Traceback (most recent call last):
             ...
           lp.translations.interfaces.translationimporter.TranslationFormatSyntaxError: Extra content found after string: (x)