← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:py3-registry-browser-doctests-future-imports into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:py3-registry-browser-doctests-future-imports into launchpad:master.

Commit message:
Convert lp.registry.browser doctests to preferred __future__ imports

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

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

This is very large, but with the exception of the change to lib/lp/registry/browser/tests/test_views.py it consists entirely of mechanical print function conversions.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:py3-registry-browser-doctests-future-imports into launchpad:master.
diff --git a/lib/lp/registry/browser/tests/announcement-views.txt b/lib/lp/registry/browser/tests/announcement-views.txt
index 3a7a108..604eb54 100644
--- a/lib/lp/registry/browser/tests/announcement-views.txt
+++ b/lib/lp/registry/browser/tests/announcement-views.txt
@@ -56,10 +56,10 @@ smaller than in production to ease testing.
     >>> announcement_set = getUtility(IAnnouncementSet)
     >>> view = create_initialized_view(
     ...     announcement_set, '+announcements')
-    >>> print len(list(view.announcements))
+    >>> print(len(list(view.announcements)))
     20
-    >>> print view.batch_size
+    >>> print(view.batch_size)
     4
     >>> batch = view.announcement_nav.currentBatch()
-    >>> print len(list(batch))
+    >>> print(len(list(batch)))
     4
diff --git a/lib/lp/registry/browser/tests/browser-views.txt b/lib/lp/registry/browser/tests/browser-views.txt
index c24f984..028f2e4 100644
--- a/lib/lp/registry/browser/tests/browser-views.txt
+++ b/lib/lp/registry/browser/tests/browser-views.txt
@@ -20,9 +20,9 @@ javascript calls newMilestone on the object at series_api_uri.
     >>> product = factory.makeProduct(name='app')
     >>> series = factory.makeProductSeries(name='stable', product=product)
     >>> view = MilestoneCreatorView(series, LaunchpadTestRequest())
-    >>> print view.milestone_form_uri
+    >>> print(view.milestone_form_uri)
     http://launchpad.test/app/stable/+addmilestone/++form++
-    >>> print view.series_api_uri
+    >>> print(view.series_api_uri)
     /app/stable
 
 
@@ -57,14 +57,14 @@ rule is to sort on the 'sortkey' attribute of the object being counted.
 
     >>> items = (concept_1, artefact_2, artefact_3)
     >>> for status_count in get_status_counts(items, 'status'):
-    ...     print status_count.count, status_count.status
+    ...     print(status_count.count, status_count.status)
     2 Experimental
     1 Current Stable Release
 
 The attribute to sort on can be specified.
 
     >>> for status_count in get_status_counts(items, 'status', key='title'):
-    ...     print status_count.count, status_count.status
+    ...     print(status_count.count, status_count.status)
     1 Current Stable Release
     2 Experimental
 
@@ -73,7 +73,7 @@ to specify the attribute to sort on.
 
     >>> for status_count in get_status_counts(
     ...     items, 'person', key='displayname'):
-    ...     print status_count.count, status_count.status.displayname
+    ...     print(status_count.count, status_count.status.displayname)
     1 Andy
     2 Bob
 
@@ -82,6 +82,6 @@ If the object being counted is None, it is ignored.
     >>> artefact_2.person = None
     >>> for status_count in get_status_counts(
     ...     items, 'person', key='displayname'):
-    ...     print status_count.count, status_count.status.displayname
+    ...     print(status_count.count, status_count.status.displayname)
     1 Andy
     1 Bob
diff --git a/lib/lp/registry/browser/tests/coc-views.txt b/lib/lp/registry/browser/tests/coc-views.txt
index e0cc8ba..ced69df 100644
--- a/lib/lp/registry/browser/tests/coc-views.txt
+++ b/lib/lp/registry/browser/tests/coc-views.txt
@@ -11,7 +11,7 @@ the person's name in the page label.
     >>> login('admin@xxxxxxxxxxxxx')
     >>> geddy = factory.makePerson(displayname='Geddy Lee')
     >>> view = create_initialized_view(geddy, '+codesofconduct')
-    >>> print view.label
+    >>> print(view.label)
     Codes of Conduct for Geddy Lee
 
 
@@ -25,7 +25,7 @@ key registered, directions are shown.
     ...     ol = content.find('ol')
     ...     if ol is not None:
     ...         for index, li in enumerate(ol.findAll('li')):
-    ...             print '%s. %s' % ((index+1), extract_text(li))
+    ...             print('%s. %s' % ((index+1), extract_text(li)))
     >>> user = factory.makePerson()
     >>> ignored = login_person(user)
     >>> from lp.registry.interfaces.codeofconduct import ICodeOfConductSet
@@ -74,6 +74,6 @@ If the user has already signed the code of conduct, no directions are shown.
     >>> view = create_initialized_view(coc_set, '+index', principal=admin)
     >>> content = find_tag_by_id(view.render(), 'maincontent')
     >>> print_coc_directions(content)
-    >>> print extract_text(content)
+    >>> print(extract_text(content))
     Ubuntu Codes of Conduct...
     Congratulations, you have already signed the Ubuntu Code of Conduct...
diff --git a/lib/lp/registry/browser/tests/distribution-views.txt b/lib/lp/registry/browser/tests/distribution-views.txt
index 533d559..e1da99d 100644
--- a/lib/lp/registry/browser/tests/distribution-views.txt
+++ b/lib/lp/registry/browser/tests/distribution-views.txt
@@ -20,7 +20,7 @@ country.
     ...     mirrors = country_and_mirror['mirrors']
     ...     for mirror in mirrors:
     ...         assert mirror.country.name == country
-    ...     print "%s: %d mirror(s)" % (country, len(mirrors))
+    ...     print("%s: %d mirror(s)" % (country, len(mirrors)))
     France: 2 mirror(s)
     Germany: 1 mirror(s)
     United Kingdom: 1 mirror(s)
@@ -36,7 +36,7 @@ Lists of archive mirrors
     ...     mirrors = country_and_mirror['mirrors']
     ...     for mirror in mirrors:
     ...         assert mirror.country.name == country
-    ...     print "%s: %d mirror(s)" % (country, len(mirrors))
+    ...     print("%s: %d mirror(s)" % (country, len(mirrors)))
     Antarctica: 2 mirror(s)
     France: 2 mirror(s)
     United Kingdom: 1 mirror(s)
@@ -52,15 +52,15 @@ Registering a distribution
 The +add view of the DistributionSet allows admins to register distributions.
 
     >>> view = create_view(distributionset, '+add')
-    >>> print view.label
+    >>> print(view.label)
     Register a new distribution
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Register a new distribution
 
 The view provides a cancel link.
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/distros
 
 The view accepts the basic fields to register a distribution.
@@ -85,11 +85,11 @@ The view accepts the basic fields to register a distribution.
     >>> view = create_initialized_view(distributionset, '+add', form=form)
     >>> view.errors
     []
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/youbuntu
 
     >>> distribution = distributionset.getByName("youbuntu")
-    >>> print distribution.name
+    >>> print(distribution.name)
     youbuntu
 
 Only admins and owners can access the view.
@@ -112,13 +112,13 @@ a label, page_title, and cancel_url.
 
     >>> login("admin@xxxxxxxxxxxxx")
     >>> view = create_view(distribution, '+edit')
-    >>> print view.label
+    >>> print(view.label)
     Change YoUbuntu details
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Change YoUbuntu details
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/youbuntu
 
 The view accepts most of the distribution fields.
@@ -143,10 +143,10 @@ The view accepts most of the distribution fields.
     >>> view = create_initialized_view(distribution, '+edit', form=form)
     >>> view.errors
     []
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/youbuntu
 
-    >>> print distribution.bug_reporting_guidelines
+    >>> print(distribution.bug_reporting_guidelines)
     guidelines
 
     >>> distribution.bug_tracking_usage
@@ -170,18 +170,18 @@ administrator.
 
     >>> login("admin@xxxxxxxxxxxxx")
     >>> view = create_view(distribution, '+selectmirroradmins')
-    >>> print view.label
+    >>> print(view.label)
     Change the YoUbuntu mirror administrator
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Change the YoUbuntu mirror administrator
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/youbuntu
 
 The view accepts the mirror_admin field.
 
-    >>> print distribution.mirror_admin.name
+    >>> print(distribution.mirror_admin.name)
     name16
 
     >>> view.field_names
@@ -195,10 +195,10 @@ The view accepts the mirror_admin field.
     ...     distribution, '+selectmirroradmins', form=form)
     >>> view.errors
     []
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/youbuntu
 
-    >>> print distribution.mirror_admin.name
+    >>> print(distribution.mirror_admin.name)
     no-priv
 
 Only admins and owners can access the view.
@@ -267,18 +267,18 @@ the +selectmirroradmins allows the owner or admin to change the members team.
 
     >>> login("admin@xxxxxxxxxxxxx")
     >>> view = create_view(distribution, '+selectmemberteam')
-    >>> print view.label
+    >>> print(view.label)
     Change the YoUbuntu members team
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Change the YoUbuntu members team
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/youbuntu
 
 The view accepts the members field.
 
-    >>> print distribution.members.name
+    >>> print(distribution.members.name)
     landscape-developers
 
     >>> view.field_names
@@ -292,10 +292,10 @@ The view accepts the members field.
     ...     distribution, '+selectmemberteam', form=form)
     >>> view.errors
     []
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/youbuntu
 
-    >>> print distribution.members.name
+    >>> print(distribution.members.name)
     ubuntu-team
 
 Only admins and owners can access the view.
@@ -330,13 +330,13 @@ not appear.
 
     >>> view = create_view(distribution, name='+index', principal=owner)
     >>> content = find_tag_by_id(view.render(), 'maincontent')
-    >>> print find_tag_by_id(content, 'portlet-latest-faqs')
+    >>> print(find_tag_by_id(content, 'portlet-latest-faqs'))
     None
-    >>> print find_tag_by_id(content, 'portlet-latest-questions')
+    >>> print(find_tag_by_id(content, 'portlet-latest-questions'))
     None
-    >>> print find_tag_by_id(content, 'portlet-latest-bugs')
+    >>> print(find_tag_by_id(content, 'portlet-latest-bugs'))
     None
-    >>> print find_tag_by_id(content, 'portlet-blueprints')
+    >>> print(find_tag_by_id(content, 'portlet-blueprints'))
     None
 
 If the distribution officially uses the application, its portlet does appear.
@@ -349,13 +349,13 @@ If the distribution officially uses the application, its portlet does appear.
 
     >>> view = create_view(distribution, name='+index', principal=owner)
     >>> content = find_tag_by_id(view.render(), 'maincontent')
-    >>> print find_tag_by_id(content, 'portlet-latest-faqs')['id']
+    >>> print(find_tag_by_id(content, 'portlet-latest-faqs')['id'])
     portlet-latest-faqs
-    >>> print find_tag_by_id(content, 'portlet-latest-questions')['id']
+    >>> print(find_tag_by_id(content, 'portlet-latest-questions')['id'])
     portlet-latest-questions
-    >>> print find_tag_by_id(content, 'portlet-latest-bugs')['id']
+    >>> print(find_tag_by_id(content, 'portlet-latest-bugs')['id'])
     portlet-latest-bugs
-    >>> print find_tag_by_id(content, 'portlet-blueprints')['id']
+    >>> print(find_tag_by_id(content, 'portlet-blueprints')['id'])
     portlet-blueprints
 
 
@@ -366,11 +366,11 @@ The +series view provides a page title and list of dicts that represent
 the series and the CSS class to present them with.
 
     >>> view = create_view(ubuntu, name='+series')
-    >>> print view.label
+    >>> print(view.label)
     Timeline
 
     >>> for styled_series in view.styled_series:
-    ...     print styled_series['series'].name, styled_series['css_class']
+    ...     print(styled_series['series'].name, styled_series['css_class'])
     breezy-autotest
     grumpy
     hoary highlight
@@ -384,11 +384,11 @@ The +derivatives view provides a page title and list of dicts that represent
 the derivatives and the CSS class to present them with.
 
     >>> view = create_view(ubuntu, name='+derivatives')
-    >>> print view.label
+    >>> print(view.label)
     Derivatives
 
     >>> for styled_series in view.styled_series:
-    ...     print styled_series['series'].name, styled_series['css_class']
+    ...     print(styled_series['series'].name, styled_series['css_class'])
     hoary-test
     krunch
     breezy-autotest
@@ -402,9 +402,9 @@ The +ppas view provides a page title and label, some statistics helpers
 and search results.
 
     >>> view = create_view(ubuntu, name='+ppas')
-    >>> print view.label
+    >>> print(view.label)
     Personal Package Archives for Ubuntu
 
     # The leaf of the breadcrumbs, also used in the page-title.
-    >>> print view.page_title
+    >>> print(view.page_title)
     Personal Package Archives
diff --git a/lib/lp/registry/browser/tests/distributionmirror-views.txt b/lib/lp/registry/browser/tests/distributionmirror-views.txt
index f8fe4c5..29297df 100644
--- a/lib/lp/registry/browser/tests/distributionmirror-views.txt
+++ b/lib/lp/registry/browser/tests/distributionmirror-views.txt
@@ -18,7 +18,7 @@ Other distributions cannot use the form.
     >>> view = create_initialized_view(
     ...     distribution, '+newmirror', principal=distribution.owner)
     >>> content = find_tag_by_id(view.render(), 'not-full-functionality')
-    >>> print extract_text(content)
+    >>> print(extract_text(content))
     This functionality is not yet available...
 
 Ubuntu has mirror support enabled, so it can have mirrors.
@@ -30,18 +30,18 @@ Ubuntu has mirror support enabled, so it can have mirrors.
     >>> ignored = login_person(owner)
     >>> view = create_initialized_view(ubuntu, '+newmirror', principal=owner)
     >>> content = find_tag_by_id(view.render(), 'full-functionality')
-    >>> print extract_text(content)
+    >>> print(extract_text(content))
     To register a new mirror...
 
 The view provides a label, page_title, and cancel_url
 
-    >>> print view.label
+    >>> print(view.label)
     Register a new mirror for Ubuntu
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Register a new mirror for Ubuntu
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/ubuntu
 
 A HTTP, HTTPS or FTP URL is required to register a mirror.
@@ -68,7 +68,7 @@ A HTTP, HTTPS or FTP URL is required to register a mirror.
     >>> view = create_initialized_view(ubuntu, '+newmirror', form=form)
     >>> view.errors
     []
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/ubuntu/+mirror/secret.me-archive
 
     >>> transaction.commit()
@@ -81,14 +81,14 @@ A mirror can only be registered once for a HTTP URL (the trailing slash is
 not significant).
 
     >>> mirror = ubuntu.getMirrorByName('secret.me-archive')
-    >>> print mirror.http_base_url
+    >>> print(mirror.http_base_url)
     http://secret.me/
 
     >>> bad_form = dict(form)
     >>> bad_form['field.http_base_url'] = 'http://secret.me'
     >>> view = create_initialized_view(ubuntu, '+newmirror', form=bad_form)
     >>> for error in view.errors:
-    ...     print error[2]
+    ...     print(error[2])
     The distribution mirror ... is already registered with this URL.
 
 The same is true for a FTP URL.
@@ -99,7 +99,7 @@ The same is true for a FTP URL.
     >>> bad_form['field.ftp_base_url'] = 'ftp://now-here.me'
     >>> view = create_initialized_view(ubuntu, '+newmirror', form=bad_form)
     >>> for error in view.errors:
-    ...     print error[2]
+    ...     print(error[2])
     The distribution mirror ... is already registered with this URL.
 
 The same is true for a rsync URL.
@@ -109,7 +109,7 @@ The same is true for a rsync URL.
     >>> bad_form['field.rsync_base_url'] = 'rsync://nowhere.me'
     >>> view = create_initialized_view(ubuntu, '+newmirror', form=bad_form)
     >>> for error in view.errors:
-    ...     print error[2]
+    ...     print(error[2])
     The distribution mirror ... is already registered with this URL.
 
 A mirror must have an ftp, HTTPS or http URL.
@@ -119,7 +119,7 @@ A mirror must have an ftp, HTTPS or http URL.
     >>> bad_form['field.ftp_base_url'] = ''
     >>> view = create_initialized_view(ubuntu, '+newmirror', form=bad_form)
     >>> for message in view.errors:
-    ...     print message
+    ...     print(message)
     A mirror must have at least an HTTP(S) or FTP URL.
 
 The URL cannot contain a fragment.
@@ -127,7 +127,7 @@ The URL cannot contain a fragment.
     >>> bad_form['field.http_base_url'] = 'http://secret.me/#fragement'
     >>> view = create_initialized_view(ubuntu, '+newmirror', form=bad_form)
     >>> for error in view.errors:
-    ...     print error[2]
+    ...     print(error[2])
     URIs with fragment identifiers are not allowed.
 
 The URL cannot contain a query string.
@@ -135,7 +135,7 @@ The URL cannot contain a query string.
     >>> bad_form['field.http_base_url'] = 'http://secret.me/?query=string'
     >>> view = create_initialized_view(ubuntu, '+newmirror', form=bad_form)
     >>> for error in view.errors:
-    ...     print error[2]
+    ...     print(error[2])
     URIs with query strings are not allowed.
 
 The HTTPS URL may not have an HTTP scheme.
@@ -144,7 +144,7 @@ The HTTPS URL may not have an HTTP scheme.
     >>> bad_form['field.https_base_url'] = 'http://secret.me/#fragement'
     >>> view = create_initialized_view(ubuntu, '+newmirror', form=bad_form)
     >>> for error in view.errors:
-    ...     print error[2]
+    ...     print(error[2])
     The URI scheme "http" is not allowed.
     Only URIs with the following schemes may be used: https
 
@@ -154,7 +154,7 @@ The HTTPS URL cannot contain a fragment.
     >>> bad_form['field.https_base_url'] = 'https://secret.me/#fragement'
     >>> view = create_initialized_view(ubuntu, '+newmirror', form=bad_form)
     >>> for error in view.errors:
-    ...     print error[2]
+    ...     print(error[2])
     URIs with fragment identifiers are not allowed.
 
 The URL cannot contain a query string.
@@ -163,7 +163,7 @@ The URL cannot contain a query string.
     >>> bad_form['field.https_base_url'] = 'https://secret.me/?query=string'
     >>> view = create_initialized_view(ubuntu, '+newmirror', form=bad_form)
     >>> for error in view.errors:
-    ...     print error[2]
+    ...     print(error[2])
     URIs with query strings are not allowed.
 
 
@@ -176,21 +176,21 @@ changed the person who changed it and the date it was changed.
 
 Only official mirrors are probed.
 
-    >>> print mirror.status.name
+    >>> print(mirror.status.name)
     PENDING_REVIEW
-    >>> print mirror.date_reviewed, mirror.reviewer
+    >>> print(mirror.date_reviewed, mirror.reviewer)
     None None
 
 The view provides a label, page_title, and cancel_url.
 
     >>> view =  create_initialized_view(mirror, '+review')
-    >>> print view.label
+    >>> print(view.label)
     Review mirror Illuminati
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Review mirror Illuminati
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/ubuntu/+mirror/secret.me-archive
 
 If the status is not changed, the reviewer and date_reviewed won't be
@@ -206,9 +206,9 @@ changed either.
     >>> view.errors
     []
 
-    >>> print mirror.status.name
+    >>> print(mirror.status.name)
     PENDING_REVIEW
-    >>> print mirror.date_reviewed, mirror.reviewer
+    >>> print(mirror.date_reviewed, mirror.reviewer)
     None None
 
 When the status is changed, though, both reviewer and date_reviewed are
@@ -219,14 +219,14 @@ changed.
     >>> view =  create_initialized_view(mirror, '+review', form=review_form)
     >>> view.errors
     []
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/ubuntu/+mirror/secret.me-archive
 
-    >>> print mirror.status.name
+    >>> print(mirror.status.name)
     OFFICIAL
-    >>> print mirror.reviewer.name
+    >>> print(mirror.reviewer.name)
     karl
-    >>> print mirror.whiteboard
+    >>> print(mirror.whiteboard)
     This site is good.
 
     # This is to check that the mirror's date_reviewed has just been updated,
@@ -258,13 +258,13 @@ The +edit view provides a label, page_title, and cancel_url.
 
     >>> login('karl@xxxxxxxxxxxxx')
     >>> view =  create_initialized_view(mirror, '+edit')
-    >>> print view.label
+    >>> print(view.label)
     Edit mirror Illuminati
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Edit mirror Illuminati
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/ubuntu/+mirror/secret.me-archive
 
 The user can edit the mirror fields.
@@ -274,7 +274,7 @@ The user can edit the mirror fields.
      'http_base_url', 'ftp_base_url', 'rsync_base_url', 'speed', 'country',
      'content', 'official_candidate']
 
-    >>> print mirror.ftp_base_url
+    >>> print(mirror.ftp_base_url)
     None
 
     >>> form['field.ftp_base_url'] = 'ftp://secret.me/'
@@ -282,10 +282,10 @@ The user can edit the mirror fields.
     >>> view = create_initialized_view(mirror, '+edit', form=form)
     >>> view.errors
     []
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/ubuntu/+mirror/secret.me-archive
 
-    >>> print mirror.ftp_base_url
+    >>> print(mirror.ftp_base_url)
     ftp://secret.me/
 
 Only users with launchpad.Edit can access the view.
@@ -325,7 +325,7 @@ The mirror owner can resubmit a 'Broken' mirror for a new review.
     >>> view =  create_initialized_view(mirror, '+review', form=review_form)
     >>> form['field.actions.resubmit'] = 'Resubmit'
     >>> view = create_initialized_view(mirror, '+resubmit', form=form)
-    >>> print mirror.status.name
+    >>> print(mirror.status.name)
     PENDING_REVIEW
 
 The resubmit view should only be available to people with launchpad.Edit.
@@ -347,13 +347,13 @@ The +delete view provides a label, page_title, and cancel_url.
 
     >>> login('karl@xxxxxxxxxxxxx')
     >>> view = create_initialized_view(mirror, '+delete')
-    >>> print view.label
+    >>> print(view.label)
     Delete mirror Illuminati
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Delete mirror Illuminati
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/ubuntu/+mirror/secret.me-archive
 
 A mirror that have been probed cannot be deleted.
@@ -369,7 +369,7 @@ A mirror that have been probed cannot be deleted.
     >>> view.errors
     []
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     This mirror has been probed and thus can't be deleted.
 
 Deletion is permanent.
@@ -380,11 +380,11 @@ Deletion is permanent.
     >>> view =  create_initialized_view(mirror, '+delete', form=form)
     >>> view.errors
     []
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/ubuntu/+pendingreviewmirrors
 
     >>> transaction.commit()
-    >>> print ubuntu.getMirrorByName('secret.me-archive')
+    >>> print(ubuntu.getMirrorByName('secret.me-archive'))
     None
 
 Only users with launchpad.Admin can access the view.
@@ -416,61 +416,61 @@ The archive mirror page summarizes the current state of the mirror.
 
 The page shows the mirror's owner:
 
-    >>> print extract_text(find_tag_by_id(content, 'owner'))
+    >>> print(extract_text(find_tag_by_id(content, 'owner')))
     Owner:
     Mark Shuttleworth
 
 The page shows the mirror status
 
-    >>> print extract_text(find_tag_by_id(content, 'status'))
+    >>> print(extract_text(find_tag_by_id(content, 'status')))
     Status:
     Official
 
 The page shows which country the mirror is in:
 
-    >>> print extract_text(find_tag_by_id(content, 'country'))
+    >>> print(extract_text(find_tag_by_id(content, 'country')))
     Country:
     Antarctica
 
 The page shows which kind of mirror a mirror is:
 
-    >>> print extract_text(find_tag_by_id(content, 'type'))
+    >>> print(extract_text(find_tag_by_id(content, 'type')))
     Type:
     Archive
 
 And which organisation runs a mirror:
 
-    >>> print extract_text(find_tag_by_id(content, 'organisation'))
+    >>> print(extract_text(find_tag_by_id(content, 'organisation')))
     Organisation:
     None
 
 The page contains a source list...
 
-    >>> print extract_text(find_tag_by_id(content, 'sources-list-entries'))
+    >>> print(extract_text(find_tag_by_id(content, 'sources-list-entries')))
     deb http://localhost:11375/valid-mirror2/ YOUR_UBUNTU_VERSION_HERE main
     deb-src http://localhost:11375/valid-mirror2/ YOUR_UBUNTU_VERSION_HERE main
 
 and the select control that lets you update them.
 
-    >>> print extract_text(find_tag_by_id(content, 'field.series'))
+    >>> print(extract_text(find_tag_by_id(content, 'field.series')))
     Choose your Ubuntu version
       Hoary (5.04)
       Warty (4.10)
 
 The last probed information is present.
 
-    >>> print extract_text(find_tag_by_id(content, 'last-probe'))
+    >>> print(extract_text(find_tag_by_id(content, 'last-probe')))
     Last probe
     This mirror was last verified ...
 
 The information found is also shown.
 
-    >>> print extract_text(find_tag_by_id(content, 'arches'))
+    >>> print(extract_text(find_tag_by_id(content, 'arches')))
     Version                     Architecture  Status
     The Hoary Hedgehog Release  i386          One hour behind
     The Warty Warthog Release   i386          Two hours behind
 
-    >>> print extract_text(find_tag_by_id(content, 'sources'))
+    >>> print(extract_text(find_tag_by_id(content, 'sources')))
     Version                      Status
     The Hoary Hedgehog Release   Up to date
     The Warty Warthog Release    Six hours behind
@@ -482,13 +482,13 @@ The last probed information is present.
     >>> view = create_initialized_view(
     ...     cd_mirror, '+index', principal=user)
     >>> content = find_tag_by_id(view.render(), 'maincontent')
-    >>> print extract_text(find_tag_by_id(content, 'last-probe'))
+    >>> print(extract_text(find_tag_by_id(content, 'last-probe')))
     Last probe
     This mirror was last verified ...
 
 The information found is also shown.
 
-    >>> print extract_text(find_tag_by_id(content, 'series'))
+    >>> print(extract_text(find_tag_by_id(content, 'series')))
     Version                     Flavours
     The Hoary Hedgehog Release  Ubuntu, Edubuntu
     The Warty Warthog Release   Ubuntu, Kubuntu
@@ -501,14 +501,14 @@ Mirror admins can also see a whiteboard
     >>> view = create_initialized_view(
     ...     cd_mirror, '+index', principal=user)
     >>> whiteboard = find_tag_by_id(view.render(), 'whiteboard')
-    >>> print extract_text(whiteboard.find('dd'))
+    >>> print(extract_text(whiteboard.find('dd')))
     This is a good mirror.
 
     >>> login('no-priv@xxxxxxxxxxxxx')
     >>> user = getUtility(ILaunchBag).user
     >>> view = create_initialized_view(
     ...     cd_mirror, '+index', principal=user)
-    >>> print find_tag_by_id(view.render(), 'whiteboard')
+    >>> print(find_tag_by_id(view.render(), 'whiteboard'))
     None
 
 
@@ -522,7 +522,7 @@ Any user can see the RSS for an archive mirror
     >>> view = create_initialized_view(
     ...     ubuntu, '+archivemirrors-rss', principal=user,
     ...     server_url='http://launchpad.test/ubuntu/+archivemirrors-rss')
-    >>> print view()
+    >>> print(view())
     <?xml version="1.0"...?>
     <rss xmlns:mirror="https://launchpad.net/"; version="2.0">
       <channel>
@@ -547,7 +547,7 @@ Any user can see the RSS for an archive mirror
       </channel>
     </rss>
 
-    >>> print view.request.response.getHeader('content-type')
+    >>> print(view.request.response.getHeader('content-type'))
     text/xml;charset=utf-8
 
 Any user can see the RSS for an CD mirror
@@ -555,7 +555,7 @@ Any user can see the RSS for an CD mirror
     >>> view = create_initialized_view(
     ...     ubuntu, '+cdmirrors-rss', principal=user,
     ...     server_url='http://launchpad.test/ubuntu/+cdmirrors-rss')
-    >>> print view()
+    >>> print(view())
     <?xml version="1.0"...?>
     <rss ...
       <channel>
@@ -584,5 +584,5 @@ Any user can see the RSS for an CD mirror
       </channel>
     </rss>
 
-    >>> print view.request.response.getHeader('content-type')
+    >>> print(view.request.response.getHeader('content-type'))
     text/xml;charset=utf-8
diff --git a/lib/lp/registry/browser/tests/distributionsourcepackage-views.txt b/lib/lp/registry/browser/tests/distributionsourcepackage-views.txt
index 4e50bd7..35daee3 100644
--- a/lib/lp/registry/browser/tests/distributionsourcepackage-views.txt
+++ b/lib/lp/registry/browser/tests/distributionsourcepackage-views.txt
@@ -49,7 +49,7 @@ series.
     >>> view = create_initialized_view(
     ...     ubuntu_eel, name='+index', principal=factory.makePerson())
     >>> for series in view.active_series:
-    ...     print series.name, series.version
+    ...     print(series.name, series.version)
     latest 10.04
     breezy-autotest 6.6.6
     earliest 1.1
@@ -58,7 +58,7 @@ The view has a latest_sourcepackage attribute whose series is the same
 as the first series from view.active_series.
 
     >>> latest_series = view.latest_sourcepackage.distroseries
-    >>> print latest_series.name, latest_series.version
+    >>> print(latest_series.name, latest_series.version)
     latest 10.04
 
 The view has a version_table attribute for populating a table. The "Set
@@ -73,8 +73,8 @@ CURRENT or DEVELOPMENT.
     ...         if row['show_set_upstream_link'] is True:
     ...             set_upstream_link = '  set-upstream-link'
     ...         ds = row['distroseries']
-    ...         print "%-16s %-12s %s" % (
-    ...             ds.name, ds.status.name, set_upstream_link)
+    ...         print("%-16s %-12s %s" % (
+    ...             ds.name, ds.status.name, set_upstream_link))
     latest           DEVELOPMENT    set-upstream-link
     breezy-autotest  CURRENT        set-upstream-link
     earliest         SUPPORTED
@@ -84,7 +84,7 @@ this page will display a form to add one.
 
     >>> from lp.testing.pages import find_tag_by_id
     >>> upstream_portlet = find_tag_by_id(view.render(), 'upstream')
-    >>> print upstream_portlet.find(id='field.actions.link')['value']
+    >>> print(upstream_portlet.find(id='field.actions.link')['value'])
     Link to Upstream Project
 
 
@@ -140,17 +140,17 @@ package.
     >>> ubuntu_gedit_view = create_initialized_view(
     ...     ubuntu_gedit, name='+index')
     >>> for archive_pub in ubuntu_gedit_view.related_ppa_versions:
-    ...     print "%s - %s" % (
+    ...     print("%s - %s" % (
     ...         archive_pub['archive'].displayname,
     ...         archive_pub['versions']
-    ...         )
+    ...         ))
     PPA named nightly for Person-name... - Breezy Badger Autotest (0.8.2n3)
     PPA named beta for Person-name... - Breezy Badger Autotest (0.8.1),
         Hoary Mock (0.8.0)
 
 The view also calculates the url for finding further PPA versions.
 
-    >>> print ubuntu_gedit_view.further_ppa_versions_url
+    >>> print(ubuntu_gedit_view.further_ppa_versions_url)
     http://launchpad.test/ubuntutest/+ppas?name_filter=gedit
 
 
@@ -166,13 +166,13 @@ view provides a label, page_title and cancel_url.
     >>> package = factory.makeDistributionSourcePackage(
     ...     sourcepackagename=sourcepackagename, distribution=distribution)
     >>> view = create_initialized_view(package, '+edit')
-    >>> print view.label
+    >>> print(view.label)
     Edit ...bonkers... package in Youbuntu
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Edit ...bonkers... package in Youbuntu
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/youbuntu/+source/bonkers
 
 The view allows the user the set the bug_reporting_guidelines field.
@@ -181,7 +181,7 @@ The view allows the user the set the bug_reporting_guidelines field.
     ['bug_reporting_guidelines', 'bug_reported_acknowledgement',
     'enable_bugfiling_duplicate_search']
 
-    >>> print package.bug_reporting_guidelines
+    >>> print(package.bug_reporting_guidelines)
     None
 
     >>> form = {
@@ -191,8 +191,8 @@ The view allows the user the set the bug_reporting_guidelines field.
     >>> view = create_initialized_view(package, '+edit', form=form)
     >>> view.errors
     []
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/youbuntu/+source/bonkers
 
-    >>> print package.bug_reporting_guidelines
+    >>> print(package.bug_reporting_guidelines)
     guidelines
diff --git a/lib/lp/registry/browser/tests/distroseries-views.txt b/lib/lp/registry/browser/tests/distroseries-views.txt
index 54bd8a0..06dc916 100644
--- a/lib/lp/registry/browser/tests/distroseries-views.txt
+++ b/lib/lp/registry/browser/tests/distroseries-views.txt
@@ -15,13 +15,13 @@ The +admin view allows administrators to change a series. It provides a
 label, page_title, and cancel_url
 
     >>> view = create_initialized_view(hoary, name='+admin')
-    >>> print view.label
+    >>> print(view.label)
     Administer The Hoary Hedgehog Release
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Administer The Hoary Hedgehog Release
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/ubuntu/hoary
 
 We will use a function to print the details related with the
@@ -29,17 +29,17 @@ distroseries being tested.
 
     >>> def administrate_distroseries(distroseries, form):
     ...     view = create_initialized_view(hoary, name='+admin', form=form)
-    ...     print '%d errors' % len(view.errors)
+    ...     print('%d errors' % len(view.errors))
     ...     for error in view.errors:
     ...         try:
     ...             name, title, message = error
     ...         except ValueError:
     ...             title, message = error
-    ...         print '%s: %s' % (title, message)
-    ...     print 'Name:', distroseries.name
-    ...     print 'Version:', distroseries.version
-    ...     print 'Changeslist:', distroseries.changeslist
-    ...     print 'Status:', distroseries.status.name
+    ...         print('%s: %s' % (title, message))
+    ...     print('Name:', distroseries.name)
+    ...     print('Version:', distroseries.version)
+    ...     print('Changeslist:', distroseries.changeslist)
+    ...     print('Status:', distroseries.status.name)
 
     >>> form = {
     ...     'field.actions.change': 'Change',
@@ -91,7 +91,7 @@ When the distroseries is released, i.e. when it goes from an unstable
 status (FUTURE, EXPERIMENTAL, DEVELOPMENT, FROZEN) to CURRENT, its
 'datereleased' field is set.
 
-    >>> print hoary.datereleased
+    >>> print(hoary.datereleased)
     None
 
     >>> form['field.status'] = 'CURRENT'
@@ -160,13 +160,13 @@ uses the display_name, title, and description fields.
     >>> hoary.driver = driver
     >>> ignored = login_person(driver)
     >>> view = create_initialized_view(hoary, '+edit')
-    >>> print view.label
+    >>> print(view.label)
     Edit The Hoary Hedgehog Release details
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Edit The Hoary Hedgehog Release details
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/ubuntu/hoary
 
     >>> [field.__name__ for field in view.form_fields]
@@ -191,13 +191,13 @@ Series that belong to derivative distributions also contain the status field.
     >>> youbuntu.driver = yo_driver
     >>> ignored = login_person(yo_driver)
     >>> view = create_initialized_view(yo_series, '+edit')
-    >>> print view.label
+    >>> print(view.label)
     Edit Melon details
 
     >>> [field.__name__ for field in view.form_fields]
     ['display_name', 'title', 'summary', 'description', 'status']
 
-    >>> print view.widgets.get('status')._getFormValue().title
+    >>> print(view.widgets.get('status')._getFormValue().title)
     Active Development
 
 
@@ -209,14 +209,14 @@ A distroseries is created using the distroseries view.
     >>> login('foo.bar@xxxxxxxxxxxxx')
 
     >>> view = create_view(ubuntu, '+addseries')
-    >>> print view.page_title
+    >>> print(view.page_title)
     Add a series
-    >>> print view.label
+    >>> print(view.label)
     Add a series
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/ubuntu
-    >>> print view.next_url
+    >>> print(view.next_url)
     None
 
     >>> view.field_names
@@ -235,7 +235,7 @@ A distroseries is created whent the required field are submitted.
     >>> view.errors
     []
     >>> sane_distroseries = ubuntu.getSeries('sane')
-    >>> print sane_distroseries.name
+    >>> print(sane_distroseries.name)
     sane
 
     # Save this series to test name and version constraints.
@@ -273,7 +273,7 @@ Launchpad for package management can create a series.
     []
 
     >>> yo_series = youbuntu.getSeries('island')
-    >>> print yo_series.display_name
+    >>> print(yo_series.display_name)
     Island
 
 But drivers of distributions that use Soyuz officially (eg. Ubuntu)
@@ -297,7 +297,7 @@ Drivers editing distro series
 The series driver (release manager) can edit a series if the series
 doesn't manage its packages in Launchpad.
 
-    >>> print yo_series.driver.name
+    >>> print(yo_series.driver.name)
     yo-driver
 
     >>> ignored = login_person(yo_driver)
@@ -315,7 +315,7 @@ doesn't manage its packages in Launchpad.
     >>> view.errors
     []
 
-    >>> print yo_series.display_name
+    >>> print(yo_series.display_name)
     Mountain
 
 Drivers of packages with packages such as Ubuntu cannot edit a series.
@@ -340,7 +340,7 @@ The distroseries name is unique.
     >>> form['field.version'] = '2009.07'
     >>> view = create_initialized_view(ubuntu, '+addseries', form=form)
     >>> for error in view.errors:
-    ...     print error[2]
+    ...     print(error[2])
     sane is already in use by another series.
 
 The distroseries name cannot contain spaces.
@@ -348,7 +348,7 @@ The distroseries name cannot contain spaces.
     >>> form['field.name'] = 'insane name'
     >>> view = create_initialized_view(ubuntu, '+addseries', form=form)
     >>> for error in view.errors:
-    ...     print error[2]
+    ...     print(error[2])
     Invalid name 'insane name'...
 
 
@@ -361,7 +361,7 @@ Versions cannot contain spaces.
     >>> form['field.version'] = '6.06 LTS'
     >>> view = create_initialized_view(ubuntu, '+addseries', form=form)
     >>> for error in view.errors:
-    ...     print error[2]
+    ...     print(error[2])
     6.06 LTS is not a valid version
 
 The distroseries version must be a valid debversion.
@@ -369,20 +369,20 @@ The distroseries version must be a valid debversion.
     >>> form['field.version'] = 'Hardy-6.06-LTS'
     >>> view = create_initialized_view(ubuntu, '+addseries', form=form)
     >>> for error in view.errors:
-    ...     print error[2]
+    ...     print(error[2])
     &#x27;Hardy-6.06-LTS&#x27;: Could not parse version...
 
 The distroseries version is unique to a distribution. Version '2009.06'
 cannot be reused by another Ubuntu series.
 
-    >>> print sane_distroseries.version
+    >>> print(sane_distroseries.version)
     2009.06
 
     >>> form['field.name'] = 'experimental'
     >>> form['field.version'] = '2009.06'
     >>> view = create_initialized_view(ubuntu, '+addseries', form=form)
     >>> for error in view.errors:
-    ...     print error[2]
+    ...     print(error[2])
     2009.06 is already in use by another version in this distribution.
 
 But version '2009.06' can be used by another distribution.
@@ -393,5 +393,5 @@ But version '2009.06' can be used by another distribution.
     []
 
     >>> experimental_distroseries = other_distro.getSeries('experimental')
-    >>> print experimental_distroseries.version
+    >>> print(experimental_distroseries.version)
     2009.06
diff --git a/lib/lp/registry/browser/tests/karmaaction-views.txt b/lib/lp/registry/browser/tests/karmaaction-views.txt
index fc3f14d..1d38bd0 100644
--- a/lib/lp/registry/browser/tests/karmaaction-views.txt
+++ b/lib/lp/registry/browser/tests/karmaaction-views.txt
@@ -18,7 +18,7 @@ The karma action set +index view lists all the karma actions.
     >>> user = getUtility(ILaunchBag).user
     >>> view = create_view(karmaactionset, '+index', principal=user,
     ...     path_info='/karmaaction')
-    >>> print extract_text(find_tag_by_id(view(), 'karmas'))
+    >>> print(extract_text(find_tag_by_id(view(), 'karmas')))
     Category        Action          Points
     bugs            Bug Accepted    5
     ...
@@ -32,13 +32,13 @@ view provides a label, page_title and a cancel_url
 
     >>> action = karmaactionset.getByName('branchcreated')
     >>> view = create_initialized_view(action, '+index')
-    >>> print view.label
+    >>> print(view.label)
     Edit New branch registered karma action
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Edit New branch registered karma action
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/karmaaction
 
 The admin can edit the karma action's fields.
@@ -58,7 +58,7 @@ The admin can edit the karma action's fields.
     >>> view.errors
     []
 
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/karmaaction
 
     >>> action.points
diff --git a/lib/lp/registry/browser/tests/karmacontext-views.txt b/lib/lp/registry/browser/tests/karmacontext-views.txt
index 86e23da..3546713 100644
--- a/lib/lp/registry/browser/tests/karmacontext-views.txt
+++ b/lib/lp/registry/browser/tests/karmacontext-views.txt
@@ -22,8 +22,8 @@ contributors on a given context and the top contributors by category.
     >>> contributors = view.top_contributors_by_category
     >>> categories = sorted(contributors.keys())
     >>> for category in categories:
-    ...     print category, [(contrib.person.name, contrib.karmavalue)
-    ...                      for contrib in contributors[category]]
+    ...     print(category, [(contrib.person.name, contrib.karmavalue)
+    ...                      for contrib in contributors[category]])
     Bug Management [(u'name16', 11)]
     Specification Tracking [(u'mark', 22)]
     Translations in Rosetta [(u'name16', 164), (u'carlos', 9)]
@@ -31,21 +31,21 @@ contributors on a given context and the top contributors by category.
 The view renders summaries by category.
 
     >>> content = find_tag_by_id(view.render(), 'maincontent')
-    >>> print extract_text(find_tag_by_id(content, 'overall_top'))
+    >>> print(extract_text(find_tag_by_id(content, 'overall_top')))
     Person             Project Karma  Total Karma
     Foo Bar            175            241
     Mark Shuttleworth   22            130
     Carlos ...           9              9
 
-    >>> print extract_text(find_tag_by_id(content, 'Bug Management'))
+    >>> print(extract_text(find_tag_by_id(content, 'Bug Management')))
     Person   Bug Management Karma  Total Karma
     Foo Bar  11                     241
 
-    >>> print extract_text(find_tag_by_id(content, 'Specification Tracking'))
+    >>> print(extract_text(find_tag_by_id(content, 'Specification Tracking')))
     Person             Specification Tracking Karma  Total Karma
     Mark Shuttleworth  22                            130
 
-    >>> print extract_text(find_tag_by_id(content, 'Translations in Rosetta'))
+    >>> print(extract_text(find_tag_by_id(content, 'Translations in Rosetta')))
     Person      Translations in Rosetta Karma  Total Karma
     Foo Bar     164                            241
     Carlos ...    9                              9
@@ -59,7 +59,7 @@ The top contributors portlet shows the top contributors to a project
     >>> view = create_initialized_view(
     ...     product, name='+portlet-top-contributors', principal=user)
     >>> content = find_tag_by_id(view.render(), 'portlet-top-contributors')
-    >>> print extract_text(content)
+    >>> print(extract_text(content))
     More contributors Top contributors
     Foo Bar...
     Mark ...
@@ -69,5 +69,5 @@ It has a link to +topcontributors page.
 
     >>> css_class = {'class': 'menu-link-top_contributors sprite info'}
     >>> link = content.find('a', css_class)
-    >>> print link['href']
+    >>> print(link['href'])
     http://launchpad.test/evolution/+topcontributors
diff --git a/lib/lp/registry/browser/tests/mailinglist-views.txt b/lib/lp/registry/browser/tests/mailinglist-views.txt
index 513bfb3..6bad9a7 100644
--- a/lib/lp/registry/browser/tests/mailinglist-views.txt
+++ b/lib/lp/registry/browser/tests/mailinglist-views.txt
@@ -91,7 +91,7 @@ no communication between the two systems.
 Nobody can purge an active mailing list, the team owner...
 
     >>> view = create_view(the_owner)
-    >>> print view.label
+    >>> print(view.label)
     Mailing list configuration
     >>> view.list_can_be_purged
     False
@@ -117,7 +117,7 @@ Even subverting the form will not trick Launchpad into purging the list.
     >>> view = create_view(
     ...     an_admin,
     ...     {'field.actions.purge_list': u'Purge this Mailing List'})
-    >>> print '\n'.join(view.errors)
+    >>> print('\n'.join(view.errors))
     This list cannot be purged.
 
 Now the team owner deactivates the mailing list.  When this completes
diff --git a/lib/lp/registry/browser/tests/milestone-views.txt b/lib/lp/registry/browser/tests/milestone-views.txt
index 672a7d1..6747dda 100644
--- a/lib/lp/registry/browser/tests/milestone-views.txt
+++ b/lib/lp/registry/browser/tests/milestone-views.txt
@@ -15,7 +15,7 @@ The default url for a milestone is to the main site.
 
     >>> request = LaunchpadTestRequest(SERVER_URL='http://bugs.launchpad.net')
     >>> login(ANONYMOUS, request)
-    >>> print test_tales("milestone/fmt:url", milestone=milestone)
+    >>> print(test_tales("milestone/fmt:url", milestone=milestone))
     http://launchpad.test/puffin/+milestone/kakapo
 
 Milestone defines several menus.
@@ -49,23 +49,23 @@ it has one.
 
     >>> ignored = login_person(person)
     >>> view = create_view(milestone, '+index')
-    >>> print view.context.name
+    >>> print(view.context.name)
     kakapo
 
-    >>> print view.milestone.name
+    >>> print(view.milestone.name)
     kakapo
 
-    >>> print view.release
+    >>> print(view.release)
     None
 
     >>> release = factory.makeProductRelease(milestone)
     >>> view = create_view(milestone, '+index')
-    >>> print view.release.version
+    >>> print(view.release.version)
     kakapo
 
 The view makes the HTML page title.
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Puffin kakapo
 
 Bugs and specifications targeted to the milestone are accessible too.
@@ -91,11 +91,11 @@ milestone has any bugs or specifications.
     True
 
     >>> for bugtask in view.bugtasks:
-    ...     print bugtask.bug.title
+    ...     print(bugtask.bug.title)
     kiwi
 
     >>> for spec in view.specifications:
-    ...     print spec.title
+    ...     print(spec.title)
     dodo
 
 On a IDistroSeries/IProductSeries main page, we use this view to list detailed
@@ -124,7 +124,7 @@ is used by the decorator.
     ...     bugtask
     ...     badge_dict = view._bug_badge_properties[bugtask]
     ...     for key in sorted(badge_dict):
-    ...         print '%s: %s' % (key, badge_dict[key])
+    ...         print('%s: %s' % (key, badge_dict[key]))
     <BugTask ...>
         has_branch: False
         has_patch: False
@@ -137,10 +137,10 @@ There bugtask_count_text and specification_count_text properties provide
 formatted text descriptions of the bugtasks and specifications. The text
 supports plural descriptions.
 
-    >>> print view.bugtask_count_text
+    >>> print(view.bugtask_count_text)
     1 bug
 
-    >>> print view.specification_count_text
+    >>> print(view.specification_count_text)
     1 blueprint
 
     >>> bug = factory.makeBug(title="emo")
@@ -152,10 +152,10 @@ supports plural descriptions.
     >>> spec.milestone = milestone
 
     >>> view = create_view(milestone, '+index')
-    >>> print view.bugtask_count_text
+    >>> print(view.bugtask_count_text)
     2 bugs
 
-    >>> print view.specification_count_text
+    >>> print(view.specification_count_text)
     2 blueprints
 
 Bugtasks are ordered by status (fix released last), and importance
@@ -163,7 +163,7 @@ Bugtasks are ordered by status (fix released last), and importance
 
     >>> for bugtask in view.bugtasks:
     ...     assignee = bugtask.assignee
-    ...     print bugtask.bug.title, assignee.name, bugtask.status.title
+    ...     print(bugtask.bug.title, assignee.name, bugtask.status.title)
     emo   puffin-owner  New
     kiwi  puffin-owner  Fix Committed
 
@@ -180,12 +180,12 @@ specifications and bugtasks.
     >>> status = spec.updateLifecycleStatus(person)
 
     >>> for status_count in view.specification_status_counts:
-    ...     print '%s: %s' % (status_count.status.title, status_count.count)
+    ...     print('%s: %s' % (status_count.status.title, status_count.count))
     Unknown: 1
     Good progress: 1
 
     >>> for status_count in view.bugtask_status_counts:
-    ...     print '%s: %s' % (status_count.status.title, status_count.count)
+    ...     print('%s: %s' % (status_count.status.title, status_count.count))
     New: 1
     Fix Committed: 1
 
@@ -193,14 +193,14 @@ The assignment_counts property returns all the users and count of bugs and
 specifications assigned to them.
 
     >>> for status_count in view.assignment_counts:
-    ...     print '%s: %s' % (status_count.status.name, status_count.count)
+    ...     print('%s: %s' % (status_count.status.name, status_count.count))
     engineer: 1
     puffin-owner: 2
 
 The user_counts property is the count items assigned to the current user.
 
     >>> for status_count in view.user_counts:
-    ...     print '%s: %s' % (status_count.status, status_count.count)
+    ...     print('%s: %s' % (status_count.status, status_count.count))
     bugs: 2
 
 The user_counts property is an empty list if the user is None.
@@ -225,7 +225,7 @@ release as a set.
 The download_files property returns a decorated list of IProductRelease
 files. If there is no release, or no files, None is returned.
 
-    >>> print view.download_files
+    >>> print(view.download_files)
     None
 
 If there are files, these files will be returned as a list.
@@ -251,22 +251,22 @@ the product release data for a milestone.
     >>> view = create_view(
     ...     milestone, '+productrelease-data', principal=person)
     >>> content = find_tag_by_id(view.render(), 'release-data')
-    >>> print find_tag_by_id(content, 'how-to-verify').a['href']
+    >>> print(find_tag_by_id(content, 'how-to-verify').a['href'])
     /+help-registry/verify-downloads.html
 
-    >>> print extract_text(find_tag_by_id(content, 'downloads'))
+    >>> print(extract_text(find_tag_by_id(content, 'downloads')))
     File                 Description  Downloads  Delete
     test.txt (md5, sig)  test file ...
 
-    >>> print find_tag_by_id(content, 'delete-files')['type']
+    >>> print(find_tag_by_id(content, 'delete-files')['type'])
     submit
 
 This release does not not have release notes or a change log.
 
-    >>> print find_tag_by_id(content, 'release-notes')
+    >>> print(find_tag_by_id(content, 'release-notes'))
     None
 
-    >>> print find_tag_by_id(content, 'changelog')
+    >>> print(find_tag_by_id(content, 'changelog'))
     None
 
 This release notes and change log do appear when the release has them.
@@ -276,10 +276,10 @@ This release notes and change log do appear when the release has them.
     >>> view = create_view(
     ...     milestone, '+productrelease-data', principal=person)
     >>> content = find_tag_by_id(view.render(), 'release-data')
-    >>> print extract_text(find_tag_by_id(content, 'release-notes'))
+    >>> print(extract_text(find_tag_by_id(content, 'release-notes')))
     My release notes
 
-    >>> print extract_text(find_tag_by_id(content, 'changelog'))
+    >>> print(extract_text(find_tag_by_id(content, 'changelog')))
     My changelog
 
 The delete column and delete submit are not rendered if the user does
@@ -289,11 +289,11 @@ not have edit permission.
     >>> view = create_view(
     ...     milestone, '+productrelease-data', principal=engineer)
     >>> content = find_tag_by_id(view.render(), 'release-data')
-    >>> print extract_text(find_tag_by_id(content, 'downloads'))
+    >>> print(extract_text(find_tag_by_id(content, 'downloads')))
     File                 Description  Downloads
     test.txt (md5, sig)  test file ...
 
-    >>> print find_tag_by_id(content, 'delete-files')
+    >>> print(find_tag_by_id(content, 'delete-files'))
     None
 
     >>> ignored = login_person(person)
@@ -310,14 +310,14 @@ generates CSS that hides the space occupied by the side portlets.
     >>> project_milestone = projectgroup.getMilestone('kakapo')
     >>> view = create_initialized_view(
     ...     project_milestone, '+index', principal=person)
-    >>> print find_tag_by_id(view.render(), 'hide-side-portlets')['type']
+    >>> print(find_tag_by_id(view.render(), 'hide-side-portlets')['type'])
     text/css
 
 A normal milestone does not have the CSS rule.
 
     >>> view = create_initialized_view(
     ...     milestone, '+index', principal=person)
-    >>> print find_tag_by_id(content, 'hide-side-portlets')
+    >>> print(find_tag_by_id(content, 'hide-side-portlets'))
     None
 
 
@@ -343,33 +343,33 @@ user may edit.
 The view allows the user to modify the mutable milestone fields. The
 cancel_url property can be used to return to the milestone.
 
-    >>> print view.label
+    >>> print(view.label)
     Modify milestone details
 
     >>> view.field_names
     ['name', 'code_name', 'active', 'dateexpected', 'tags', 'summary',
      'productseries']
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/firefox/+milestone/1.0.8
 
 This milestone belongs to a product, so the productseries field is
 included in the list of field names. The user can change the field
 values.
 
-    >>> print milestone.name
+    >>> print(milestone.name)
     1.0.8
 
-    >>> print milestone.dateexpected
+    >>> print(milestone.dateexpected)
     None
 
-    >>> print milestone.summary
+    >>> print(milestone.summary)
     None
 
     >>> milestone.active
     True
 
-    >>> print milestone.productseries.name
+    >>> print(milestone.productseries.name)
     1.0
 
     >>> form = {
@@ -383,19 +383,19 @@ values.
     ...     }
     >>> view = create_initialized_view(milestone, '+edit', form=form)
 
-    >>> print milestone.name
+    >>> print(milestone.name)
     1.0.9
 
-    >>> print milestone.dateexpected
+    >>> print(milestone.dateexpected)
     2007-05-11
 
-    >>> print milestone.summary
+    >>> print(milestone.summary)
     a summary
 
     >>> milestone.active
     False
 
-    >>> print milestone.productseries.name
+    >>> print(milestone.productseries.name)
     trunk
 
 The milestone's name is unique to the product or series.
@@ -412,11 +412,11 @@ The milestone's name is unique to the product or series.
     ...     }
     >>> view = create_initialized_view(milestone, '+edit', form=form)
     >>> for error in view.errors:
-    ...     print error.errors
+    ...     print(error.errors)
     The name 1.0 is already used by a milestone in Mozilla Firefox.
 
     >>> for milestone in milestone.target.milestones:
-    ...     print milestone.name, milestone.code_name
+    ...     print(milestone.name, milestone.code_name)
     1.0 None
 
 The view restricts the productseries field to series that belong to the
@@ -430,7 +430,7 @@ product. A series from another product is rejected.
     >>> form['field.productseries'] = '100'
     >>> view = create_initialized_view(milestone, '+edit', form=form)
 
-    >>> print milestone.productseries.name
+    >>> print(milestone.productseries.name)
     trunk
 
 A milestone that belongs to the distroseries has a distroseries field
@@ -462,22 +462,22 @@ The distroseries milestone can be updated too.
     ...     }
     >>> view = create_initialized_view(milestone, '+edit', form=form)
 
-    >>> print milestone.name
+    >>> print(milestone.name)
     omega
 
-    >>> print milestone.code_name
+    >>> print(milestone.code_name)
     omega-licious
 
-    >>> print milestone.dateexpected
+    >>> print(milestone.dateexpected)
     2007-05-11
 
-    >>> print milestone.summary
+    >>> print(milestone.summary)
     a summary
 
     >>> milestone.active
     False
 
-    >>> print milestone.distroseries.name
+    >>> print(milestone.distroseries.name)
     grumpy
 
 Like the productseries field, the distroseries field only accepts series
@@ -491,7 +491,7 @@ that belong to the distribution.
     >>> form['field.distroseries'] = '100'
     >>> view = create_initialized_view(milestone, '+edit', form=form)
 
-    >>> print milestone.distroseries.name
+    >>> print(milestone.distroseries.name)
     grumpy
 
 Users without launchpad.Edit permissions cannot access the view.
@@ -513,7 +513,7 @@ The AddMilestoneView is used to create a new milestone.
     >>> owner = firefox.owner
     >>> ignored = login_person(owner)
     >>> view = create_initialized_view(firefox_1_0, '+addmilestone')
-    >>> print view.label
+    >>> print(view.label)
     Register a new milestone
 
     >>> view.field_names
@@ -522,10 +522,10 @@ The AddMilestoneView is used to create a new milestone.
 The view provides an action_url and cancel_url properties that form
 submitting the form or aborting the action.
 
-    >>> print view.action_url
+    >>> print(view.action_url)
     http://launchpad.test/firefox/1.0/+addmilestone
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/firefox/1.0
 
 Only the name of the milestone is required.
@@ -537,7 +537,7 @@ Only the name of the milestone is required.
     >>> view = create_initialized_view(
     ...     firefox_1_0, '+addmilestone', form=form)
     >>> for milestone in firefox_1_0.milestones:
-    ...     print milestone.name, milestone.code_name
+    ...     print(milestone.name, milestone.code_name)
     1.1 None
 
 The milestone name is unique to a product or distribution. The view
@@ -552,11 +552,11 @@ cannot create a duplicate milestone.
     >>> view = create_initialized_view(
     ...     firefox_1_0, '+addmilestone', form=form)
     >>> for error in view.errors:
-    ...     print error.errors
+    ...     print(error.errors)
     The name 1.1 is already used by a milestone in Mozilla Firefox.
 
     >>> for milestone in firefox_1_0.milestones:
-    ...     print milestone.name, milestone.code_name
+    ...     print(milestone.name, milestone.code_name)
     1.1 None
 
 An empty code_name or summary (submitted via AJAX) is converted to None.
@@ -570,7 +570,7 @@ An empty code_name or summary (submitted via AJAX) is converted to None.
     >>> view = create_initialized_view(
     ...     firefox_1_0, '+addmilestone', form=form)
     >>> for milestone in firefox_1_0.milestones:
-    ...     print milestone.name, milestone.code_name, milestone.summary
+    ...     print(milestone.name, milestone.code_name, milestone.summary)
     2.1 None None
     1.1 None None
 
@@ -594,7 +594,7 @@ release manager and can create milestones.
     >>> view = create_initialized_view(
     ...     distroseries, '+addmilestone', form=form)
     >>> milestone = distroseries.milestones[0]
-    >>> print milestone.name
+    >>> print(milestone.name)
     pie
 
 The driver has access to the milestone.
@@ -631,7 +631,7 @@ of the series.
 
     >>> ignored = login_person(owner)
     >>> milestone = firefox_1_0.newMilestone('1.0.10')
-    >>> print milestone.name
+    >>> print(milestone.name)
     1.0.10
 
     >>> view = create_initialized_view(milestone, '+delete')
@@ -648,7 +648,7 @@ release or product release files.
     >>> view.specifications
     []
 
-    >>> print view.product_release
+    >>> print(view.product_release)
     None
 
     >>> view.product_release_files
@@ -661,10 +661,10 @@ The milestone is deleted when the delete action is called.
     ...     }
     >>> view = create_initialized_view(milestone, '+delete', form=form)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Milestone 1.0.10 deleted.
 
-    >>> print firefox.getMilestone('1.0.10')
+    >>> print(firefox.getMilestone('1.0.10'))
     None
 
 The view will delete the dependent product release and release files if
@@ -703,19 +703,19 @@ milestone.
 
     >>> view = create_initialized_view(milestone, '+delete', form=form)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Milestone 1.0.11 deleted.
 
-    >>> print firefox.getMilestone('1.0.11')
+    >>> print(firefox.getMilestone('1.0.11'))
     None
 
-    >>> print firefox_1_0.getRelease('1.0.11')
+    >>> print(firefox_1_0.getRelease('1.0.11'))
     None
 
-    >>> print specification.milestone
+    >>> print(specification.milestone)
     None
 
-    >>> print bugtask.milestone
+    >>> print(bugtask.milestone)
     None
 
     >>> [subscription for subscription in owner.structural_subscriptions]
@@ -748,9 +748,9 @@ to a private bug that was targeted to a milestone by a driver.
 
     >>> view = create_initialized_view(milestone, '+delete', form=form)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Milestone 1.0.13 deleted.
 
     >>> transaction.commit()
-    >>> print private_bugtask.milestone
+    >>> print(private_bugtask.milestone)
     None
diff --git a/lib/lp/registry/browser/tests/nameblacklist-views.txt b/lib/lp/registry/browser/tests/nameblacklist-views.txt
index 0a5bc44..9f69f0b 100644
--- a/lib/lp/registry/browser/tests/nameblacklist-views.txt
+++ b/lib/lp/registry/browser/tests/nameblacklist-views.txt
@@ -25,8 +25,8 @@ person names can be seen on the /+nameblacklist page.
     >>> ignored = login_person(registry_expert)
     >>> view = create_initialized_view(name_blacklist_set, '+index',
     ...                                principal=registry_expert)
-    >>> print extract_text(
-    ...     find_tag_by_id(view.render(), 'blacklist'), formatter='html')
+    >>> print(extract_text(
+    ...     find_tag_by_id(view.render(), 'blacklist'), formatter='html'))
     Regular Expression                   Admin    Comment
     ^admin Edit blacklist expression     &mdash;
     blacklist Edit blacklist expression  &mdash;  For testing purposes
@@ -45,7 +45,7 @@ An invalid regular expression cannot be added.
     ...     }
     >>> view = create_initialized_view(name_blacklist_set, '+add', form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     Invalid regular expression: unbalanced parenthesis
 
 A duplicate regular expression cannot be added.
@@ -53,7 +53,7 @@ A duplicate regular expression cannot be added.
     >>> form['field.regexp'] = u'blacklist'
     >>> view = create_initialized_view(name_blacklist_set, '+add', form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     This regular expression already exists.
 
 After adding a regular expression, a notification will be displayed.
@@ -61,14 +61,14 @@ After adding a regular expression, a notification will be displayed.
     >>> form['field.regexp'] = u'foo'
     >>> view = create_initialized_view(name_blacklist_set, '+add', form=form)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Regular expression &quot;foo&quot; has been added to the name blacklist.
 
     >>> transaction.commit()
     >>> foo_exp = name_blacklist_set.getByRegExp(u'foo')
-    >>> print foo_exp.regexp
+    >>> print(foo_exp.regexp)
     foo
-    >>> print foo_exp.admin.name
+    >>> print(foo_exp.admin.name)
     registry
 
 
@@ -85,7 +85,7 @@ When a regular expression is edited, it still must be valid.
     ...     }
     >>> view = create_initialized_view(foo_exp, '+edit', form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     Invalid regular expression: unbalanced parenthesis
 
 It cannot changed to conflict with another regular expression.
@@ -93,12 +93,12 @@ It cannot changed to conflict with another regular expression.
     >>> form['field.regexp'] = u'blacklist'
     >>> view = create_initialized_view(foo_exp, '+edit', form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     This regular expression already exists.
 
 Otherwise, the change will be successful.
 
     >>> form['field.regexp'] = u'bar'
     >>> view = create_initialized_view(foo_exp, '+edit', form=form)
-    >>> print foo_exp.regexp, foo_exp.comment
+    >>> print(foo_exp.regexp, foo_exp.comment)
     bar new-comment
diff --git a/lib/lp/registry/browser/tests/packaging-views.txt b/lib/lp/registry/browser/tests/packaging-views.txt
index 8120834..98dd27d 100644
--- a/lib/lp/registry/browser/tests/packaging-views.txt
+++ b/lib/lp/registry/browser/tests/packaging-views.txt
@@ -29,27 +29,27 @@ The distroseries field's vocabulary is the same as the ubuntu.series
 attribute.
 
     >>> view = create_view(productseries, '+ubuntupkg')
-    >>> print view.label
+    >>> print(view.label)
     Ubuntu source packaging
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Ubuntu source packaging
 
-    >>> print view.field_names
+    >>> print(view.field_names)
     ['sourcepackagename', 'distroseries']
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/hot/hotter
 
     >>> for series in ubuntu.series:
-    ...     print series.name
+    ...     print(series.name)
     breezy-autotest
     grumpy
     hoary
     warty
     >>> view.setUpFields()
     >>> for term in view.form_fields['distroseries'].field.vocabulary:
-    ...     print term.token
+    ...     print(term.token)
     breezy-autotest
     grumpy
     hoary
@@ -66,7 +66,7 @@ attribute.
     >>> view.errors
     []
     >>> for package in productseries.sourcepackages:
-    ...     print package.name
+    ...     print(package.name)
     hot
 
     >>> transaction.commit()
@@ -80,29 +80,29 @@ Ubuntu package.
 
     >>> view = create_initialized_view(productseries, '+ubuntupkg')
 
-    >>> print view.label
+    >>> print(view.label)
     Ubuntu source packaging
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Ubuntu source packaging
 
-    >>> print view.field_names
+    >>> print(view.field_names)
     ['sourcepackagename', 'distroseries']
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/hot/hotter
 
 The view restricts the packaging to Ubuntu series, and default is the current
 Ubuntu series.
 
-    >>> print view.default_distroseries.name
+    >>> print(view.default_distroseries.name)
     hoary
 
-    >>> print view.widgets['distroseries']._getDefault().name
+    >>> print(view.widgets['distroseries']._getDefault().name)
     hoary
 
     >>> for term in view.widgets['distroseries'].vocabulary:
-    ...     print term.title
+    ...     print(term.title)
     Breezy Badger Autotest (6.6.6)
     Grumpy (5.10)
     Hoary (5.04)
@@ -115,28 +115,28 @@ packaging history is empty, and the sourcepackagename widget is empty.
     ...     product=product, name='cold')
     >>> view = create_initialized_view(new_productseries, '+ubuntupkg')
 
-    >>> print view.default_sourcepackagename
+    >>> print(view.default_sourcepackagename)
     None
 
-    >>> print view.widgets.get('sourcepackagename')._getFormValue()
+    >>> print(view.widgets.get('sourcepackagename')._getFormValue())
     <BLANKLINE>
 
-    >>> print view.ubuntu_history
+    >>> print(view.ubuntu_history)
     []
 
 Series have been packaged in Ubuntu do have the current information and
 a history.
 
     >>> view = create_initialized_view(productseries, '+ubuntupkg')
-    >>> print view.default_sourcepackagename.name
+    >>> print(view.default_sourcepackagename.name)
     hot
 
-    >>> print view.widgets.get('sourcepackagename')._getFormValue().name
+    >>> print(view.widgets.get('sourcepackagename')._getFormValue().name)
     hot
 
     >>> for packaging in view.ubuntu_history:
-    ...     print packaging.distroseries.name
-    ...     print packaging.sourcepackagename.name
+    ...     print(packaging.distroseries.name)
+    ...     print(packaging.sourcepackagename.name)
     hoary hot
 
 The package in the current Ubuntu series can be updated.
@@ -156,8 +156,8 @@ The package in the current Ubuntu series can be updated.
 We now have two source packages linked to our productseries.
 
     >>> for packaging in view.ubuntu_history:
-    ...     print packaging.distroseries.name
-    ...     print packaging.sourcepackagename.name
+    ...     print(packaging.distroseries.name)
+    ...     print(packaging.sourcepackagename.name)
     hoary thunderbird
     hoary hot
 
@@ -174,8 +174,8 @@ action is ignored because there is no change
     []
 
     >>> for packaging in view.ubuntu_history:
-    ...     print packaging.distroseries.name
-    ...     print packaging.sourcepackagename.name
+    ...     print(packaging.distroseries.name)
+    ...     print(packaging.sourcepackagename.name)
     hoary thunderbird
     hoary hot
 
@@ -202,15 +202,15 @@ and a new entry can be added to the packaging history.
     >>> view.errors
     []
 
-    >>> print view.default_distroseries.name
+    >>> print(view.default_distroseries.name)
     grumpy
 
-    >>> print view.default_sourcepackagename
+    >>> print(view.default_sourcepackagename)
     None
 
     >>> for packaging in view.ubuntu_history:
-    ...     print packaging.distroseries.name
-    ...     print packaging.sourcepackagename.name
+    ...     print(packaging.distroseries.name)
+    ...     print(packaging.sourcepackagename.name)
     grumpy hot
     hoary thunderbird
     hoary hot
@@ -222,18 +222,18 @@ Product packages view
 The +packages named view displays the packages links to the product's series.
 
     >>> view = create_initialized_view(product, name='+packages')
-    >>> print view.label
+    >>> print(view.label)
     Linked packages
 
 The view provides the series_batch property.
 
     >>> def print_packages(view):
     ...     for series in view.series_batch.batch:
-    ...         print series.name
+    ...         print(series.name)
     ...         for package in series.packagings:
-    ...             print '  Package %s: %s' % (
+    ...             print('  Package %s: %s' % (
     ...                 package.sourcepackagename.name,
-    ...                 package.distroseries.name)
+    ...                 package.distroseries.name))
     >>> print_packages(view)
     trunk
     hotter
@@ -248,7 +248,7 @@ sorted by distribution with Ubuntu first and the rest in alphabetic
 order.
 
     >>> for distro_dict in view.distro_packaging:
-    ...     print distro_dict['distribution'].name
+    ...     print(distro_dict['distribution'].name)
     ubuntu
 
 A packaging link can be deleted if the owner believes it is an error. The
@@ -275,7 +275,7 @@ instead.)
     >>> table = find_tag_by_id(view.render(), 'packages-hotter')
     >>> for link in table.findAll('a'):
     ...     if '+remove-packaging' in link['href']:
-    ...         print link['href']
+    ...         print(link['href'])
     http://launchpad.test/ubuntu/grumpy/+source/hot/+remove-packaging
     http://launchpad.test/ubuntu/hoary/+source/thunderbird/+remove-packaging
     http://launchpad.test/ubuntu/hoary/+source/hot/+remove-packaging
@@ -309,10 +309,10 @@ The DistroSeriesPackagesView shows the packages in a distro series that
 are linked to upstream projects.
 
     >>> view = create_initialized_view(hoary, name='+packaging')
-    >>> print view.label
+    >>> print(view.label)
     All series packages linked to upstream project series
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     All upstream links
 
 The view provides a property to get prioritized list of series packagings.
@@ -325,11 +325,11 @@ to access the packagings. The default batch size is 20.
     >>> batch_navigator.default_size
     20
 
-    >>> print batch_navigator.heading
+    >>> print(batch_navigator.heading)
     packagings
 
     >>> for packaging in batch_navigator.batch:
-    ...     print packaging.sourcepackagename.name
+    ...     print(packaging.sourcepackagename.name)
     netapplet
     evolution
     hot
@@ -342,10 +342,10 @@ The +needs-packaging view lists the source packages that needs packaging
 links to an upstream project.
 
     >>> view = create_initialized_view(hoary, name='+needs-packaging')
-    >>> print view.label
+    >>> print(view.label)
     Packages that need upstream packaging links
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Needs upstream links
 
 The view provides the cached_unlinked_packages property to access a
@@ -355,11 +355,11 @@ The view provides the cached_unlinked_packages property to access a
     >>> batch_navigator.default_size
     20
 
-    >>> print batch_navigator.heading
+    >>> print(batch_navigator.heading)
     packages
 
     >>> for summary in batch_navigator.batch:
-    ...     print summary['package'].name
+    ...     print(summary['package'].name)
     pmount
     alsa-utils
     cnews
diff --git a/lib/lp/registry/browser/tests/people-views.txt b/lib/lp/registry/browser/tests/people-views.txt
index 5add73a..7970cf0 100644
--- a/lib/lp/registry/browser/tests/people-views.txt
+++ b/lib/lp/registry/browser/tests/people-views.txt
@@ -59,7 +59,7 @@ one person and one team matching the 'test' string.
     >>> def print_batch(batch):
     ...     for thing in batch.currentBatch():
     ...         naked_thing = removeSecurityProxy(thing)
-    ...         print naked_thing
+    ...         print(naked_thing)
 
     >>> form = dict(name='test')
     >>> view = create_initialized_view(person_set, '+index', form=form)
diff --git a/lib/lp/registry/browser/tests/peoplemerge-views.txt b/lib/lp/registry/browser/tests/peoplemerge-views.txt
index 5d8dcb2..f059ad4 100644
--- a/lib/lp/registry/browser/tests/peoplemerge-views.txt
+++ b/lib/lp/registry/browser/tests/peoplemerge-views.txt
@@ -22,9 +22,9 @@ team.
 
 A team (name21) can be merged into another (ubuntu-team).
 
-    >>> print person_set.getByName('name21').displayname
+    >>> print(person_set.getByName('name21').displayname)
     Hoary Gnome Team
-    >>> print person_set.getByName('ubuntu-team').displayname
+    >>> print(person_set.getByName('ubuntu-team').displayname)
     Ubuntu Team
 
     >>> form = {'field.dupe_person': 'name21',
@@ -35,7 +35,7 @@ A team (name21) can be merged into another (ubuntu-team).
     >>> len(view.errors)
     0
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     A merge is queued and is expected to complete in a few minutes.
 
 
@@ -50,7 +50,7 @@ Attempting to merge a non-existent team results in an error.
     >>> len(view.errors)
     2
     >>> for error in view.errors:
-    ...     print error[0]
+    ...     print(error[0])
     Invalid value
     Invalid value
 
@@ -76,7 +76,7 @@ them to merge a profile which has no email address.
     ...     person_set, '+requestmerge', form=form)
     >>> len(view.errors)
     2
-    >>> print view.getFieldError('dupe_person')
+    >>> print(view.getFieldError('dupe_person'))
     The duplicate is not a valid person or team.
 
 Admins and registry experts, on the other hand, are allowed to merge people
@@ -90,7 +90,7 @@ without a single email address.
     ...     person_set, '+adminpeoplemerge', form=form)
     >>> view.errors
     []
-    >>> print view.request.response.getHeader('location')
+    >>> print(view.request.response.getHeader('location'))
     http://launchpad.test/~name16
 
 
@@ -123,13 +123,13 @@ can delete teams.
 
 The view provides a label, page_title, and cancel url to present the page.
 
-    >>> print view.label
+    >>> print(view.label)
     Delete Deletable
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Delete
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/~deletable
 
 The view uses the similar form fields as the team merge view, but it does not
@@ -147,13 +147,13 @@ and it is only rendered if canDelete() returns True.
     {'field.delete': True, 'field.dupe_person': u'deletable'}
 
     >>> content = find_tag_by_id(view.render(), 'maincontent')
-    >>> print find_tag_by_id(content, 'field.dupe_person')
+    >>> print(find_tag_by_id(content, 'field.dupe_person'))
     None
 
-    >>> print find_tag_by_id(content, 'field.delete')
+    >>> print(find_tag_by_id(content, 'field.delete'))
     None
 
-    >>> print find_tag_by_id(content, 'field.actions.delete')['value']
+    >>> print(find_tag_by_id(content, 'field.actions.delete')['value'])
     Delete
 
     >>> view.canDelete(data={})
@@ -164,7 +164,7 @@ deleted.
 
     >>> from lp.testing.pages import extract_text
 
-    >>> print extract_text(content)
+    >>> print(extract_text(content))
     Delete Deletable
     Deleting a team is permanent. It cannot be undone.
     Deletable has 2 active members who will be removed before it is deleted...
@@ -177,10 +177,10 @@ The user is redirected to /people when a team is deleted.
     []
 
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     The team is queued to be deleted.
 
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/people
 
 And there is a person merge job setup to delete them.
@@ -202,7 +202,7 @@ the team that the merge operation is performed with.
     ...     'field.actions.delete': 'Delete'}
     >>> view = create_initialized_view(deletable_team, '+delete', form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     Unable to process submitted data.
 
     >>> view.request.response.notifications
@@ -222,13 +222,13 @@ A team with a mailing list cannot be deleted.
     True
 
     >>> content = find_tag_by_id(view.render(), 'maincontent')
-    >>> print extract_text(content)
+    >>> print(extract_text(content))
     Delete Not Deletable
     Deleting a team is permanent. It cannot be undone.
     This team cannot be deleted until its mailing list is first deactivated,
     then purged after the deactivation is confirmed...
 
-    >>> print find_tag_by_id(content, 'field.actions.delete')
+    >>> print(find_tag_by_id(content, 'field.actions.delete'))
     None
 
 Private teams can be deleted by admins.
@@ -244,5 +244,5 @@ Private teams can be deleted by admins.
     >>> view.errors
     []
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     The team is queued to be deleted.
diff --git a/lib/lp/registry/browser/tests/person-admin-views.txt b/lib/lp/registry/browser/tests/person-admin-views.txt
index d5d8dd6..2564e38 100644
--- a/lib/lp/registry/browser/tests/person-admin-views.txt
+++ b/lib/lp/registry/browser/tests/person-admin-views.txt
@@ -14,7 +14,7 @@ The PersonAdministerView is registered under the +review name.
     >>> view = create_initialized_view(user, '+review')
     >>> check_permission('launchpad.Admin', view)
     True
-    >>> print view.errors
+    >>> print(view.errors)
     []
     >>> view.field_names
     ['name', 'display_name',
@@ -41,15 +41,15 @@ of a user's attributes.
     ...     'field.actions.change': 'Change',
     ...     }
     >>> view = create_initialized_view(user, '+review', form=form)
-    >>> print view.errors
+    >>> print(view.errors)
     []
-    >>> print user.name
+    >>> print(user.name)
     zaphod
-    >>> print user.display_name
+    >>> print(user.display_name)
     Zaphod Beeblebrox
     >>> user.personal_standing
     <DBItem PersonalStanding.POOR, ...>
-    >>> print user.personal_standing_reason
+    >>> print(user.personal_standing_reason)
     Zaphod's just this guy.
     >>> user.require_strong_email_authentication
     False
@@ -79,7 +79,7 @@ An admin can see a user's account information.
     ...     user, '+reviewaccount', principal=admin)
     >>> check_permission('launchpad.Admin', view)
     True
-    >>> print view.errors
+    >>> print(view.errors)
     []
     >>> view.field_names
     ['status', 'comment']
@@ -106,7 +106,7 @@ The admin can change the user's account information.
     ...     'field.actions.change': 'Change',
     ...     }
     >>> view = create_initialized_view(user, '+reviewaccount', form=form)
-    >>> print view.errors
+    >>> print(view.errors)
     []
 
 An admin can suspend a user's account using the +reviewaccount view. When
@@ -114,7 +114,7 @@ an account is suspended, the preferred email address is disabled.
 
     >>> user.account_status
     <DBItem AccountStatus.ACTIVE, ...>
-    >>> print user.account_status_history
+    >>> print(user.account_status_history)
     None
 
     >>> form = {
@@ -123,7 +123,7 @@ an account is suspended, the preferred email address is disabled.
     ...     'field.actions.change': 'Change',
     ...     }
     >>> view = create_initialized_view(user, '+reviewaccount', form=form)
-    >>> print view.errors
+    >>> print(view.errors)
     []
     >>> transaction.commit()
     >>> user.account_status
@@ -131,7 +131,7 @@ an account is suspended, the preferred email address is disabled.
     >>> user.account_status_history
     u'... name16: Active -> Suspended:
     Wanted by the galactic police.\n'
-    >>> print user.preferredemail
+    >>> print(user.preferredemail)
     None
 
 No one can force account status to an invalid transition:
@@ -156,12 +156,12 @@ user must log in to restore the email addresses using the reactivate step.
     ...     'field.actions.change': 'Change',
     ...     }
     >>> view = create_initialized_view(user, '+reviewaccount', form=form)
-    >>> print view.errors
+    >>> print(view.errors)
     []
     >>> user.account_status
     <DBItem AccountStatus.DEACTIVATED, ...>
     >>> user.account_status_history
     u"... name16: Active -> Suspended: Wanted by the galactic police.\n...
     name16: Suspended -> Deactivated: Zaphod's a hoopy frood.\n"
-    >>> print user.preferredemail
+    >>> print(user.preferredemail)
     None
diff --git a/lib/lp/registry/browser/tests/person-edit-views.txt b/lib/lp/registry/browser/tests/person-edit-views.txt
index 60318f4..815a87a 100644
--- a/lib/lp/registry/browser/tests/person-edit-views.txt
+++ b/lib/lp/registry/browser/tests/person-edit-views.txt
@@ -13,13 +13,13 @@ The +editircnickname provides a label and a title.
     >>> ignored = login_person(person)
     >>> view = create_initialized_view(
     ...     person, name='+editircnicknames', form={}, principal=person)
-    >>> print view.label
+    >>> print(view.label)
     Basil's IRC nicknames
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Basil's IRC nicknames
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/~basil
 
 The IRC form requires a nickname.
@@ -37,7 +37,7 @@ The IRC form requires a nickname.
     []
 
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Neither Nickname nor Network can be empty...
 
     >>> [irc for irc in person.ircnicknames]
@@ -58,7 +58,7 @@ The IRC form requires a network.
     []
 
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Neither Nickname nor Network can be empty.
 
     >>> [irc for irc in person.ircnicknames]
@@ -78,7 +78,7 @@ The IRC nickname is added when both the nickname and network are submitted.
     >>> view.errors
     []
 
-    >>> print view.request.response.notifications
+    >>> print(view.request.response.notifications)
     []
 
     # We need to clear ircnicknames from the property cache so the new data
@@ -86,7 +86,7 @@ The IRC nickname is added when both the nickname and network are submitted.
     >>> from lp.services.propertycache import get_property_cache
     >>> del get_property_cache(person).ircnicknames
     >>> [ircnickname] = [irc for irc in person.ircnicknames]
-    >>> print ircnickname.nickname
+    >>> print(ircnickname.nickname)
     basil
 
 An IRC nickname can be removed.
@@ -105,7 +105,7 @@ An IRC nickname can be removed.
     >>> view.errors
     []
 
-    >>> print view.request.response.notifications
+    >>> print(view.request.response.notifications)
     []
 
     # Clear the cache first.
diff --git a/lib/lp/registry/browser/tests/person-karma-views.txt b/lib/lp/registry/browser/tests/person-karma-views.txt
index 4afd9fa..c684e17 100644
--- a/lib/lp/registry/browser/tests/person-karma-views.txt
+++ b/lib/lp/registry/browser/tests/person-karma-views.txt
@@ -10,12 +10,12 @@ The ~person/+karma page is controlled by the PersonKarmaView.
 
 The view's label shows the person who's karma we're looking at...
 
-    >>> print view.label
+    >>> print(view.label)
     Your Launchpad Karma
 
 ...even when the logged in user is looking at someone else's karma.
 
     >>> neil = factory.makePerson(name='neil', displayname='Neil Peart')
     >>> view = create_initialized_view(neil, '+karma')
-    >>> print view.label
+    >>> print(view.label)
     Launchpad Karma
diff --git a/lib/lp/registry/browser/tests/person-views.txt b/lib/lp/registry/browser/tests/person-views.txt
index 6b4c3db..b1c4dca 100644
--- a/lib/lp/registry/browser/tests/person-views.txt
+++ b/lib/lp/registry/browser/tests/person-views.txt
@@ -40,7 +40,7 @@ are there any email addresses.
     >>> view.email_address_visibility.is_login_required
     True
 
-    >>> print view.visible_email_address_description
+    >>> print(view.visible_email_address_description)
     None
 
     >>> view.visible_email_addresses
@@ -86,7 +86,7 @@ them.
     >>> view.email_address_visibility.are_hidden
     True
 
-    >>> print view.visible_email_address_description
+    >>> print(view.visible_email_address_description)
     None
 
     >>> view.visible_email_addresses
@@ -159,7 +159,7 @@ email addresses state is NONE_AVAILABLE.
     >>> view.email_address_visibility.are_none_available
     True
 
-    >>> print view.visible_email_address_description
+    >>> print(view.visible_email_address_description)
     None
 
     >>> view.visible_email_addresses
@@ -180,7 +180,7 @@ their preferred languages, English is used.
 
     >>> login(ANONYMOUS)
     >>> view = create_view(sample_person, '+portlet-contact-details')
-    >>> print view.languages
+    >>> print(view.languages)
     English
 
 This assumption is visible to the user when they view their own profile
@@ -194,7 +194,7 @@ correction. The list of languages is alphabetized.
     >>> sample_person.addLanguage(languageset.getLanguageByCode('fr'))
 
     >>> view = create_view(sample_person, '+portlet-contact-details')
-    >>> print view.languages
+    >>> print(view.languages)
     French, Somali
 
 Teams may have languages too. English is the default if the team has not
@@ -204,7 +204,7 @@ set a language.
     []
 
     >>> view = create_view(landscape_developers, '+portlet-contact-details')
-    >>> print view.languages
+    >>> print(view.languages)
     English
 
 Teams most often set just one language that is used for the Answers
@@ -214,7 +214,7 @@ parenthesis.
     >>> landscape_developers.addLanguage(
     ...     languageset.getLanguageByCode('pt_BR'))
     >>> view = create_view(landscape_developers, '+portlet-contact-details')
-    >>> print view.languages
+    >>> print(view.languages)
     Portuguese (Brazil)
 
 
@@ -284,7 +284,7 @@ working on.
     >>> len(view.assigned_specs_in_progress)
     1
 
-    >>> print view.render()
+    >>> print(view.render())
     <div id="working-on"...
     <a href="/~ken/+specs?role=assignee"> All assigned blueprints </a>...
     ...<a ...href="http://blueprints.launchpad.test/tool/+spec/...";...>Specs
@@ -323,7 +323,7 @@ status is in INPROGRESS.
     >>> len(view.assigned_specs_in_progress)
     1
 
-    >>> print view.render()
+    >>> print(view.render())
     <div id="working-on"...
     <a href="http://launchpad.test/~ken/+assignedbugs?...";>
       All bugs in progress </a>...
@@ -439,7 +439,7 @@ If the PPA is private, only the owner will see the section.
 For a user with no PPAs, nobody will see the section apart from themselves.
 This aspect allows them to access the 'Create a new PPA' link.
 
-    >>> print sample_person.archive
+    >>> print(sample_person.archive)
     None
 
     >>> ignored = login_person(sample_person)
diff --git a/lib/lp/registry/browser/tests/pillar-views.txt b/lib/lp/registry/browser/tests/pillar-views.txt
index 603a3a0..93b80d9 100644
--- a/lib/lp/registry/browser/tests/pillar-views.txt
+++ b/lib/lp/registry/browser/tests/pillar-views.txt
@@ -19,7 +19,7 @@ be rendered. The newly created pillar does not use any launchpad applications.
     >>> view.has_involvement
     False
 
-    >>> print view.render()
+    >>> print(view.render())
     <BLANKLINE>
 
 Pillars that do use launchpad applications have an involvement menu.
@@ -34,22 +34,22 @@ Pillars that do use launchpad applications have an involvement menu.
 
     >>> view.official_malone
     True
-    >>> print view.answers_usage.name
+    >>> print(view.answers_usage.name)
     LAUNCHPAD
-    >>> print view.translations_usage.name
+    >>> print(view.translations_usage.name)
     UNKNOWN
-    >>> print view.blueprints_usage.name
+    >>> print(view.blueprints_usage.name)
     UNKNOWN
-    >>> print view.codehosting_usage.name
+    >>> print(view.codehosting_usage.name)
     UNKNOWN
 
 The view provides a list of enabled links that is rendered by the template.
 
     >>> for link in view.enabled_links:
-    ...     print link.name
+    ...     print(link.name)
     report_bug ask_question
 
-    >>> print view.render()
+    >>> print(view.render())
     <div id="involvement" class="portlet">
       <h2>Get Involved</h2>
       <ul class="involvement">
@@ -68,10 +68,10 @@ Products are supported.
     >>> ignored = login_person(product.owner)
     >>> product.blueprints_usage = ServiceUsage.LAUNCHPAD
     >>> view = create_view(product, '+get-involved')
-    >>> print view.blueprints_usage.name
+    >>> print(view.blueprints_usage.name)
     LAUNCHPAD
     >>> for link in view.enabled_links:
-    ...     print link.name
+    ...     print(link.name)
     register_blueprint
 
 Products subclass the view to display disabled links to encourage
@@ -80,13 +80,13 @@ also has configuration links that make it easy to figure out where
 to configure each service.
 
     >>> for link in view.visible_disabled_links:
-    ...     print link.name
+    ...     print(link.name)
     report_bug
     ask_question
     help_translate
 
     >>> for link in view.configuration_links:
-    ...     print link['link'].name
+    ...     print(link['link'].name)
     configure_code
     configure_bugtracker
     configure_translations
@@ -98,7 +98,7 @@ configuration links nor the completeness computation as the use of
 blueprints is not promoted.
 
     >>> for key in sorted(view.configuration_states.keys()):
-    ...     print key, view.configuration_states[key]
+    ...     print(key, view.configuration_states[key])
     configure_answers False
     configure_bugtracker False
     configure_code False
@@ -108,7 +108,7 @@ The percentage of the registration completed can be determined by
 using the 'registration_completeness' property, which returns a
 dictionary, which makes it easy for use in the page template.
 
-    >>> print pretty(view.registration_completeness)
+    >>> print(pretty(view.registration_completeness))
     {'done': 0,
      'undone': 100}
 
@@ -117,13 +117,13 @@ Changing the product's usage is reflected in the view properties.
     >>> product.translations_usage = ServiceUsage.LAUNCHPAD
     >>> view = create_view(product, '+get-involved')
     >>> for key in sorted(view.configuration_states.keys()):
-    ...     print key, view.configuration_states[key]
+    ...     print(key, view.configuration_states[key])
     configure_answers False
     configure_bugtracker False
     configure_code False
     configure_translations True
 
-    >>> print pretty(view.registration_completeness)
+    >>> print(pretty(view.registration_completeness))
     {'done': 25,
      'undone': 75}
 
@@ -131,7 +131,7 @@ The progress bar is shown as a green bar.
 
     >>> from lp.testing.pages import find_tag_by_id
     >>> rendered = view.render()
-    >>> print find_tag_by_id(rendered, 'progressbar')
+    >>> print(find_tag_by_id(rendered, 'progressbar'))
     <div id="progressbar" ...>
     <img ...src="/@@/green-bar" ... width: 25%.../>
     ...
@@ -139,7 +139,7 @@ The progress bar is shown as a green bar.
 Each application is displayed (except for blueprints) with an
 indicator showing whether it has been configured or not.
 
-    >>> print find_tag_by_id(rendered, 'configuration_links')
+    >>> print(find_tag_by_id(rendered, 'configuration_links'))
     <table...
     <a ...href="http://launchpad.test/bread/+configure-code";...
     <span class="sprite no action-icon">...
@@ -158,18 +158,18 @@ applications used by their products.
     >>> product.projectgroup = project_group
 
     >>> view = create_view(project_group, '+get-involved')
-    >>> print view.blueprints_usage.name
+    >>> print(view.blueprints_usage.name)
     LAUNCHPAD
 
 The offical_codehosting for a project is based on whether the project's
 development focus series has a branch.
 
-    >>> print product.development_focus.branch
+    >>> print(product.development_focus.branch)
     None
     >>> product.official_codehosting
     False
     >>> view = create_view(product, '+get-involved')
-    >>> print view.codehosting_usage.name
+    >>> print(view.codehosting_usage.name)
     UNKNOWN
 
     >>> product.development_focus.branch = factory.makeBranch(
@@ -177,7 +177,7 @@ development focus series has a branch.
     >>> product.official_codehosting
     True
     >>> view = create_view(product, '+get-involved')
-    >>> print view.codehosting_usage.name
+    >>> print(view.codehosting_usage.name)
     LAUNCHPAD
 
     >>> from lp.code.enums import BranchType
@@ -187,7 +187,7 @@ development focus series has a branch.
     >>> remote.official_codehosting
     False
     >>> view = create_view(remote, '+get-involved')
-    >>> print view.codehosting_usage.name
+    >>> print(view.codehosting_usage.name)
     UNKNOWN
 
 
@@ -195,7 +195,7 @@ Project groups cannot make links to register a branch, so
 official_codehosting is always false.
 
     >>> view = create_view(project_group, '+get-involved')
-    >>> print view.codehosting_usage.name
+    >>> print(view.codehosting_usage.name)
     NOT_APPLICABLE
 
 Project groups ignore products translations_usage setting if none of the
@@ -206,7 +206,7 @@ products are fully configured as translatable.
     False
 
     >>> view = create_view(project_group, '+get-involved')
-    >>> print view.translations_usage.name
+    >>> print(view.translations_usage.name)
     UNKNOWN
 
 If a product is translatable, translations is enabled in the involvment menu.
@@ -222,7 +222,7 @@ If a product is translatable, translations is enabled in the involvment menu.
     True
 
     >>> view = create_view(project_group, '+get-involved')
-    >>> print view.translations_usage.name
+    >>> print(view.translations_usage.name)
     LAUNCHPAD
 
 DistroSeries can use this view. The distribution is used to set the links.
@@ -230,7 +230,7 @@ DistroSeries can use this view. The distribution is used to set the links.
     >>> series = factory.makeDistroSeries(distribution=distribution)
     >>> view = create_view(series, '+get-involved')
     >>> for link in view.enabled_links:
-    ...     print link.name
+    ...     print(link.name)
     report_bug
 
 DistributionSourcePackages can use this view. The distribution is used to
@@ -246,7 +246,7 @@ and translations those links are not enabled for DistributionSourcePackages.
     ...     distribution=distribution)
     >>> view = create_view(package, '+get-involved')
     >>> for link in view.enabled_links:
-    ...     print link.name
+    ...     print(link.name)
     report_bug ask_question
 
 
@@ -264,7 +264,7 @@ The menu when viewed from a product page.
     >>> menuapi = MenuAPI(view)
     >>> for link in sorted(
     ...     menuapi.navigation.values(), key=attrgetter('sort_key')):
-    ...     print link.url
+    ...     print(link.url)
     http://bugs.launchpad.test/bread/+filebug
     http://answers.launchpad.test/bread/+addquestion
     http://translations.launchpad.test/bread
@@ -282,7 +282,7 @@ The menu when viewed from a distribution page.
     >>> for link in sorted(
     ...     menuapi.navigation.values(), key=attrgetter('sort_key')):
     ...     if link.enabled:
-    ...         print link.url
+    ...         print(link.url)
     http://bugs.launchpad.test/umbra/+filebug
     http://answers.launchpad.test/umbra/+addquestion
     http://translations.launchpad.test/umbra
@@ -295,6 +295,6 @@ The menu when viewed from a distribution source package page.
     >>> for link in sorted(
     ...     menuapi.navigation.values(), key=attrgetter('sort_key')):
     ...     if link.enabled:
-    ...         print link.url
+    ...         print(link.url)
     http://bugs.launchpad.test/umbra/+source/box/+filebug
     http://answers.launchpad.test/umbra/+source/box/+addquestion
diff --git a/lib/lp/registry/browser/tests/poll-views.txt b/lib/lp/registry/browser/tests/poll-views.txt
index b9e1e65..3303151 100644
--- a/lib/lp/registry/browser/tests/poll-views.txt
+++ b/lib/lp/registry/browser/tests/poll-views.txt
@@ -31,7 +31,7 @@ The portlet does not render any markup when there are no polls...
     >>> view.should_show_polls_portlet
     False
 
-    >>> print extract_text(view.render())
+    >>> print(extract_text(view.render()))
     <BLANKLINE>
 
 Unless the user is a team owner.
@@ -44,7 +44,7 @@ Unless the user is a team owner.
     >>> view.should_show_polls_portlet
     True
 
-    >>> print extract_text(view.render())
+    >>> print(extract_text(view.render()))
     Polls
     No current polls.
     Show polls
@@ -71,7 +71,7 @@ has not opened.
     >>> view.should_show_polls_portlet
     True
 
-    >>> print extract_text(view.render())
+    >>> print(extract_text(view.render()))
     Polls
     Show polls
 
@@ -85,7 +85,7 @@ The portlet shows more details to the poll owner.
     >>> view.should_show_polls_portlet
     True
 
-    >>> print extract_text(view.render())
+    >>> print(extract_text(view.render()))
     Polls
     title - opens in 5 hours
     Show polls
@@ -98,7 +98,7 @@ and an owner is the owner has a link to create more polls.
 
     >>> ignored = login_person(user)
     >>> view = create_team_view(team, name='+portlet-polls', principal=user)
-    >>> print extract_text(view.render())
+    >>> print(extract_text(view.render()))
     Polls
     title - closes on ...
     You have 7 days left to vote in this poll.
@@ -106,7 +106,7 @@ and an owner is the owner has a link to create more polls.
 
     >>> ignored = login_person(owner)
     >>> view = create_team_view(team, name='+portlet-polls', principal=owner)
-    >>> print extract_text(view.render())
+    >>> print(extract_text(view.render()))
     Polls
     title - closes on ...
     You have 7 days left to vote in this poll.
@@ -120,14 +120,14 @@ see the polls.
 
     >>> ignored = login_person(user)
     >>> view = create_team_view(team, name='+portlet-polls', principal=user)
-    >>> print extract_text(view.render())
+    >>> print(extract_text(view.render()))
     Polls
     No current polls.
     Show polls
 
     >>> ignored = login_person(owner)
     >>> view = create_team_view(team, name='+portlet-polls', principal=owner)
-    >>> print extract_text(view.render())
+    >>> print(extract_text(view.render()))
     Polls
     No current polls.
     Show polls
diff --git a/lib/lp/registry/browser/tests/poll-views_0.txt b/lib/lp/registry/browser/tests/poll-views_0.txt
index a89220f..47ab535 100644
--- a/lib/lp/registry/browser/tests/poll-views_0.txt
+++ b/lib/lp/registry/browser/tests/poll-views_0.txt
@@ -35,7 +35,7 @@ with a proper explanation of why it failed.
   >>> request = LaunchpadTestRequest(method='POST', form=form)
   >>> new_poll = getMultiAdapter((ubuntu_team, request), name="+newpoll")
   >>> new_poll.initialize()
-  >>> print "\n".join(new_poll.errors)
+  >>> print("\n".join(new_poll.errors))
   A poll cannot open less than 12 hours after it&#x27;s created.
 
 Now we successfully create a poll which starts 12h from now.
@@ -65,7 +65,7 @@ matrix as a python list, with the necessary headers (the option's names).
 
   >>> poll_results = getMultiAdapter((poll, TestRequest()), name="+index")
   >>> for row in poll_results.getPairwiseMatrixWithHeaders():
-  ...     print row
+  ...     print(row)
   [None, u'A', u'B', u'C', u'D']
   [u'A', None, 2L, 2L, 2L]
   [u'B', 2L, None, 2L, 2L]
diff --git a/lib/lp/registry/browser/tests/private-team-creation-views.txt b/lib/lp/registry/browser/tests/private-team-creation-views.txt
index b1e3587..5e5fd24 100644
--- a/lib/lp/registry/browser/tests/private-team-creation-views.txt
+++ b/lib/lp/registry/browser/tests/private-team-creation-views.txt
@@ -63,11 +63,11 @@ When creating a private team, the team membership policy must be
     ...     personset, '+newteam',
     ...     form=form, principal=foo_bar)
 
-    >>> print len(view.request.notifications)
+    >>> print(len(view.request.notifications))
     0
 
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     Private teams must have a Restricted membership policy.
 
 When the inputs are correct the admin can successfully create the team.
@@ -86,9 +86,9 @@ When the inputs are correct the admin can successfully create the team.
     ...     personset, '+newteam',
     ...     form=form, principal=foo_bar)
 
-    >>> print len(view.request.notifications)
+    >>> print(len(view.request.notifications))
     0
-    >>> print len(view.errors)
+    >>> print(len(view.errors))
     0
 
 Commercial admins can create a team too.
@@ -108,16 +108,16 @@ Commercial admins can create a team too.
     ...     personset, '+newteam',
     ...     form=form, principal=commercial_member)
 
-    >>> print len(view.request.notifications)
+    >>> print(len(view.request.notifications))
     0
 
-    >>> print len(view.errors)
+    >>> print(len(view.errors))
     0
 
     >>> import transaction
     >>> transaction.commit()
     >>> secret_team = personset.getByName('secret-team')
-    >>> print secret_team.visibility.name
+    >>> print(secret_team.visibility.name)
     PRIVATE
 
 Admins who attempt to create a new team with the name of an existing
@@ -138,11 +138,11 @@ team get the normal error message.
     ...     personset, '+newteam',
     ...     form=form, principal=foo_bar)
 
-    >>> print len(view.request.notifications)
+    >>> print(len(view.request.notifications))
     0
 
     >>> for error in view.errors:
-    ...     print view.getFieldError(error.field_name)
+    ...     print(view.getFieldError(error.field_name))
     secret-team is already in use by another person or team.
 
 Regular users who try to create a team with a name that is already
@@ -162,11 +162,11 @@ taken by a private team get the blacklist message.
     ...     personset, '+newteam',
     ...     form=form, principal=nopriv)
 
-    >>> print len(view.request.notifications)
+    >>> print(len(view.request.notifications))
     0
 
     >>> for error in view.errors:
-    ...     print view.getFieldError(error.field_name)
+    ...     print(view.getFieldError(error.field_name))
     The name &#x27;secret-team&#x27; has been blocked by the Launchpad
     administrators.  Contact Launchpad Support if you want to use this
     name.
@@ -212,11 +212,11 @@ And a private team must have restricted membership.
     ...     secret_team, '+edit',
     ...     form=form, principal=foo_bar)
 
-    >>> print len(view.request.notifications)
+    >>> print(len(view.request.notifications))
     0
 
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     Private teams must have a Restricted membership policy.
 
 Visibility transitions
@@ -293,9 +293,9 @@ those permitted by private teams.
     >>> view = create_initialized_view(
     ...     team, '+edit',
     ...     form=form, principal=foo_bar)
-    >>> print len(view.request.notifications)
+    >>> print(len(view.request.notifications))
     0
-    >>> print len(view.errors)
+    >>> print(len(view.errors))
     0
 
 If the team has any other artifacts then it will not be allowed to
@@ -318,10 +318,10 @@ change to Private.
     >>> view = create_initialized_view(
     ...     team, '+edit',
     ...     form=form, principal=foo_bar)
-    >>> print len(view.request.notifications)
+    >>> print(len(view.request.notifications))
     0
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     This team cannot be converted to Private since it is referenced by a
     bugtracker.
 
@@ -330,10 +330,10 @@ display_name for the team is the old value.
 
     >>> transaction.commit()
     >>> super_secret2 = personset.getByName('super-secret2')
-    >>> print super_secret2.name
+    >>> print(super_secret2.name)
     super-secret2
 
-    >>> print super_secret2.display_name
+    >>> print(super_secret2.display_name)
     Shhhh
 
 
@@ -358,9 +358,9 @@ Commercial admins can create private projects with the 'private-' prefix.
     ...     personset, '+newteam',
     ...     form=form, principal=foo_bar)
 
-    >>> print len(view.request.notifications)
+    >>> print(len(view.request.notifications))
     0
-    >>> print len(view.errors)
+    >>> print(len(view.errors))
     0
 
 When trying to register a project with a 'private-' prefix, regular
@@ -381,11 +381,11 @@ users will get a blacklist message.
     ...     personset, '+newteam',
     ...     form=form, principal=nopriv)
 
-    >>> print len(view.request.notifications)
+    >>> print(len(view.request.notifications))
     0
 
     >>> for error in view.errors:
-    ...     print view.getFieldError(error.field_name)
+    ...     print(view.getFieldError(error.field_name))
     The name &#x27;private-top-secret&#x27; has been blocked by the
     Launchpad administrators. Contact Launchpad Support if you want to
     use this name.
diff --git a/lib/lp/registry/browser/tests/product-edit-people-view.txt b/lib/lp/registry/browser/tests/product-edit-people-view.txt
index 470238d..21576d3 100644
--- a/lib/lp/registry/browser/tests/product-edit-people-view.txt
+++ b/lib/lp/registry/browser/tests/product-edit-people-view.txt
@@ -13,7 +13,7 @@ Person (name12).
     >>> productset = getUtility(IProductSet)
     >>> firefox = productset.getByName('firefox')
     >>> sample_person = firefox.owner
-    >>> print sample_person.name
+    >>> print(sample_person.name)
     name12
 
 No Privileges Person is taking over the project, but they cannot access the
diff --git a/lib/lp/registry/browser/tests/product-files-views.txt b/lib/lp/registry/browser/tests/product-files-views.txt
index f85b19c..c999548 100644
--- a/lib/lp/registry/browser/tests/product-files-views.txt
+++ b/lib/lp/registry/browser/tests/product-files-views.txt
@@ -16,12 +16,12 @@ Test for the product/+download page.
     4
 
     >>> batch = view.series_and_releases_batch.currentBatch()
-    >>> print len(list(batch))
+    >>> print(len(list(batch)))
     1
 
     >>> def print_series_release(sr):
-    ...     print "%s from the %s series" % (sr.release.name_with_codename,
-    ...                                      sr.series.name)
+    ...     print("%s from the %s series" % (sr.release.name_with_codename,
+    ...                                      sr.series.name))
 
     >>> for sr in batch:
     ...     print_series_release(sr)
@@ -39,7 +39,7 @@ Test for the product/+download page.
     ...             milestone=milestone)
     >>> view = create_initialized_view(product, '+download')
     >>> batch = view.series_and_releases_batch.currentBatch()
-    >>> print len(batch)
+    >>> print(len(batch))
     4
     >>> for sr in batch:
     ...     print_series_release(sr)
@@ -66,7 +66,7 @@ page will be links to add new files for each series and release.
     ...                                principal=product.owner)
     >>> admin_links = find_tag_by_id(view.render(), 'admin-links')
     >>> content = extract_text(admin_links)
-    >>> print content
+    >>> print(content)
     Add download file to the s4 series for release: 4.3, 4.2, 4.1
     Add download file to the s3 series for release: 3.3, 3.2, 3.1
     Add download file to the s2 series for release: 2.3, 2.2, 2.1
@@ -79,7 +79,7 @@ Product index
 The product index view shows the latest release for the project.
 
     >>> view = create_initialized_view(product, name='+index')
-    >>> print view.latest_release_with_download_files.version
+    >>> print(view.latest_release_with_download_files.version)
     4.3
 
 Obsolete series are ignored.
@@ -89,5 +89,5 @@ Obsolete series are ignored.
     >>> obsolete_series = product.getSeries('s4')
     >>> obsolete_series.status = SeriesStatus.OBSOLETE
     >>> view = create_initialized_view(product, name='+index')
-    >>> print view.latest_release_with_download_files.version
+    >>> print(view.latest_release_with_download_files.version)
     3.3
diff --git a/lib/lp/registry/browser/tests/product-views.txt b/lib/lp/registry/browser/tests/product-views.txt
index 680c9f2..486824c 100644
--- a/lib/lp/registry/browser/tests/product-views.txt
+++ b/lib/lp/registry/browser/tests/product-views.txt
@@ -32,14 +32,14 @@ project has no driver then None is returned.
 
 Neither Mozilla nor Firefox has a driver set.
 
-    >>> print mozilla.driver
+    >>> print(mozilla.driver)
     None
-    >>> print firefox.driver
+    >>> print(firefox.driver)
     None
 
 Thus the effective driver for Firefox is None.
     >>> view = create_initialized_view(firefox, name='+index')
-    >>> print view.effective_driver
+    >>> print(view.effective_driver)
     None
 
 Setting the driver for the Mozilla project trickles down to Firefox.
@@ -49,23 +49,23 @@ Setting the driver for the Mozilla project trickles down to Firefox.
 But since the effective_driver is a cached property it will not show
 up on this view instance.
 
-    >>> print view.effective_driver
+    >>> print(view.effective_driver)
     None
 
 Creating a new view shows the new driver.
 
     >>> view = create_initialized_view(firefox, name='+index')
-    >>> print view.effective_driver.name
+    >>> print(view.effective_driver.name)
     mark
 
 Setting the driver for Firefox shows that it is used for the product,
 after a new view is obtained.
 
     >>> firefox.driver = cprov
-    >>> print view.effective_driver.name
+    >>> print(view.effective_driver.name)
     mark
     >>> view = create_initialized_view(firefox, name='+index')
-    >>> print view.effective_driver.name
+    >>> print(view.effective_driver.name)
     cprov
 
 
@@ -81,35 +81,35 @@ For product maintainers the property is true.  Sample Person
 
     >>> login('test@xxxxxxxxxxxxx')
     >>> view = create_initialized_view(firefox, name='+index')
-    >>> print view.show_commercial_subscription_info
+    >>> print(view.show_commercial_subscription_info)
     True
 
 For Launchpad admins the property is true.
 
     >>> login('foo.bar@xxxxxxxxxxxxx')
     >>> view = create_initialized_view(firefox, name='+index')
-    >>> print view.show_commercial_subscription_info
+    >>> print(view.show_commercial_subscription_info)
     True
 
 For Launchpad commercial members th property is true.
 
     >>> login('commercial-member@xxxxxxxxxxxxx')
     >>> view = create_initialized_view(firefox, name='+index')
-    >>> print view.show_commercial_subscription_info
+    >>> print(view.show_commercial_subscription_info)
     True
 
 But for a no-privileges user the property is false.
 
     >>> login('no-priv@xxxxxxxxxxxxx')
     >>> view = create_initialized_view(firefox, name='+index')
-    >>> print view.show_commercial_subscription_info
+    >>> print(view.show_commercial_subscription_info)
     False
 
 And for an anonymous user it is false.
 
     >>> login(ANONYMOUS)
     >>> view = create_initialized_view(firefox, name='+index')
-    >>> print view.show_commercial_subscription_info
+    >>> print(view.show_commercial_subscription_info)
     False
 
 
@@ -134,7 +134,7 @@ Mark is in the registry admins team and is allowed to access the page.
 
     >>> login('mark@xxxxxxxxxxx')
     >>> view = create_initialized_view(firefox, name='+review-license')
-    >>> print view.label
+    >>> print(view.label)
     Review project
 
 Adding the Commercial Admin to the registry experts team will give
@@ -147,7 +147,7 @@ them access.
     >>> transaction.commit()
     >>> login('commercial-member@xxxxxxxxxxxxx')
     >>> view = create_initialized_view(firefox, name='+review-license')
-    >>> print view.label
+    >>> print(view.label)
     Review project
 
 The view allow the reviewer to see and change project privileges and
@@ -190,7 +190,7 @@ The reviewer can deactivate a project if they conclude it is bogus.
     []
     >>> product.active
     False
-    >>> print product.reviewer_whiteboard
+    >>> print(product.reviewer_whiteboard)
     Looks bogus
 
 The reviewer can reactivate the project.
@@ -207,7 +207,7 @@ The reviewer can reactivate the project.
     []
     >>> firefox.active
     True
-    >>> print firefox.reviewer_whiteboard
+    >>> print(firefox.reviewer_whiteboard)
     Reinstated old project
 
 A project with proprietary licence cannot be approved; the owner must
@@ -236,7 +236,7 @@ purchase a commercial subscription.
        to be allowed to use Launchpad.']
     >>> firefox.license_approved
     False
-    >>> print firefox.reviewer_whiteboard
+    >>> print(firefox.reviewer_whiteboard)
     None
 
 A project with additional licence information must be approved by a reviewer.
@@ -348,13 +348,13 @@ Drivers, which include project driver and owners can access the
 The +addseries view provides a label and a page_title. There is a cancel_url
 too.
 
-    >>> print view.label
+    >>> print(view.label)
     Register a new Mozilla Firefox release series
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Register a new Mozilla Firefox release series
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/firefox
 
 The view allows the driver to set series name, summary, branch and
@@ -371,13 +371,13 @@ releasefileglob fields.
     ...     'field.actions.add': 'Register Series',
     ...     }
     >>> view = create_initialized_view(firefox, name='+addseries', form=form)
-    >>> print view.series.name
+    >>> print(view.series.name)
     master
 
-    >>> print view.series.summary
+    >>> print(view.series.summary)
     The primary development series.
 
-    >>> print view.series.releasefileglob
+    >>> print(view.series.releasefileglob)
     ftp://mozilla.org/firefox.*bz2
 
 
@@ -391,10 +391,10 @@ All the product series can be viewed in batches.
     ...     series = factory.makeProductSeries(product=product, name=name)
     >>> view = create_view(product, name='+series')
     >>> batch = view.batched_series.currentBatch()
-    >>> print batch.total()
+    >>> print(batch.total())
     6
     >>> for series in batch:
-    ...     print series.name
+    ...     print(series.name)
     trunk
     1.2
     1.1
@@ -424,13 +424,13 @@ officially supports.
     >>> view = create_initialized_view(
     ...     product, name='+index', principal=owner)
     >>> content = find_tag_by_id(view.render(), 'maincontent')
-    >>> print find_tag_by_id(content, 'portlet-latest-faqs')
+    >>> print(find_tag_by_id(content, 'portlet-latest-faqs'))
     None
-    >>> print find_tag_by_id(content, 'portlet-latest-questions')
+    >>> print(find_tag_by_id(content, 'portlet-latest-questions'))
     None
-    >>> print find_tag_by_id(content, 'portlet-latest-bugs')
+    >>> print(find_tag_by_id(content, 'portlet-latest-bugs'))
     None
-    >>> print find_tag_by_id(content, 'portlet-blueprints')
+    >>> print(find_tag_by_id(content, 'portlet-blueprints'))
     None
 
 The portlet are rendered when a product officially uses the Launchpad
@@ -444,11 +444,11 @@ Answers, Blueprints, and Bugs applications.
     >>> view = create_initialized_view(
     ...     product, name='+index', principal=owner)
     >>> content = find_tag_by_id(view.render(), 'maincontent')
-    >>> print find_tag_by_id(content, 'portlet-latest-faqs')['id']
+    >>> print(find_tag_by_id(content, 'portlet-latest-faqs')['id'])
     portlet-latest-faqs
-    >>> print find_tag_by_id(content, 'portlet-latest-questions')['id']
+    >>> print(find_tag_by_id(content, 'portlet-latest-questions')['id'])
     portlet-latest-questions
-    >>> print find_tag_by_id(content, 'portlet-latest-bugs')['id']
+    >>> print(find_tag_by_id(content, 'portlet-latest-bugs')['id'])
     portlet-latest-bugs
-    >>> print find_tag_by_id(content, 'portlet-blueprints')['id']
+    >>> print(find_tag_by_id(content, 'portlet-blueprints')['id'])
     portlet-blueprints
diff --git a/lib/lp/registry/browser/tests/productrelease-views.txt b/lib/lp/registry/browser/tests/productrelease-views.txt
index 60455fc..fb28f23 100644
--- a/lib/lp/registry/browser/tests/productrelease-views.txt
+++ b/lib/lp/registry/browser/tests/productrelease-views.txt
@@ -14,7 +14,7 @@ A new ProductRelease can be created using ProductReleaseAddView.
     >>> product = factory.makeProduct(name='app', owner=owner)
     >>> series = factory.makeProductSeries(name='simple', product=product)
     >>> naked_milestone = removeSecurityProxy(series).newMilestone('0.1')
-    >>> print naked_milestone.active
+    >>> print(naked_milestone.active)
     True
 
 The view explains what that the user is creating a release, and lists
@@ -22,15 +22,15 @@ the other releases for the series. There are no other releases yet.
 
     >>> ignored = login_person(owner)
     >>> view = create_initialized_view(naked_milestone, '+addrelease')
-    >>> print view.label
+    >>> print(view.label)
     Create a new release for App
-    >>> print view.page_title
+    >>> print(view.page_title)
     Create a new release for App
 
 The view creates a checkbox to allow the user to keep the milestone
 active, which is normally deactivated when a release is made.
 
-    >>> print view.widgets['keep_milestone_active'].hint
+    >>> print(view.widgets['keep_milestone_active'].hint)
     Only select this if bugs or blueprints still need to be targeted to this
     project release's milestone.
 
@@ -45,17 +45,17 @@ milestone.
     ...     'field.keep_milestone_active.used': '', # false
     ...     }
     >>> view = create_initialized_view(naked_milestone, '+addrelease', form=form)
-    >>> print view.errors
+    >>> print(view.errors)
     []
 
-    >>> print view.widget_errors
+    >>> print(view.widget_errors)
     {}
 
-    >>> print naked_milestone.active
+    >>> print(naked_milestone.active)
     False
 
     >>> for release in series.releases:
-    ...     print release.version, release.release_notes, release.datereleased
+    ...     print(release.version, release.release_notes, release.datereleased)
     0.1 Initial release. 2007-05-11 00:00:00+00:00
 
     >>> transaction.commit()
@@ -64,14 +64,14 @@ Only one release can be created for the milestone.
 
     >>> view = create_initialized_view(naked_milestone, '+addrelease', form=form)
     >>> for notice in view.request.response.notifications:
-    ...     print notice.message
+    ...     print(notice.message)
     A project release already exists for this milestone.
 
 The milestone can be kept active when a release is created by submitting
 the keep_milestone_active option as 'on' (the value of the checkbox).
 
     >>> active_milestone = series.newMilestone('0.2')
-    >>> print active_milestone.active
+    >>> print(active_milestone.active)
     True
 
     >>> form = {
@@ -83,16 +83,16 @@ the keep_milestone_active option as 'on' (the value of the checkbox).
     ...     }
     >>> view = create_initialized_view(
     ...     active_milestone, '+addrelease', form=form)
-    >>> print view.errors
+    >>> print(view.errors)
     []
 
-    >>> print view.widget_errors
+    >>> print(view.widget_errors)
     {}
 
     >>> view.request.response.notifications
     []
 
-    >>> print active_milestone.active
+    >>> print(active_milestone.active)
     True
 
 
@@ -112,9 +112,9 @@ set the milestone.
     >>> [field.__name__ for field in view.form_fields]
     ['milestone_for_release', 'keep_milestone_active', 'datereleased',
      'release_notes', 'changelog']
-    >>> print view.label
+    >>> print(view.label)
     Create a new release for App
-    >>> print view.page_title
+    >>> print(view.page_title)
     Create a new release for App
 
 The rendered template includes a script that adds a js-action link to
@@ -123,7 +123,7 @@ show a formoverlay that updates the milestone_for_release field.
     >>> from lp.testing.pages import find_tag_by_id
 
     >>> script = find_tag_by_id(view.render(), 'milestone-script')
-    >>> print script
+    >>> print(script)
     <script id="milestone-script" type="text/javascript">
         LPJS.use(... 'lp.registry.milestoneoverlay'...
             var milestone_form_uri = '.../app/simple/+addmilestone/++form++';
@@ -142,7 +142,7 @@ Editing a a product release
 A ProductRelease can be edited using the ProductReleaseEditView.
 
     >>> release = series.getRelease('0.1')
-    >>> print release.release_notes
+    >>> print(release.release_notes)
     Initial release.
 
     >>> form = {
@@ -152,19 +152,19 @@ A ProductRelease can be edited using the ProductReleaseEditView.
     ...     'field.actions.change': 'Change',
     ...     }
     >>> view = create_initialized_view(release, '+edit', form=form)
-    >>> print view.label
+    >>> print(view.label)
     Edit App 0.1 release details
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Edit App 0.1 release details
 
-    >>> print view.errors
+    >>> print(view.errors)
     []
 
-    >>> print view.widget_errors
+    >>> print(view.widget_errors)
     {}
 
-    >>> print release.release_notes
+    >>> print(release.release_notes)
     revised
 
 
@@ -193,10 +193,10 @@ Adding a download file to a release
     >>> view = create_initialized_view(
     ...     release, '+adddownloadfile',
     ...     form=form)
-    >>> print view.label
+    >>> print(view.label)
     Add a download file to App 0.1
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Add a download file to App 0.1
 
 
@@ -207,18 +207,18 @@ Deleting a product release
     ...     'field.actions.delete': 'Delete Release',
     ...     }
     >>> view = create_initialized_view(release, '+delete', form=form)
-    >>> print view.label
+    >>> print(view.label)
     Delete App 0.1
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Delete App 0.1
 
-    >>> print view.errors
+    >>> print(view.errors)
     []
 
-    >>> print view.widget_errors
+    >>> print(view.widget_errors)
     {}
 
     >>> release = series.getRelease('0.1')
-    >>> print release
+    >>> print(release)
     None
diff --git a/lib/lp/registry/browser/tests/productseries-setbranch-view.txt b/lib/lp/registry/browser/tests/productseries-setbranch-view.txt
index 7aea39e..1f2a8ce 100644
--- a/lib/lp/registry/browser/tests/productseries-setbranch-view.txt
+++ b/lib/lp/registry/browser/tests/productseries-setbranch-view.txt
@@ -18,7 +18,7 @@ that exists externally in a variety of version control systems.
     >>> view = create_initialized_view(
     ...     series, name='+setbranch', principal=driver)
     >>> content = find_tag_by_id(view.render(), 'maincontent')
-    >>> print content
+    >>> print(content)
     <div...
     ...Link to a Bazaar branch already on Launchpad...
     ...Import a branch hosted somewhere else...
@@ -45,7 +45,7 @@ must be provided.
     >>> view = create_initialized_view(
     ...    series, name='+setbranch', principal=driver, form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     The branch location must be set.
 
 Setting the branch location to an invalid branch results in another
@@ -59,7 +59,7 @@ validation error.
     >>> view = create_initialized_view(
     ...    series, name='+setbranch', principal=driver, form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     (u'Invalid value', InvalidValue("token ...'foo' not found in vocabulary"))
 
 Providing a valid branch results in a successful linking.
@@ -76,12 +76,12 @@ Providing a valid branch results in a successful linking.
     >>> view = create_initialized_view(
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Series code location updated.
 
-    >>> print series.branch.name
+    >>> print(series.branch.name)
     impala-branch
 
 Revisiting the +setbranch page when the branch is already set will
@@ -89,7 +89,7 @@ show the branch location pre-populated with the existing value.
 
     >>> view = create_initialized_view(
     ...     series, name='+setbranch', principal=driver, form=form)
-    >>> print view.widgets.get('branch_location')._getFormValue().unique_name
+    >>> print(view.widgets.get('branch_location')._getFormValue().unique_name)
     ~person.../chevy/impala-branch
 
 
@@ -111,9 +111,9 @@ Lots of data are required to create an import.
     >>> view = create_initialized_view(
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     You must set the external repository URL.
     You must specify the type of RCS for the remote host.
     The branch name must be set.
@@ -132,9 +132,9 @@ For Bazaar branches the scheme may only be http or https.
     >>> view = create_initialized_view(
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     ('repo_url'...The URI scheme &quot;bzr+ssh&quot; is not allowed.
     Only URIs with the following schemes may be used: bzr, http,
     https'))
@@ -153,11 +153,11 @@ A correct URL is accepted.
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> transaction.commit()
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Code import created and branch linked to the series.
-    >>> print series.branch.name
+    >>> print(series.branch.name)
     blazer-branch
     >>> series.branch.registrant.name == driver.name
     True
@@ -170,7 +170,7 @@ External Bazaar imports can not use an Launchpad URL.
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> transaction.commit()
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     You cannot create same-VCS imports for branches or repositories that are
     hosted by Launchpad.
 
@@ -183,11 +183,11 @@ Git imports can use a Launchpad URL.
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> transaction.commit()
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Code import created and branch linked to the series.
-    >>> print series.branch.name
+    >>> print(series.branch.name)
     blazer-git-branch
 
 Git branches cannot use svn.
@@ -203,9 +203,9 @@ Git branches cannot use svn.
     >>> view = create_initialized_view(
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     ('repo_url'...'The URI scheme &quot;svn&quot; is not allowed.  Only
     URIs with the following schemes may be used: git, http, https'))
 
@@ -225,11 +225,11 @@ But Git branches may use git.
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> transaction.commit()
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Code import created and branch linked to the series.
-    >>> print series.branch.name
+    >>> print(series.branch.name)
     chevette-branch
 
 But Subversion branches cannnot use git.
@@ -245,9 +245,9 @@ But Subversion branches cannnot use git.
     >>> view = create_initialized_view(
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     ('repo_url'...'The URI scheme &quot;git&quot; is not allowed.  Only
     URIs with the following schemes may be used: http, https, svn'))
 
@@ -266,11 +266,11 @@ But Subversion branches may use svn as the scheme.
     >>> view = create_initialized_view(
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Code import created and branch linked to the series.
-    >>> print series.branch.name
+    >>> print(series.branch.name)
     suburban-branch
 
 CVS branches must use http or https as the scheme and must have the
@@ -289,9 +289,9 @@ CVS module field specified.
     >>> view = create_initialized_view(
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     The CVS module must be set.
 
     >>> form = {
@@ -306,11 +306,11 @@ CVS module field specified.
     >>> view = create_initialized_view(
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Code import created and branch linked to the series.
-    >>> print series.branch.name
+    >>> print(series.branch.name)
     corvair-branch
 
 Attempting to import a location that has already been imported results
@@ -327,13 +327,13 @@ in an error.
     >>> view = create_initialized_view(
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     <BLANKLINE>
     This foreign branch URL is already specified for
     the imported branch
     <a href='http://.../chevy/chevette-branch'>~.../chevy/chevette-branch</a>.
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
 
 Using a branch name that already exists results in an error.
 
@@ -348,18 +348,18 @@ Using a branch name that already exists results in an error.
     >>> view = create_initialized_view(
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     There is already an existing import for
     <a href="http://.../chevy";>chevy</a>
     with the name of
     <a href="http://.../chevy/chevette-branch";>chevette-branch</a>.
-    >>> print view.errors_in_action
+    >>> print(view.errors_in_action)
     True
-    >>> print view.next_url
+    >>> print(view.next_url)
     None
 
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
 
 Bazaar external branches are handled differently but they also give an
 error if a duplicate name is used.
@@ -375,16 +375,16 @@ error if a duplicate name is used.
     >>> view = create_initialized_view(
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     <BLANKLINE>
     This foreign branch URL is already specified for the imported branch
     <a href='http://.../blazer-branch'>...</a>.
-    >>> print view.errors_in_action
+    >>> print(view.errors_in_action)
     False
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/chevy/corvair
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
 
 If the owner is set to a private team, an error is raised.
 
@@ -402,5 +402,5 @@ If the owner is set to a private team, an error is raised.
     >>> view = create_initialized_view(
     ...     series, name='+setbranch', principal=driver, form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     Private teams are forbidden from owning external imports.
diff --git a/lib/lp/registry/browser/tests/productseries-views.txt b/lib/lp/registry/browser/tests/productseries-views.txt
index 3aa6138..5cd10a5 100644
--- a/lib/lp/registry/browser/tests/productseries-views.txt
+++ b/lib/lp/registry/browser/tests/productseries-views.txt
@@ -32,19 +32,19 @@ rendering links:
     >>> view = create_view(series, '+get-involved')
 
     # answers_usage is never LAUNCHPAD for product series.
-    >>> print view.answers_usage.name
+    >>> print(view.answers_usage.name)
     NOT_APPLICABLE
-    >>> print view.blueprints_usage.name
+    >>> print(view.blueprints_usage.name)
     LAUNCHPAD
-    >>> print view.official_malone
+    >>> print(view.official_malone)
     True
-    >>> print view.translations_usage.name
+    >>> print(view.translations_usage.name)
     LAUNCHPAD
-    >>> print view.codehosting_usage.name
+    >>> print(view.codehosting_usage.name)
     UNKNOWN
 
     >>> for link in view.enabled_links:
-    ...     print link.url
+    ...     print(link.url)
     http://bugs.launchpad.test/app/simple/+filebug
     http://translations.launchpad.test/app/simple
     http://blueprints.launchpad.test/app/simple/+addspec
@@ -62,7 +62,7 @@ update the milestones and releases table.
     >>> login('foo.bar@xxxxxxxxxxxxx')
     >>> view = create_view(series, '+index', principal=product.owner)
     >>> script = find_tag_by_id(view.render(), 'milestone-script')
-    >>> print script
+    >>> print(script)
     <script id="milestone-script" type="text/javascript">
         LPJS.use(... 'lp.registry.milestoneoverlay',
                       'lp.registry.milestonetable'...
@@ -84,7 +84,7 @@ If the Create milestone link is not enabled, the script is not present.
     >>> ignored = login_person(a_user)
     >>> view = create_view(series, '+index', principal=a_user)
     >>> content = view.render()
-    >>> print find_tag_by_id(content, 'milestone-script')
+    >>> print(find_tag_by_id(content, 'milestone-script'))
     None
     >>> 'var milestone_form_uri' in content
     False
@@ -95,18 +95,18 @@ the class table is 'listing hidden'.
 
     >>> ignored = login_person(product.owner)
     >>> view = create_view(series, '+index', principal=product.owner)
-    >>> print view.milestone_table_class
+    >>> print(view.milestone_table_class)
     listing hidden
 
     >>> table = find_tag_by_id(view.render(), 'series-simple')
-    >>> print ' '.join(table['class'])
+    >>> print(' '.join(table['class']))
     listing hidden
 
 When the product series has milestones, the class is just 'listing'.
 
     >>> milestone = series.newMilestone('12', code_name='twelve')
     >>> view = create_view(series, '+index')
-    >>> print view.milestone_table_class
+    >>> print(view.milestone_table_class)
     listing
 
 Obsolete series are less interesting that other series. The ProductSeriesView
@@ -115,7 +115,7 @@ to display.
 
     >>> from lp.registry.interfaces.series import SeriesStatus
 
-    >>> print series.status.title
+    >>> print(series.status.title)
     Active Development
     >>> view.is_obsolete
     False
@@ -129,18 +129,18 @@ The view provides access to the latest release if it has one.
 
     >>> from lp.registry.interfaces.product import IProductSet
 
-    >>> print view.latest_release_with_download_files
+    >>> print(view.latest_release_with_download_files)
     None
 
     >>> firefox = getUtility(IProductSet).getByName('firefox')
     >>> series_with_downloads = firefox.getSeries('trunk')
     >>> view = create_initialized_view(series_with_downloads, name='+index')
-    >>> print view.latest_release_with_download_files.version
+    >>> print(view.latest_release_with_download_files.version)
     0.9.2
 
 The view also provides a link to register a new code import.
 
-    >>> print view.request_import_link
+    >>> print(view.request_import_link)
     http://code.launchpad.test/firefox/+new-import
 
 
@@ -150,18 +150,18 @@ Edit ProductSeries
 The productseries +edit view provides a label and page_title for the page.
 
     >>> view = create_initialized_view(series, '+edit')
-    >>> print view.label
+    >>> print(view.label)
     Edit App simple series
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Edit App simple series
 
 The view provides a cancel_url and a next_url.
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/app/simple
 
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/app/simple
 
 
@@ -183,15 +183,15 @@ parent project.
 
 The view provides a label and page_title.
 
-    >>> print view.label
+    >>> print(view.label)
     Administer App simple series
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Administer App simple series
 
 The view provides a cancel_url and a next_url.
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/app/simple
 
 Users without edit permission cannot access the view.
@@ -245,19 +245,19 @@ Registry experts can also access the view.
 
 The delete view has a label and page_title to explain what it does.
 
-    >>> print view.label
+    >>> print(view.label)
     Delete Field rabbit series
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Delete Field rabbit series
 
 The view has a a next_url to the product used when the delete is successful,
 though it is None by default. There is a cancel_url that links to the series.
 
-    >>> print view.next_url
+    >>> print(view.next_url)
     None
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/field/rabbit
 
 There are helper properties that list the associates objects with the
@@ -305,16 +305,16 @@ portion do.
     True
     >>> for bugtask in view.bugtasks:
     ...     if bugtask.milestone is not None:
-    ...         print bugtask.milestone.name
+    ...         print(bugtask.milestone.name)
     ...     else:
-    ...         print bugtask.target.name
+    ...         print(bugtask.target.name)
     rabbit
     0.2
     >>> for spec in view.specifications:
     ...     if spec.milestone is not None:
-    ...         print spec.milestone.name
+    ...         print(spec.milestone.name)
     ...     else:
-    ...         print spec.goal.name
+    ...         print(spec.goal.name)
     rabbit
     0.1
 
@@ -348,10 +348,10 @@ development.
     >>> active_view = create_initialized_view(
     ...     active_series, '+delete', form=form)
     >>> for error in active_view.errors:
-    ...     print error
+    ...     print(error)
     You cannot delete a series that is the focus of development. Make another
     series the focus of development before deleting this one.
-    >>> print active_series.product.name
+    >>> print(active_series.product.name)
     field
 
 The delete action will not delete a series that is linked to a package.
@@ -379,7 +379,7 @@ The delete action will not delete a series that is linked to a package.
     >>> linked_view = create_initialized_view(
     ...     linked_series, '+delete', form=form)
     >>> for error in linked_view.errors:
-    ...     print error
+    ...     print(error)
     You cannot delete a series that is linked to packages in distributions.
     You can remove the links from the <a ...>project packaging</a> page.
 
@@ -392,22 +392,22 @@ Series structural subscriptions are removed. Branch links are removed.
 
     >>> view = create_initialized_view(productseries, '+delete', form=form)
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Series rabbit deleted.
 
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/field
     >>> [milestone for milestone in product.all_milestones]
     []
     >>> [release for release in  product.releases]
     []
-    >>> print specification.milestone
+    >>> print(specification.milestone)
     None
-    >>> print bugtask.milestone
+    >>> print(bugtask.milestone)
     None
     >>> bugtask.related_tasks
     []
-    >>> print series_specification.milestone
+    >>> print(series_specification.milestone)
     None
     >>> [subscription for subscription in owner.structural_subscriptions]
     []
@@ -422,14 +422,14 @@ avoid conflicts. The linked branch is removed.
     >>> obsolete_junk = celebrities.obsolete_junk
     >>> productseries.product == obsolete_junk
     True
-    >>> print productseries.name
+    >>> print(productseries.name)
     field-rabbit-20090501-193424
 
 The series status is set to obsolete and the releasefileglob was set to None.
 
-    >>> print productseries.status.title
+    >>> print(productseries.status.title)
     Obsolete
-    >>> print productseries.releasefileglob
+    >>> print(productseries.releasefileglob)
     None
 
 A series cannot be deleted if it is has translation templates.
@@ -452,7 +452,7 @@ A series cannot be deleted if it is has translation templates.
     >>> translated_view = create_initialized_view(
     ...     translated_series, '+delete', form=form)
     >>> for error in translated_view.errors:
-    ...     print error
+    ...     print(error)
     This series cannot be deleted because it has translations.
 
 The view reports all the reason why a series cannot be deleted.
@@ -468,7 +468,7 @@ The view reports all the reason why a series cannot be deleted.
     ...     }
     >>> view = create_initialized_view(active_series, '+delete', form=form)
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     You cannot delete a series that is the focus of development. Make another
     series the focus of development before deleting this one.
     You cannot delete a series that is linked to packages in distributions.
diff --git a/lib/lp/registry/browser/tests/project-add-views.txt b/lib/lp/registry/browser/tests/project-add-views.txt
index 6bffef4..36f1960 100644
--- a/lib/lp/registry/browser/tests/project-add-views.txt
+++ b/lib/lp/registry/browser/tests/project-add-views.txt
@@ -26,7 +26,7 @@ forwarded, but is only required by the Zope machinery, not the view.
 
     >>> view = create_initialized_view(product_set, name='+new', form=form)
     >>> for error in view.view.errors:
-    ...     print error
+    ...     print(error)
     ('display_name', 'Name', RequiredMissing('display_name'))
     ('name', 'URL', RequiredMissing('name'))
     ('summary', u'Summary', RequiredMissing('summary'))
@@ -49,9 +49,9 @@ count.  The first step has no search results.
     >>> view = ProjectAddStepOne(product_set, request)
     >>> view.initialize()
 
-    >>> print view.label
+    >>> print(view.label)
     Register a project in Launchpad
-    >>> print view.step_description
+    >>> print(view.step_description)
     Project basics
     >>> view.search_results_count
     0
@@ -73,9 +73,9 @@ information in the label.
     >>> view = ProjectAddStepTwo(product_set, request)
     >>> view.initialize()
 
-    >>> print view.label
+    >>> print(view.label)
     Register Snowdog (snowdog) in Launchpad
-    >>> print view.step_description
+    >>> print(view.step_description)
     Registration details
     >>> view.search_results_count
     0
@@ -96,13 +96,13 @@ can see that there are search results available.
     >>> view = ProjectAddStepTwo(product_set, request)
     >>> view.initialize()
 
-    >>> print view.label
+    >>> print(view.label)
     Register Snowdog (snowdog) in Launchpad
 
 Because there are search results, the description used on the page is
 different.
 
-    >>> print view.step_description
+    >>> print(view.step_description)
     Check for duplicate projects
 
 The search results are displayed on the page.
@@ -110,7 +110,7 @@ The search results are displayed on the page.
     >>> view.search_results_count
     2
     >>> for project in view.search_results:
-    ...     print project.name
+    ...     print(project.name)
     firefox
     mozilla
 
@@ -127,7 +127,7 @@ result in an error, since the licence is required.
     >>> view = ProjectAddStepTwo(product_set, request)
     >>> view.initialize()
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     You must select at least one licence.  If you select Other/Proprietary
     or Other/OpenSource you must include a description of the licence.
     ...
@@ -157,7 +157,7 @@ When an open source licence is selected, the project is created.
     >>> view.errors
     []
 
-    >>> print product_set.getByName('snowdog').display_name
+    >>> print(product_set.getByName('snowdog').display_name)
     Snowdog
 
 
@@ -180,6 +180,6 @@ that's checked for duplicates is the 'name' field.
     >>> view.initialize()
 
     >>> for error in view.errors:
-    ...     print error
+    ...     print(error)
     ('name', 'URL',
      LaunchpadValidationError(u'snowdog is already used by another project'))
diff --git a/lib/lp/registry/browser/tests/projectgroup-views.txt b/lib/lp/registry/browser/tests/projectgroup-views.txt
index 99aaca0..1621e06 100644
--- a/lib/lp/registry/browser/tests/projectgroup-views.txt
+++ b/lib/lp/registry/browser/tests/projectgroup-views.txt
@@ -62,13 +62,13 @@ support any applications.
 
     >>> view = create_view(projectgroup, name='+index', principal=owner)
     >>> content = find_tag_by_id(view.render(), 'maincontent')
-    >>> print find_tag_by_id(content, 'portlet-latest-faqs')
+    >>> print(find_tag_by_id(content, 'portlet-latest-faqs'))
     None
-    >>> print find_tag_by_id(content, 'portlet-latest-questions')
+    >>> print(find_tag_by_id(content, 'portlet-latest-questions'))
     None
-    >>> print find_tag_by_id(content, 'portlet-latest-bugs')
+    >>> print(find_tag_by_id(content, 'portlet-latest-bugs'))
     None
-    >>> print find_tag_by_id(content, 'portlet-blueprints')
+    >>> print(find_tag_by_id(content, 'portlet-blueprints'))
     None
 
 The portlet are rendered when a child product officially uses the Launchpad
@@ -82,11 +82,11 @@ Answers, Blueprints, and Bugs applications.
     >>> view = create_view(projectgroup, name='+index', principal=owner)
     >>> content = find_tag_by_id(view.render(), 'maincontent')
 
-    >>> print find_tag_by_id(content, 'portlet-latest-faqs')['id']
+    >>> print(find_tag_by_id(content, 'portlet-latest-faqs')['id'])
     portlet-latest-faqs
-    >>> print find_tag_by_id(content, 'portlet-latest-questions')['id']
+    >>> print(find_tag_by_id(content, 'portlet-latest-questions')['id'])
     portlet-latest-questions
-    >>> print find_tag_by_id(content, 'portlet-latest-bugs')['id']
+    >>> print(find_tag_by_id(content, 'portlet-latest-bugs')['id'])
     portlet-latest-bugs
-    >>> print find_tag_by_id(content, 'portlet-blueprints')['id']
+    >>> print(find_tag_by_id(content, 'portlet-blueprints')['id'])
     portlet-blueprints
diff --git a/lib/lp/registry/browser/tests/projectgroupset-views.txt b/lib/lp/registry/browser/tests/projectgroupset-views.txt
index bcf68b6..f567517 100644
--- a/lib/lp/registry/browser/tests/projectgroupset-views.txt
+++ b/lib/lp/registry/browser/tests/projectgroupset-views.txt
@@ -24,7 +24,7 @@ A Launchpad admin has permission to access the +index view.
 
 The view provides a page_title.
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Project groups registered in Launchpad
 
 A regular user cannot access the view.
@@ -64,7 +64,7 @@ A Launchpad admin has permission to access the +all view.
 
 The view provides a page_title.
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Project groups registered in Launchpad
 
 A regular user cannot access the view.
@@ -90,7 +90,7 @@ A Launchpad admin has permission to access the +new view.
     >>> check_permission('launchpad.Moderate', view)
     True
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Register a project group with Launchpad
 
 A regular user cannot access the view.
diff --git a/lib/lp/registry/browser/tests/sourcepackage-views.txt b/lib/lp/registry/browser/tests/sourcepackage-views.txt
index d157ee5..8239afa 100644
--- a/lib/lp/registry/browser/tests/sourcepackage-views.txt
+++ b/lib/lp/registry/browser/tests/sourcepackage-views.txt
@@ -16,13 +16,13 @@ Edit packaging view
     ...     sourcepackagename=sourcepackagename, distroseries=distroseries)
 
     >>> view = create_initialized_view(package, name='+edit-packaging')
-    >>> print view.label
+    >>> print(view.label)
     Link to an upstream project
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Link to an upstream project
 
-    >>> print view.view.cancel_url
+    >>> print(view.view.cancel_url)
     http://launchpad.test/youbuntu/busy/+source/bonkers
 
 
@@ -36,17 +36,17 @@ to create a source package.
     >>> [form_field.__name__ for form_field in view.view.form_fields]
     ['__visited_steps__', 'product']
 
-    >>> print view.view.widgets.get('product')._getFormValue()
+    >>> print(view.view.widgets.get('product')._getFormValue())
     <BLANKLINE>
 
-    >>> print package.productseries
+    >>> print(package.productseries)
     None
 
 This is a multistep view. In the first step, the product is specified.
 
-    >>> print view.view.__class__.__name__
+    >>> print(view.view.__class__.__name__)
     SourcePackageChangeUpstreamStepOne
-    >>> print view.view.request.form
+    >>> print(view.view.request.form)
     {'field.__visited_steps__': 'sourcepackage_change_upstream_step1'}
 
     >>> ignored = login_person(product.owner)
@@ -64,9 +64,9 @@ This is a multistep view. In the first step, the product is specified.
 In the second step, one of the series of the previously selected
 product can be chosen from a list of options.
 
-    >>> print view.view.__class__.__name__
+    >>> print(view.view.__class__.__name__)
     SourcePackageChangeUpstreamStepTwo
-    >>> print view.view.request.form['field.__visited_steps__']
+    >>> print(view.view.request.form['field.__visited_steps__'])
     sourcepackage_change_upstream_step1|sourcepackage_change_upstream_step2
     >>> [term.token for term in view.view.widgets['productseries'].vocabulary]
     ['trunk', 'crazy']
@@ -82,14 +82,14 @@ product can be chosen from a list of options.
     ...     principal=product.owner)
 
     >>> ignored = view.view.render()
-    >>> print view.view.next_url
+    >>> print(view.view.next_url)
     http://launchpad.test/youbuntu/busy/+source/bonkers
 
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Upstream link updated.
 
-    >>> print package.productseries.name
+    >>> print(package.productseries.name)
     crazy
 
     >>> transaction.commit()
@@ -98,7 +98,7 @@ The form shows the current product if it is set.
 
     >>> view = create_initialized_view(package, name='+edit-packaging')
 
-    >>> print view.view.widgets.get('product')._getFormValue().name
+    >>> print(view.view.widgets.get('product')._getFormValue().name)
     bonkers
 
 If the same product as the current product series is selected,
@@ -112,7 +112,7 @@ then the current product series will be the selected option.
     >>> view = create_initialized_view(
     ...     package, name='+edit-packaging', form=form,
     ...     principal=product.owner)
-    >>> print view.view.widgets.get('productseries')._getFormValue().name
+    >>> print(view.view.widgets.get('productseries')._getFormValue().name)
     crazy
 
 The form requires a product. An error is raised if the field is left
@@ -127,7 +127,7 @@ empty.
     ...     package, name='+edit-packaging', form=form,
     ...     principal=product.owner)
     >>> for error in view.view.errors:
-    ...     print error
+    ...     print(error)
     ('product', u'Project', RequiredMissing('product'))
 
 Submitting the same product series as the current packaging is not an error,
@@ -142,14 +142,14 @@ but there is no notification message that the upstream link was updated.
     >>> view = create_initialized_view(
     ...     package, name='+edit-packaging', form=form,
     ...     principal=product.owner)
-    >>> print view.view
+    >>> print(view.view)
     <...SourcePackageChangeUpstreamStepTwo object...>
-    >>> print view.view.next_url
+    >>> print(view.view.next_url)
     http://launchpad.test/youbuntu/busy/+source/bonkers
     >>> view.view.errors
     []
 
-    >>> print view.request.response.notifications
+    >>> print(view.request.response.notifications)
     []
 
 
@@ -166,20 +166,20 @@ bonkers project, the portlet will display that information.
 
     >>> view = create_initialized_view(package, name='+portlet-associations')
     >>> for product in view.product_suggestions:
-    ...     print product.name
+    ...     print(product.name)
     bonkers
 
     >>> from lp.testing.pages import (
     ...     extract_text, find_tag_by_id)
     >>> content = find_tag_by_id(view.render(), 'upstreams')
     >>> for link in content.findAll('a'):
-    ...     print link['href']
+    ...     print(link['href'])
     /bonkers
     /bonkers/crazy
     .../+source/bonkers/+edit-packaging
     .../+source/bonkers/+remove-packaging
 
-    >>> print extract_text(content)
+    >>> print(extract_text(content))
     Bonkers...crazy...
     Bug supervisor: no
     Bug tracker: no
@@ -196,11 +196,11 @@ the portlet showing the suggested project.
 
     >>> view = create_initialized_view(package, name='+portlet-associations')
     >>> for product in view.product_suggestions:
-    ...     print product.name
+    ...     print(product.name)
     lernid
 
     >>> content = extract_text(find_tag_by_id(view.render(), 'no-upstreams'))
-    >>> print content
+    >>> print(content)
     Launchpad doesn’t know which project and series this package belongs to.
     ...
     Is the following project the upstream for this source package?
@@ -212,7 +212,7 @@ the portlet showing the suggested project.
 The form does not steal focus because it is not the primary purpose of the
 page.
 
-    >>> print view.initial_focus_widget
+    >>> print(view.initial_focus_widget)
     None
 
 If there are multiple potential matches, the first 9 are shown. The 10th
@@ -222,7 +222,7 @@ item is reserved for the "Choose another upstream project" option.
     ...     name='lernid-dev', displayname='Lernid Dev')
     >>> view = create_initialized_view(package, name='+portlet-associations')
     >>> for product in view.product_suggestions:
-    ...     print product.name
+    ...     print(product.name)
     lernid
     lernid-dev
 
@@ -230,7 +230,7 @@ item is reserved for the "Choose another upstream project" option.
     9
 
     >>> content = extract_text(find_tag_by_id(view.render(), 'no-upstreams'))
-    >>> print content
+    >>> print(content)
     Launchpad doesn’t know which project and series this package belongs to.
     ...
     Is one of these projects the upstream for this source package?
@@ -251,7 +251,7 @@ to the +edit-packaging page where the user can search for a project.
     ...     package, name='+portlet-associations', form=form)
     >>> view.errors
     []
-    >>> print view.next_url
+    >>> print(view.next_url)
     http://launchpad.test/youbuntu/busy/+source/lernid/+edit-packaging
 
 
@@ -277,15 +277,15 @@ If the view's package has no productseries set then has_bugtracker is False.
     >>> view = create_initialized_view(
     ...     package, name='+upstream-connections')
 
-    >>> print package.productseries
+    >>> print(package.productseries)
     None
-    >>> print view.has_bugtracker
+    >>> print(view.has_bugtracker)
     False
 
 So let's set the product series so we can do more interesting testing.
 
     >>> package.setPackaging(productseries, product.owner)
-    >>> print package.productseries.name
+    >>> print(package.productseries.name)
     stinkyseries
 
 If a product is not part of a project group and its bug tracker is not
@@ -294,18 +294,18 @@ set then the view property is false.
     >>> view = create_initialized_view(
     ...     package, name='+upstream-connections')
 
-    >>> print product.bug_tracking_usage.name
+    >>> print(product.bug_tracking_usage.name)
     UNKNOWN
-    >>> print product.bugtracker
+    >>> print(product.bugtracker)
     None
-    >>> print view.has_bugtracker
+    >>> print(view.has_bugtracker)
     False
 
 Having official_malone set results in has_bugtracker being true.
 
     >>> ignored = login_person(product.owner)
     >>> product.official_malone = True
-    >>> print view.has_bugtracker
+    >>> print(view.has_bugtracker)
     True
 
 Having a bug_tracker set also results in has_bugtracker being true (a
@@ -314,7 +314,7 @@ bit of a tautology you'd think).
     >>> product.official_malone = False
     >>> bugtracker = factory.makeBugTracker()
     >>> product.bugtracker = bugtracker
-    >>> print view.has_bugtracker
+    >>> print(view.has_bugtracker)
     True
 
 If the product has no bug tracker and is in a project group with no
@@ -322,10 +322,10 @@ bug tracker then the property is false.
 
     >>> product.bugtracker = None
     >>> projectgroup = factory.makeProject()
-    >>> print projectgroup.bugtracker
+    >>> print(projectgroup.bugtracker)
     None
     >>> product.projectgroup = projectgroup
-    >>> print view.has_bugtracker
+    >>> print(view.has_bugtracker)
     False
 
 If the product's project group does have a bug tracker then the product
@@ -333,7 +333,7 @@ inherits it.
 
     >>> ignored = login_person(projectgroup.owner)
     >>> projectgroup.bugtracker = bugtracker
-    >>> print view.has_bugtracker
+    >>> print(view.has_bugtracker)
     True
 
 
@@ -344,13 +344,13 @@ This view allows removal of the packaging link from the sourcepackage
 to the project series.
 
     >>> view = create_initialized_view(package, name='+remove-packaging')
-    >>> print view.label
+    >>> print(view.label)
     Unlink an upstream project
 
-    >>> print view.page_title
+    >>> print(view.page_title)
     Unlink an upstream project
 
-    >>> print view.cancel_url
+    >>> print(view.cancel_url)
     http://launchpad.test/youbuntu/wonky/+source/stinkypackage
 
     >>> user = package.packaging.owner
@@ -362,7 +362,7 @@ to the project series.
     []
 
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     Removed upstream association between Stinky stinkyseries series and Wonky.
 
 If somebody attempts to remove this packaging link a second time,
@@ -375,11 +375,11 @@ deleted.
     []
 
     >>> for notification in view.request.response.notifications:
-    ...     print notification.message
+    ...     print(notification.message)
     The packaging link has already been deleted.
 
     >>> view = create_initialized_view(package, name='+portlet-associations')
-    >>> print extract_text(find_tag_by_id(view.render(), 'no-upstreams'))
+    >>> print(extract_text(find_tag_by_id(view.render(), 'no-upstreams')))
     Launchpad doesn’t know which project ...
     There are no projects registered in Launchpad that are a potential
     match for this source package. Can you help us find one?
diff --git a/lib/lp/registry/browser/tests/team-join-views.txt b/lib/lp/registry/browser/tests/team-join-views.txt
index 8212e97..97c8d60 100644
--- a/lib/lp/registry/browser/tests/team-join-views.txt
+++ b/lib/lp/registry/browser/tests/team-join-views.txt
@@ -16,7 +16,7 @@ Tests for the team '+join' page's raw view objects.
     ...     view = getMultiAdapter((team, request), name='+join')
     ...     view.initialize()
     ...     for notification in request.notifications:
-    ...         print notification.message
+    ...         print(notification.message)
 
     # Define a helper for creating teams with a specific subscription
     # policy.
diff --git a/lib/lp/registry/browser/tests/team-views.txt b/lib/lp/registry/browser/tests/team-views.txt
index 191ba5c..553cd78 100644
--- a/lib/lp/registry/browser/tests/team-views.txt
+++ b/lib/lp/registry/browser/tests/team-views.txt
@@ -17,14 +17,14 @@ as well as the up to five latest members who proposed themselves.
     >>> membershipset = getUtility(ITeamMembershipSet)
     >>> for member in team_home.recently_approved_members:
     ...     membership = membershipset.getByPersonAndTeam(member, ubuntu_team)
-    ...     print "%s: %s" % (member.name, membership.status.title)
+    ...     print("%s: %s" % (member.name, membership.status.title))
     name20: Approved
     spiv: Approved
     limi: Approved
 
     >>> for member in team_home.recently_proposed_members:
     ...     membership = membershipset.getByPersonAndTeam(member, ubuntu_team)
-    ...     print "%s: %s" % (member.name, membership.status.title)
+    ...     print("%s: %s" % (member.name, membership.status.title))
     justdave: Proposed
 
 If new members are added/proposed, they'll show up at the top of the lists.
@@ -40,7 +40,7 @@ If new members are added/proposed, they'll show up at the top of the lists.
     >>> team_home = create_initialized_view(ubuntu_team, '+index')
     >>> for member in team_home.recently_approved_members:
     ...     membership = membershipset.getByPersonAndTeam(member, ubuntu_team)
-    ...     print "%s: %s" % (member.name, membership.status.title)
+    ...     print("%s: %s" % (member.name, membership.status.title))
     salgado: Approved
     name20: Approved
     spiv: Approved
@@ -48,7 +48,7 @@ If new members are added/proposed, they'll show up at the top of the lists.
 
     >>> for member in team_home.recently_proposed_members:
     ...     membership = membershipset.getByPersonAndTeam(member, ubuntu_team)
-    ...     print "%s: %s" % (member.name, membership.status.title)
+    ...     print("%s: %s" % (member.name, membership.status.title))
     name12: Proposed
     justdave: Proposed
 
@@ -83,9 +83,9 @@ because bart is not a member of the team.
     >>> ignored = login_person(bart)
 
     >>> view = create_initialized_view(guadamen, '+index')
-    >>> print view.contact_link_title
+    >>> print(view.contact_link_title)
     Send an email to this team's admins through Launchpad
-    >>> print view.specific_contact_text
+    >>> print(view.specific_contact_text)
     Contact this team's admins
 
 
@@ -98,15 +98,15 @@ page.  The display of mugshots is batched.
     >>> ubuntu = person_set.getByName('ubuntu-team')
     >>> view = create_initialized_view(ubuntu, '+mugshots')
     >>> batch = view.members.currentBatch()
-    >>> print len(list(ubuntu.allmembers))
+    >>> print(len(list(ubuntu.allmembers)))
     10
-    >>> print view.batch_size
+    >>> print(view.batch_size)
     8
-    >>> print len(list(batch))
+    >>> print(len(list(batch)))
     8
     >>> from zope.security.proxy import removeSecurityProxy
     >>> for person in list(batch):
-    ...     print removeSecurityProxy(person)
+    ...     print(removeSecurityProxy(person))
     <Person at ... limi (Alexander Limi)>
     <Person at ... cprov (Celso Providelo)>
     <Person at ... kamion (Colin Watson)>
@@ -124,9 +124,9 @@ Team visibility is used on the page to indicate privacy.  GuadaMen is a public
 team.
 
     >>> view = create_initialized_view(guadamen, '+index')
-    >>> print view.visibility_info
+    >>> print(view.visibility_info)
     Public team
-    >>> print view.visibility_portlet_class
+    >>> print(view.visibility_portlet_class)
     portlet
 
 Private teams are indicated as private.
@@ -139,9 +139,9 @@ Private teams are indicated as private.
     ...     visibility=PersonVisibility.PRIVATE)
 
     >>> view = create_initialized_view(private_team, '+index')
-    >>> print view.visibility_info
+    >>> print(view.visibility_info)
     Private team
-    >>> print view.visibility_portlet_class
+    >>> print(view.visibility_portlet_class)
     portlet private
 
 +add-my-teams
@@ -153,7 +153,7 @@ to the current team.
     >>> ignored = login_person(sample_person)
     >>> view = create_initialized_view(guadamen, '+add-my-teams')
     >>> for candidate in view.candidate_teams:
-    ...     print candidate.name, candidate.visibility.title
+    ...     print(candidate.name, candidate.visibility.title)
     landscape-developers Public
     launchpad-users Public
     private-team Private
diff --git a/lib/lp/registry/browser/tests/teammembership-views.txt b/lib/lp/registry/browser/tests/teammembership-views.txt
index ea06526..e6356a1 100644
--- a/lib/lp/registry/browser/tests/teammembership-views.txt
+++ b/lib/lp/registry/browser/tests/teammembership-views.txt
@@ -36,7 +36,7 @@ The TeamMembershipEditView provides a label that described the membership
 state of the IPerson.
 
     >>> view = create_view(membership, '+index')
-    >>> print view.label
+    >>> print(view.label)
     Active member Team-owner
 
 
@@ -48,7 +48,7 @@ the ~team/+invitations page.
 
     >>> team = factory.makeTeam(displayname='Bassists', name='bassists')
     >>> view = create_initialized_view(team, '+invitations')
-    >>> print view.label
+    >>> print(view.label)
     Invitations for Bassists
 
 
@@ -66,11 +66,11 @@ is applied during the stepto traversal--it is not a named view in ZCML.
     >>> membership = membership_set.getByPersonAndTeam(team, super_team)
     >>> ignored = login_person(team.teamowner)
     >>> view = TeamInvitationView(membership, request)
-    >>> print view.label
+    >>> print(view.label)
     Make Bassists a member of Us
 
 The view provides page_title to create a breadcrumb that describes this
 use the TeamMembership.
 
-    >>> print view.page_title.encode('ascii', 'backslashreplace')
+    >>> print(view.page_title.encode('ascii', 'backslashreplace'))
     \u201cUs\u201d team invitation
diff --git a/lib/lp/registry/browser/tests/test_views.py b/lib/lp/registry/browser/tests/test_views.py
index e5f35c4..cb9bc72 100644
--- a/lib/lp/registry/browser/tests/test_views.py
+++ b/lib/lp/registry/browser/tests/test_views.py
@@ -56,8 +56,9 @@ def test_suite():
         path = filename
         layer = special_test_layer.get(path, DatabaseFunctionalLayer)
         one_test = LayeredDocFileSuite(
-            path, setUp=setUp, tearDown=tearDown, layer=layer,
-            stdout_logging_level=logging.WARNING)
+            path,
+            setUp=lambda test: setUp(test, future=True), tearDown=tearDown,
+            layer=layer, stdout_logging_level=logging.WARNING)
         suite.addTest(one_test)
 
     return suite