← Back to team overview

launchpad-reviewers team mailing list archive

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

 

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

Commit message:
Convert lp.registry 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/398127
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:py3-registry-doctests-future-imports into launchpad:master.
diff --git a/lib/lp/registry/doc/announcement.txt b/lib/lp/registry/doc/announcement.txt
index 399b4b5..cb09b62 100644
--- a/lib/lp/registry/doc/announcement.txt
+++ b/lib/lp/registry/doc/announcement.txt
@@ -24,7 +24,7 @@ after publishing, and they can be deleted, permanently.
     >>> tomcat = getUtility(IProductSet).getByName('tomcat')
     >>> derby = getUtility(IProductSet).getByName('derby')
     >>> mark = apache.owner
-    >>> print mark.name
+    >>> print(mark.name)
     mark
 
 
@@ -152,9 +152,9 @@ project group announcements, and vice versa.
     >>> transaction.commit()
 
     >>> for pillar in [tomcat, derby, apache, kubuntu]:
-    ...   print pillar.name
+    ...   print(pillar.name)
     ...   for announcement in pillar.getAnnouncements():
-    ...     print announcement.title
+    ...     print(announcement.title)
     tomcat
     Apache Tomcat JK 1.2.25 Web Server Connector released
     OS Summit Asia 2007 - New Event by Apache and Eclipse
@@ -170,7 +170,7 @@ project group announcements, and vice versa.
 
     >>> for announcement in apache.getAnnouncements(published_only=False):
     ...   if announcement.published is False:
-    ...     print announcement.title
+    ...     print(announcement.title)
     Last Call for OSSummit Asia CFP
     The future Tomcat will yawl all night without interruption
 
@@ -196,17 +196,17 @@ modify() method.
     Traceback (most recent call last):
       ...
     zope.security.interfaces.ForbiddenAttribute: ...
-    >>> print kubuntu_release.date_last_modified
+    >>> print(kubuntu_release.date_last_modified)
     None
     >>> kubuntu_release.modify(title='Foo!', summary='Foo',
     ...                        url='http://foo.com')
-    >>> print kubuntu_release.title
+    >>> print(kubuntu_release.title)
     Foo!
-    >>> print kubuntu_release.summary,
+    >>> print(kubuntu_release.summary)
     Foo
-    >>> print kubuntu_release.url
+    >>> print(kubuntu_release.url)
     http://foo.com
-    >>> print kubuntu_release.date_last_modified is not None
+    >>> print(kubuntu_release.date_last_modified is not None)
     True
 
 
@@ -220,9 +220,9 @@ updates the date_last_modified and sets the announcement.active flag to False
     >>> transaction_timestamp = get_transaction_timestamp(
     ...     Store.of(apache_asia))
 
-    >>> print apache_asia.date_last_modified
+    >>> print(apache_asia.date_last_modified)
     None
-    >>> print apache_asia.active
+    >>> print(apache_asia.active)
     True
     >>> apache_asia.retract()
     >>> flush_database_updates()
@@ -246,7 +246,7 @@ Announcements which have been retracted can be published again:
 You can also publish an Announcement by setting the publication date to the
 current date and time:
 
-    >>> print apache_oss.date_announced
+    >>> print(apache_oss.date_announced)
     None
     >>> apache_oss.setPublicationDate(NOW)
     >>> apache_oss.date_announced is not None
@@ -261,16 +261,16 @@ And you can reset the date of publication:
 
 You can move an announcement from one pillar to the next:
 
-    >>> print apache_asia.target.name
+    >>> print(apache_asia.target.name)
     apache
     >>> apache_asia.retarget(derby)
-    >>> print apache_asia.target.name
+    >>> print(apache_asia.target.name)
     derby
     >>> apache_asia.retarget(kubuntu)
-    >>> print apache_asia.target.name
+    >>> print(apache_asia.target.name)
     kubuntu
     >>> apache_asia.retarget(apache)
-    >>> print apache_asia.target.name
+    >>> print(apache_asia.target.name)
     apache
 
 
@@ -280,7 +280,7 @@ You can ask an announcement to delete itself permanently.
 
     >>> old_id = kubuntu_release.id
     >>> kubuntu_release.destroySelf()
-    >>> print kubuntu.getAnnouncement(old_id)
+    >>> print(kubuntu.getAnnouncement(old_id))
     None
 
 
diff --git a/lib/lp/registry/doc/cache-country-mirrors.txt b/lib/lp/registry/doc/cache-country-mirrors.txt
index 5fd300a..d5ef0d5 100644
--- a/lib/lp/registry/doc/cache-country-mirrors.txt
+++ b/lib/lp/registry/doc/cache-country-mirrors.txt
@@ -41,7 +41,7 @@ look good.
     >>> set(['BR.txt', 'AR.txt', 'CO.txt', 'CL.txt']).issubset(files)
     True
     >>> fr_txt_path = os.path.join(directory, 'FR.txt')
-    >>> print '%o' % stat.S_IMODE(os.stat(fr_txt_path).st_mode)
+    >>> print('%o' % stat.S_IMODE(os.stat(fr_txt_path).st_mode))
     644
     >>> for line in sorted(open(fr_txt_path).read().split('\n')):
     ...     print(line)
diff --git a/lib/lp/registry/doc/commercialsubscription.txt b/lib/lp/registry/doc/commercialsubscription.txt
index 4d0d070..8dc23dd 100644
--- a/lib/lp/registry/doc/commercialsubscription.txt
+++ b/lib/lp/registry/doc/commercialsubscription.txt
@@ -18,7 +18,7 @@ indicated by 'None'.
 
     >>> product_set = getUtility(IProductSet)
     >>> bzr = product_set.getByName('bzr')
-    >>> print bzr.commercial_subscription
+    >>> print(bzr.commercial_subscription)
     None
 
 Make a commercial subscription.
@@ -31,7 +31,7 @@ Commercial subscriptions have zope.Public permissions for reading.
     >>> login(ANONYMOUS)
     >>> check_permission('zope.Public', bzr.commercial_subscription)
     True
-    >>> print bzr.commercial_subscription.product.name
+    >>> print(bzr.commercial_subscription.product.name)
     bzr
 
 For modification, launchpad.Commerical is required.  Anonymous users,
@@ -212,7 +212,7 @@ then display name.
     >>> flush_database_updates()
     >>> for product in product_set.forReview(commercial_member,
     ...                                      search_text='gnome'):
-    ...     print product.displayname
+    ...     print(product.displayname)
     python gnome2 dev
     Evolution
     GNOME Terminal
@@ -224,7 +224,7 @@ The license_info field is also searched for matching search_text:
     >>> bzr.license_info = 'Code in /contrib is under a mit-like licence.'
     >>> for product in product_set.forReview(commercial_member,
     ...                                      search_text='mit'):
-    ...     print product.name
+    ...     print(product.name)
     bzr
 
 The whiteboard field is also searched for matching search_text:
@@ -235,13 +235,13 @@ The whiteboard field is also searched for matching search_text:
     ...         'cc-nc discriminates against commercial uses.')
     >>> for product in product_set.forReview(commercial_member,
     ...                                      search_text='cc-nc'):
-    ...     print product.name
+    ...     print(product.name)
     bzr
 
 You can search for whether the product is active or not.
 
     >>> for product in product_set.forReview(commercial_member, active=False):
-    ...     print product.name
+    ...     print(product.name)
     python-gnome2-dev
     unassigned
 
@@ -249,7 +249,7 @@ You can search for whether the product is marked reviewed or not.
 
     >>> for product in product_set.forReview(commercial_member,
     ...                                      project_reviewed=True):
-    ...     print product.name
+    ...     print(product.name)
     python-gnome2-dev
     unassigned
     alsa-utils
@@ -261,7 +261,7 @@ any one of the licences listed.
     >>> for product in product_set.forReview(
     ...     commercial_member,
     ...     licenses=[License.GNU_GPL_V2, License.BSD]):
-    ...     print product.name
+    ...     print(product.name)
     bzr
 
 It is possible to search for problem project that have been reviewed, but
@@ -270,7 +270,7 @@ not approved
     >>> for product in product_set.forReview(
     ...     commercial_member,
     ...     project_reviewed=True, license_approved=False):
-    ...     print product.name
+    ...     print(product.name)
     python-gnome2-dev
     unassigned
     alsa-utils
@@ -283,7 +283,7 @@ was created.
     ...     search_text='bzr',
     ...     created_after=bzr.datecreated,
     ...     created_before=bzr.datecreated):
-    ...     print product.name
+    ...     print(product.name)
     bzr
 
 You can search for products based on the expiration date of
@@ -295,7 +295,7 @@ its commercial subscription.
     ...     search_text='bzr',
     ...     subscription_expires_after=date_expires,
     ...     subscription_expires_before=date_expires):
-    ...     print product.name
+    ...     print(product.name)
     bzr
 
 You can also search using a datetime.date object, since that is what
@@ -314,7 +314,7 @@ the web form delivers.
     ...     created_before=late_date,
     ...     subscription_modified_after=early_date,
     ...     subscription_modified_before=late_date):
-    ...     print product.name
+    ...     print(product.name)
     bzr
 
 A reviewer can search for projects without a commercial subscription.
@@ -322,7 +322,7 @@ A reviewer can search for projects without a commercial subscription.
     >>> for product in product_set.forReview(
     ...     commercial_member,
     ...     has_subscription=False, licenses=[License.OTHER_PROPRIETARY]):
-    ...     print product.name
+    ...     print(product.name)
     mega-money-maker
 
 You can search for products based on the date when
@@ -334,7 +334,7 @@ their commercial subscription was modified.
     ...     search_text='bzr',
     ...     subscription_modified_after=date_last_modified,
     ...     subscription_modified_before=date_last_modified):
-    ...     print product.name
+    ...     print(product.name)
     bzr
 
 All the products are returned when no parameters are passed in.
@@ -350,7 +350,7 @@ but a clause is included to search specifically for the name.
     >>> new_product = factory.makeProduct(name="abc.com")
     >>> for product in product_set.forReview(commercial_member,
     ...                                      search_text="abc.com"):
-    ...     print product.name
+    ...     print(product.name)
     abc.com
 
 The use of 'forReview' is limited to users with launchpad.Moderate.
diff --git a/lib/lp/registry/doc/distribution-mirror.txt b/lib/lp/registry/doc/distribution-mirror.txt
index 8dee6d7..77137d9 100644
--- a/lib/lp/registry/doc/distribution-mirror.txt
+++ b/lib/lp/registry/doc/distribution-mirror.txt
@@ -54,7 +54,7 @@ full functionality of Launchpad enabled:
     u'kubuntu'
     >>> poor_mirror = kubuntu.newMirror(
     ...     owner, speed, brazil, content, http_base_url=http_base_url)
-    >>> print poor_mirror
+    >>> print(poor_mirror)
     None
 
 The contents of a distribution mirror are represented by its associated
@@ -153,7 +153,7 @@ It's possible to retrieve a mirror by its name:
     >>> verifyObject(IDistributionMirror, example_mirror)
     True
 
-    >>> print mirrorset.getByName('non-existent-mirror')
+    >>> print(mirrorset.getByName('non-existent-mirror'))
     None
 
 Or by any of its URLs (HTTP, FTP or Rsync)
@@ -169,18 +169,18 @@ The getBy*Url methods return the corresponding mirrors:
     >>> http_mirror = mirrorset.getByHttpUrl(
     ...     'http://localhost:11375/valid-mirror')
 
-    >>> print mirrorset.getByHttpUrl('http://non-existent-url')
+    >>> print(mirrorset.getByHttpUrl('http://non-existent-url'))
     None
 
     >>> ftp_mirror = mirrorset.getByFtpUrl('ftp://localhost/example-ftp')
 
-    >>> print mirrorset.getByFtpUrl('ftp://non-existent-url')
+    >>> print(mirrorset.getByFtpUrl('ftp://non-existent-url'))
     None
 
     >>> rsync_mirror = mirrorset.getByRsyncUrl(
     ...     'rsync://localhost/example-rsync')
 
-    >>> print mirrorset.getByRsyncUrl('rsync://non-existent-url')
+    >>> print(mirrorset.getByRsyncUrl('rsync://non-existent-url'))
     None
 
 
@@ -303,7 +303,7 @@ probed as we don't care about it anyway.
     ...             last_probe_date = 'TODAY'
     ...         else:
     ...             last_probe_date = last_probe.date_created.isoformat()
-    ...     print mirror.name, last_probe_date
+    ...     print(mirror.name, last_probe_date)
     canonical-archive NEVER
     archive-404-mirror NEVER
     archive-mirror TODAY
@@ -317,7 +317,7 @@ probed as we don't care about it anyway.
     ...     last_probe_date = 'NEVER'
     ...     if last_probe is not None:
     ...         last_probe_date = last_probe.date_created.isoformat()
-    ...     print mirror.name, last_probe_date
+    ...     print(mirror.name, last_probe_date)
     canonical-archive NEVER
     archive-404-mirror NEVER
     archive-mirror2 2006-05-24...
@@ -356,7 +356,7 @@ up on the public mirror listings.
     'mark@xxxxxxxxxxx'
     >>> valid_mirror.enabled
     False
-    >>> print msg.get_payload()
+    >>> print(msg.get_payload())
     Dear mirror administrator,
     <BLANKLINE>
     This is an automated failure notice that has been generated by the mirror
@@ -499,7 +499,7 @@ config.distributionmirrorprober.releases_file_list_url option)
     ...     get_expected_cdimage_paths)
     >>> for (series, flavour, paths) in get_expected_cdimage_paths():
     ...     for path in paths:
-    ...         print series.name, flavour, path
+    ...         print(series.name, flavour, path)
     hoary kubuntu kubuntu/hoary/kubuntu-5.04-install-amd64.iso
     hoary kubuntu kubuntu/hoary/kubuntu-5.04-install-i386.iso
     hoary kubuntu kubuntu/hoary/kubuntu-5.04-install-powerpc.iso
@@ -647,9 +647,9 @@ is correct.
 
     >>> transaction.commit()
     >>> prober, stdout, stderr = run_prober('--content-type=archive')
-    >>> print stdout
+    >>> print(stdout)
     <BLANKLINE>
-    >>> print stderr
+    >>> print(stderr)
     INFO    Creating lockfile: /var/lock/launchpad-distributionmirror-prober.lock
     INFO    Probing Archive Mirrors
     INFO    Probed 5 mirrors.
@@ -662,9 +662,9 @@ is correct.
     <BLANKLINE>
 
     >>> prober, stdout, stderr = run_prober('--content-type=cdimage')
-    >>> print stdout
+    >>> print(stdout)
     <BLANKLINE>
-    >>> print stderr
+    >>> print(stderr)
     INFO    Creating lockfile: /var/lock/launchpad-distributionmirror-prober.lock
     INFO    Probing CD Image Mirrors
     INFO    Probed 4 mirrors.
@@ -679,9 +679,9 @@ that the mirrors were probed recently, and, by default, don't need to be
 probed again.
 
     >>> prober, stdout, stderr = run_prober('--content-type=cdimage')
-    >>> print stdout
+    >>> print(stdout)
     <BLANKLINE>
-    >>> print stderr
+    >>> print(stderr)
     INFO    Creating lockfile: /var/lock/launchpad-distributionmirror-prober.lock
     INFO    Probing CD Image Mirrors
     INFO    No mirrors to probe.
@@ -692,9 +692,9 @@ But we can override the default behaviour and tell the prober to check
 all official mirrors independently if they were probed recently or not.
 
     >>> prober, stdout, stderr = run_prober('--content-type=cdimage --force')
-    >>> print stdout
+    >>> print(stdout)
     <BLANKLINE>
-    >>> print stderr
+    >>> print(stderr)
     INFO    Creating lockfile: /var/lock/launchpad-distributionmirror-prober.lock
     INFO    Probing CD Image Mirrors
     INFO    Probed 4 mirrors.
@@ -714,7 +714,7 @@ we'll enable them again.
     >>> cdimage_mirror.enabled = False
     >>> transaction.commit()
     >>> prober, stdout, stderr = run_prober('--content-type=cdimage --force')
-    >>> print stderr
+    >>> print(stderr)
     INFO    Creating lockfile: /var/lock/launchpad-distributionmirror-prober.lock
     INFO    Probing CD Image Mirrors
     INFO    Probed 4 mirrors.
@@ -752,15 +752,15 @@ First, let's check the source and arch series of one archive mirror.
     # We only have a few publishing records, so most of the cdimage mirrors
     # will have Unknown as their freshness.
     >>> for mirror_arch_series in mirror_arch_series:
-    ...     print (mirror_arch_series.distro_arch_series.displayname,
-    ...            mirror_arch_series.freshness.title)
+    ...     print((mirror_arch_series.distro_arch_series.displayname,
+    ...            mirror_arch_series.freshness.title))
     (u'Ubuntu Warty i386', 'Up to date')
 
     >>> mirror_source_series = (
     ...     archive_mirror.getSummarizedMirroredSourceSeries())
     >>> for mirror_source_series in mirror_source_series:
-    ...     print (mirror_source_series.distroseries.displayname,
-    ...            mirror_source_series.freshness.title)
+    ...     print((mirror_source_series.distroseries.displayname,
+    ...            mirror_source_series.freshness.title))
     (u'Warty', 'Up to date')
     (u'Hoary', 'Up to date')
     (u'Breezy Badger Autotest', 'Up to date')
@@ -781,8 +781,8 @@ apt has supported HTTP redirects since Ubuntu 9.04, so mirrors that redirect are
     # We only have a few publishing records, so most of the cdimage mirrors
     # will have Unknown as their freshness.
     >>> for mirror_arch_series in mirror_arch_series:
-    ...     print (mirror_arch_series.distro_arch_series.displayname,
-    ...            mirror_arch_series.freshness.title)
+    ...     print((mirror_arch_series.distro_arch_series.displayname,
+    ...            mirror_arch_series.freshness.title))
     (u'Ubuntu Warty i386', 'Up to date')
 
 
@@ -842,7 +842,7 @@ the possible mirror speeds.
   ...     a = MockMirror()
   ...     a.speed = speed
   ...     mirrors.append(a)
-  >>> print view._sum_throughput(mirrors)
+  >>> print(view._sum_throughput(mirrors))
   37 Gbps
 
 
@@ -859,7 +859,7 @@ The mirror owner can change the owner to another user.
 
     >>> ignored = login_person(mirror.owner)
     >>> mirror.owner = new_owner
-    >>> print mirror.owner.name
+    >>> print(mirror.owner.name)
     bear
 
 
@@ -946,20 +946,20 @@ There cannot be multiple country mirrors of one type for one country:
     >>> login('karl@xxxxxxxxxxxxx')
     >>> proberecord = factory.makeMirrorProbeRecord(davis_station_archive)
 
-    >>> print davis_station_archive.content.name
+    >>> print(davis_station_archive.content.name)
     ARCHIVE
-    >>> print davis_station_archive.country_dns_mirror
+    >>> print(davis_station_archive.country_dns_mirror)
     False
-    >>> print davis_station_archive.country.name
+    >>> print(davis_station_archive.country.name)
     Antarctica
 
     >>> archive_mirror2 = getUtility(IDistributionMirrorSet).getByName(
     ...     'archive-mirror2')
-    >>> print archive_mirror2.content.name
+    >>> print(archive_mirror2.content.name)
     ARCHIVE
-    >>> print archive_mirror2.country_dns_mirror
+    >>> print(archive_mirror2.country_dns_mirror)
     False
-    >>> print archive_mirror2.country.name
+    >>> print(archive_mirror2.country.name)
     Antarctica
 
     >>> davis_station_archive.status = MirrorStatus.OFFICIAL
@@ -993,7 +993,7 @@ country mirrors:
     ...     ftp_url="ftp://ubuntu.osuosl.org/pub/ubuntu/";,
     ...     official_candidate=True)
     >>> osuosl_mirror.status = MirrorStatus.OFFICIAL
-    >>> print osuosl_mirror.http_base_url
+    >>> print(osuosl_mirror.http_base_url)
     None
 
     >>> osuosl_mirror.canTransitionToCountryMirror()
diff --git a/lib/lp/registry/doc/distribution-sourcepackage.txt b/lib/lp/registry/doc/distribution-sourcepackage.txt
index 249d582..e747f5d 100644
--- a/lib/lp/registry/doc/distribution-sourcepackage.txt
+++ b/lib/lp/registry/doc/distribution-sourcepackage.txt
@@ -38,16 +38,16 @@ Descriptive attributes
 A distribution source package has a name, displayname, title, and a summary.
 
     >>> dsp = ubuntu.getSourcePackage("pmount")
-    >>> print dsp.name
+    >>> print(dsp.name)
     pmount
 
-    >>> print dsp.displayname
+    >>> print(dsp.displayname)
     pmount in Ubuntu
 
     >>> print(dsp.title)
     pmount package in Ubuntu
 
-    >>> print dsp.summary
+    >>> print(dsp.summary)
     pmount: pmount shortdesc
 
 
@@ -57,18 +57,18 @@ Publishing-related properties
 Publishing history of 'pmount in Ubuntu':
 
     >>> for p in dsp.publishing_history:
-    ...     print " ".join((p.sourcepackagerelease.name,
+    ...     print(" ".join((p.sourcepackagerelease.name,
     ...                     p.sourcepackagerelease.version,
-    ...                     p.distroseries.name))
+    ...                     p.distroseries.name)))
     pmount 0.1-2 hoary
     pmount 0.1-1 hoary
 
 Current publishing records for 'pmount in Ubuntu':
 
     >>> for p in dsp.current_publishing_records:
-    ...     print " ".join((p.sourcepackagerelease.name,
+    ...     print(" ".join((p.sourcepackagerelease.name,
     ...                     p.sourcepackagerelease.version,
-    ...                     p.distroseries.name))
+    ...                     p.distroseries.name)))
     pmount 0.1-2 hoary
 
 Current overall publications:
@@ -101,7 +101,7 @@ is 'main' and in the older distroseries it is 'universe'.
     ...     sourcename='compiz', version='0.01-1ubuntu1', distroseries=hoary,
     ...     status=PackagePublishingStatus.OBSOLETE, component='main')
     >>> compiz = ubuntu.getSourcePackage('compiz')
-    >>> print compiz.latest_overall_publication.component.name
+    >>> print(compiz.latest_overall_publication.component.name)
     universe
 
 When more than one published publication exists in a single distroseries, 
@@ -118,7 +118,7 @@ release.
     ...     status=PackagePublishingStatus.PUBLISHED, component='main',
     ...     pocket=PackagePublishingPocket.SECURITY)
     >>> firefox = ubuntu.getSourcePackage('firefox')
-    >>> print firefox.latest_overall_publication.pocket.name
+    >>> print(firefox.latest_overall_publication.pocket.name)
     SECURITY
 
 === Release-related properties ===
@@ -132,9 +132,9 @@ We can also get the releases of 'pmount in Ubuntu' along with the
 relevant publishing information:
 
     >>> for release, pubs in dsp.getReleasesAndPublishingHistory():
-    ...     print release.version
+    ...     print(release.version)
     ...     for pub in pubs:
-    ...         print ' * %s - %s' % (pub.distroseries.name, pub.status.name)
+    ...         print(' * %s - %s' % (pub.distroseries.name, pub.status.name))
     0.1-2
      * hoary - PUBLISHED
     0.1-1
@@ -166,7 +166,7 @@ for a DSP.
     ...     distroseries=hoary, sourcepackagename='pmount', name='tip',
     ...     owner=fred)
     >>> [branch] = list(dsp.getBranches())
-    >>> print branch.unique_name
+    >>> print(branch.unique_name)
     ~fred/ubuntu/hoary/pmount/tip
 
 === Grabbing DSPRs ===
@@ -186,11 +186,11 @@ getVersion():
     True
 
     >>> pmount_dspr = dsp.getVersion('0.1-1')
-    >>> print pmount_dspr.title
+    >>> print(pmount_dspr.title)
     pmount 0.1-1 source package in Ubuntu
 
     >>> for pub in pmount_dspr.publishing_history:
-    ...     print pub.distroseries.name, pub.status.name
+    ...     print(pub.distroseries.name, pub.status.name)
     hoary SUPERSEDED
 
 'getVersion' also returns IDSPRs for REMOVED versions which allows
@@ -200,12 +200,12 @@ archive (bug #60440):
     >>> ubuntutest = getUtility(IDistributionSet)["ubuntutest"]
     >>> alsa_dsp = ubuntutest.getSourcePackage("alsa-utils")
     >>> alsa_dspr = alsa_dsp.getVersion('1.0.9a-4')
-    >>> print alsa_dspr.title
+    >>> print(alsa_dspr.title)
     alsa-utils 1.0.9a-4 source package in ubuntutest
 
     >>> for pub in alsa_dspr.publishing_history:
     ...     is_removed = pub.dateremoved is not None
-    ...     print pub.distroseries.name, pub.status.name, is_removed
+    ...     print(pub.distroseries.name, pub.status.name, is_removed)
     breezy-autotest DELETED True
 
 == __hash__ ==
@@ -242,13 +242,13 @@ retrieve a DistributionSourcePackage's upstream product using its
 upstream_product property.
 
     >>> firefox = ubuntu.getSourcePackage('mozilla-firefox')
-    >>> print firefox.upstream_product.displayname
+    >>> print(firefox.upstream_product.displayname)
     Mozilla Firefox
 
 If the package isn't linked to an upstream product, upstream_product
 will be None.
 
-    >>> print pmount.upstream_product
+    >>> print(pmount.upstream_product)
     None
 
 == Finding archives where this package is published ==
@@ -301,7 +301,7 @@ the package created by the person with the greatest karma is first:
     >>> gedit_src = ubuntu_test.getSourcePackage('gedit')
     >>> ppa_versions_for_gedit = gedit_src.findRelatedArchives()
     >>> for ppa in ppa_versions_for_gedit:
-    ...     print ppa.displayname
+    ...     print(ppa.displayname)
     PPA named nightly for Person...
     PPA named beta for Person...
 
@@ -311,7 +311,7 @@ if you want to find all *other* related archives:
     >>> ppa_versions_for_gedit = gedit_src.findRelatedArchives(
     ...     exclude_archive=ppa_nightly)
     >>> for ppa in ppa_versions_for_gedit:
-    ...     print ppa.displayname
+    ...     print(ppa.displayname)
     PPA named beta for Person...
 
 Although findRelatedArchives() defaults to PPAs, it can be used to find
@@ -320,7 +320,7 @@ packages in other archives too:
     >>> archive_versions_for_gedit = gedit_src.findRelatedArchives(
     ...     archive_purpose=None)
     >>> for archive in archive_versions_for_gedit:
-    ...     print archive.displayname
+    ...     print(archive.displayname)
     Primary Archive for Ubuntu Test
     PPA named nightly for Person...
     PPA named beta for Person...
diff --git a/lib/lp/registry/doc/distribution.txt b/lib/lp/registry/doc/distribution.txt
index 0c6b903..a411f4b 100644
--- a/lib/lp/registry/doc/distribution.txt
+++ b/lib/lp/registry/doc/distribution.txt
@@ -25,7 +25,7 @@ The IDistributionSet utility is accessed in the usual fashion:
 To retrieve a specific distribution, use IDistributionSet.get:
 
     >>> ubuntu = distroset.get(1)
-    >>> print ubuntu.name
+    >>> print(ubuntu.name)
     ubuntu
 
 The distribution has a useful string representation containing its display
@@ -77,7 +77,7 @@ have a SourcePackageName object for it.
 
     >>> evo = SourcePackageName.byName("evolution")
     >>> evo_ubuntu = ubuntu.getSourcePackage(evo)
-    >>> print evo_ubuntu.name
+    >>> print(evo_ubuntu.name)
     evolution
 
     >>> IDistributionSourcePackage.providedBy(evo_ubuntu)
@@ -98,26 +98,26 @@ have a SourcePackageName object for it.
 You can also get a release by name:
 
     >>> hoary = ubuntu.getSeries("hoary")
-    >>> print hoary.name
+    >>> print(hoary.name)
     hoary
 
 Or by version:
 
     >>> v504 = ubuntu.getSeries("5.04")
-    >>> print v504.name
+    >>> print(v504.name)
     hoary
 
 You can list development distroseriess:
 
     >>> devdists = ubuntu.getDevelopmentSeries()
     >>> for devdist in devdists:
-    ...     print devdist.name
+    ...     print(devdist.name)
     hoary
 
 You can list the series for a distribution,
 
     >>> for series in ubuntu.series:
-    ...     print series.name
+    ...     print(series.name)
     breezy-autotest
     grumpy
     hoary
@@ -126,7 +126,7 @@ You can list the series for a distribution,
 as well as the distribution architecture series for a distribution:
 
     >>> for architecture in ubuntu.architectures:
-    ...     print architecture.displayname
+    ...     print(architecture.displayname)
     Ubuntu Breezy Badger Autotest i386
     Ubuntu Hoary hppa
     Ubuntu Hoary i386
@@ -161,7 +161,7 @@ If you ask for all the distributions in the DistributionSet you should get
 Ubuntu (and all flavours of it) first and the rest alphabetically:
 
     >>> for item in distroset.getDistros():
-    ...     print item.name
+    ...     print(item.name)
     ubuntu
     kubuntu
     ubuntutest
@@ -184,23 +184,23 @@ a certain string through the magic of fti. For instance:
 
     >>> packages = ubuntu.searchSourcePackageCaches(u"mozilla")
     >>> for distro_source_package_cache, source_name, rank in packages:
-    ...     print "%-17s rank:%s" % (
+    ...     print("%-17s rank:%s" % (
     ...         distro_source_package_cache.name,
-    ...         type(rank))
+    ...         type(rank)))
     mozilla-firefox   rank:<type 'float'>
 
 The search also matches on exact package names which fti doesn't like,
 and even on substrings:
 
     >>> packages = ubuntu.searchSourcePackageCaches(u"linux-source-2.6.15")
-    >>> print packages.count()
+    >>> print(packages.count())
     1
     >>> packages = ubuntu.searchSourcePackageCaches(u'a')
     >>> for distro_source_package_cache, source_name, rank in packages:
-    ...     print "%s: %-17s rank:%s" % (
+    ...     print("%s: %-17s rank:%s" % (
     ...         distro_source_package_cache.__class__.__name__,
     ...         distro_source_package_cache.name,
-    ...         type(rank))
+    ...         type(rank)))
     DistributionSourcePackageCache: alsa-utils        rank:<type 'NoneType'>
     DistributionSourcePackageCache: commercialpackage rank:<type 'NoneType'>
     DistributionSourcePackageCache: foobar            rank:<type 'NoneType'>
@@ -212,7 +212,7 @@ of the results from searchSourcePackageCaches():
 
     >>> packages = ubuntu.searchSourcePackages(u'a')
     >>> for dsp in packages:
-    ...     print "%s: %s" % (dsp.__class__.__name__, dsp.name)
+    ...     print("%s: %s" % (dsp.__class__.__name__, dsp.name))
     DistributionSourcePackage: alsa-utils
     DistributionSourcePackage: commercialpackage
     DistributionSourcePackage: foobar
@@ -226,13 +226,13 @@ in the Packaging table linking it to an upstream project.
 
     >>> packages = ubuntu.searchSourcePackages(u'a', has_packaging=True)
     >>> for dsp in packages:
-    ...     print "%s: %s" % (dsp.__class__.__name__, dsp.name)
+    ...     print("%s: %s" % (dsp.__class__.__name__, dsp.name))
     DistributionSourcePackage: alsa-utils
     DistributionSourcePackage: mozilla-firefox
     DistributionSourcePackage: netapplet
     >>> packages = ubuntu.searchSourcePackages(u'a', has_packaging=False)
     >>> for dsp in packages:
-    ...     print "%s: %s" % (dsp.__class__.__name__, dsp.name)
+    ...     print("%s: %s" % (dsp.__class__.__name__, dsp.name))
     DistributionSourcePackage: commercialpackage
     DistributionSourcePackage: foobar
 
@@ -244,7 +244,7 @@ SourcePackagePublishingHistory table for the given distroseries.
     >>> packages = ubuntu.searchSourcePackages(
     ...     u'a', publishing_distroseries=ubuntu.currentseries)
     >>> for dsp in packages:
-    ...     print "%s: %s" % (dsp.__class__.__name__, dsp.name)
+    ...     print("%s: %s" % (dsp.__class__.__name__, dsp.name))
     DistributionSourcePackage: alsa-utils
     DistributionSourcePackage: netapplet
 
@@ -262,7 +262,7 @@ expected results:
 
     >>> results = ubuntu.searchBinaryPackages(
     ...     u"mozilla-firefox", exact_match=True)
-    >>> print [result.name for result in results]
+    >>> print([result.name for result in results])
     [u'mozilla-firefox']
 
 An exact match search with no matches on any package name returns
@@ -275,12 +275,12 @@ an empty result set:
 Loosening to substring matches gives another result:
 
     >>> results = ubuntu.searchBinaryPackages(u"mozilla", exact_match=False)
-    >>> print results[0]
+    >>> print(results[0])
     <...DistributionSourcePackageCache instance ...
 
-    >>> print [result.name for result in results]
+    >>> print([result.name for result in results])
     [u'mozilla-firefox']
-    >>> print [result.binpkgnames for result in results]
+    >>> print([result.binpkgnames for result in results])
     [u'mozilla-firefox mozilla-firefox-data']
 
 The results of searchBinaryPackages() are simply ordered alphabetically
@@ -288,7 +288,7 @@ for the moment until we have a better FTI rank to order with.
 
     >>> results = ubuntu.searchBinaryPackages(u"m")
     >>> for result in results:
-    ...     print result.name
+    ...     print(result.name)
     mozilla-firefox
     pmount
 
@@ -312,24 +312,24 @@ If we ask for a totally unknown distroseries, we raise NotFoundError
 If we ask for a plain distroseries, it should come back with the RELEASE
 pocket as the pocket.
     >>> dr, pocket = ubuntu.getDistroSeriesAndPocket('hoary')
-    >>> print dr.name
+    >>> print(dr.name)
     hoary
-    >>> print pocket.name
+    >>> print(pocket.name)
     RELEASE
 
 If we ask for a security pocket in a known distroseries it should come out
 on the other side.
     >>> dr, pocket = ubuntu.getDistroSeriesAndPocket('hoary-security')
-    >>> print dr.name
+    >>> print(dr.name)
     hoary
-    >>> print pocket.name
+    >>> print(pocket.name)
     SECURITY
 
 Find the backports pocket, too:
     >>> dr, pocket = ubuntu.getDistroSeriesAndPocket('hoary-backports')
-    >>> print dr.name
+    >>> print(dr.name)
     hoary
-    >>> print pocket.name
+    >>> print(pocket.name)
     BACKPORTS
 
 If we ask for a valid distroseries which doesn't have a given pocket it should
@@ -352,8 +352,8 @@ what component is uploadable to by what person or group of people.
     >>> for permission in sorted(
     ...     ubuntu.uploaders, key=attrgetter("id")):
     ...     assert not permission.archive.is_ppa
-    ...     print permission.component.name
-    ...     print permission.person.displayname
+    ...     print(permission.component.name)
+    ...     print(permission.person.displayname)
     universe
     Ubuntu Team
     restricted
@@ -375,27 +375,27 @@ officially. Ubuntu uses all of them:
     >>> ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
     >>> ubuntu.official_malone
     True
-    >>> print ubuntu.answers_usage.name
+    >>> print(ubuntu.answers_usage.name)
     LAUNCHPAD
-    >>> print ubuntu.blueprints_usage.name
+    >>> print(ubuntu.blueprints_usage.name)
     LAUNCHPAD
-    >>> print ubuntu.translations_usage.name
+    >>> print(ubuntu.translations_usage.name)
     LAUNCHPAD
 
 The bug_tracking_usage property currently only tracks official_malone.
 
-    >>> print ubuntu.bug_tracking_usage.name
+    >>> print(ubuntu.bug_tracking_usage.name)
     LAUNCHPAD
 
 While the other attributes track the other official_ attributes.
 
-    >>> print ubuntu.official_answers
+    >>> print(ubuntu.official_answers)
     True
-    >>> print ubuntu.answers_usage.name
+    >>> print(ubuntu.answers_usage.name)
     LAUNCHPAD
-    >>> print ubuntu.official_blueprints
+    >>> print(ubuntu.official_blueprints)
     True
-    >>> print ubuntu.blueprints_usage.name
+    >>> print(ubuntu.blueprints_usage.name)
     LAUNCHPAD
 
 If the official_ attributes are False and the enum hasn't been set,
@@ -403,14 +403,14 @@ the usage enums don't know anything.
 
     >>> ignored = login_person(ubuntu.owner.teamowner)
     >>> ubuntu.official_answers = False
-    >>> print ubuntu.answers_usage.name
+    >>> print(ubuntu.answers_usage.name)
     UNKNOWN
 
 A distribution *cannot* specify that it uses codehosting. Currently there's
 no way for a distribution to use codehosting.
 
     >>> from lp.app.enums import ServiceUsage
-    >>> print ubuntu.codehosting_usage.name
+    >>> print(ubuntu.codehosting_usage.name)
     NOT_APPLICABLE
     >>> ubuntu.codehosting_usage = ServiceUsage.LAUNCHPAD
     Traceback (most recent call last):
@@ -419,24 +419,24 @@ no way for a distribution to use codehosting.
 While Debian uses none:
 
     >>> debian = getUtility(ILaunchpadCelebrities).debian
-    >>> print debian.bug_tracking_usage.name
+    >>> print(debian.bug_tracking_usage.name)
     UNKNOWN
-    >>> print debian.translations_usage.name
+    >>> print(debian.translations_usage.name)
     UNKNOWN
-    >>> print debian.answers_usage.name
+    >>> print(debian.answers_usage.name)
     UNKNOWN
-    >>> print debian.codehosting_usage.name
+    >>> print(debian.codehosting_usage.name)
     NOT_APPLICABLE
-    >>> print debian.blueprints_usage.name
+    >>> print(debian.blueprints_usage.name)
     UNKNOWN
 
 Gentoo only uses Malone
 
-    >>> print gentoo.bug_tracking_usage.name
+    >>> print(gentoo.bug_tracking_usage.name)
     LAUNCHPAD
-    >>> print gentoo.translations_usage.name
+    >>> print(gentoo.translations_usage.name)
     UNKNOWN
-    >>> print gentoo.answers_usage.name
+    >>> print(gentoo.answers_usage.name)
     UNKNOWN
 
 Launchpad admins and the distro owner can set these fields.
@@ -445,7 +445,7 @@ Launchpad admins and the distro owner can set these fields.
     >>> login('mark@xxxxxxxxxxx')
     >>> debian = getUtility(ILaunchpadCelebrities).debian
     >>> debian.blueprints_usage = ServiceUsage.LAUNCHPAD
-    >>> print debian.blueprints_usage.name
+    >>> print(debian.blueprints_usage.name)
     LAUNCHPAD
     >>> debian.official_malone = True
     >>> debian.official_malone
@@ -458,7 +458,7 @@ Launchpad admins and the distro owner can set these fields.
     >>> debian.owner = debian_owner
     >>> ignored = login_person(debian_owner)
     >>> debian.blueprints_usage = ServiceUsage.NOT_APPLICABLE
-    >>> print debian.blueprints_usage.name
+    >>> print(debian.blueprints_usage.name)
     NOT_APPLICABLE
 
 But others can't.
@@ -507,7 +507,7 @@ There are 2 completed specs for Kubuntu:
 
     >>> filter = [SpecificationFilter.COMPLETE]
     >>> for spec in kubuntu.specifications(None, filter=filter):
-    ...    print spec.name, spec.is_complete
+    ...    print(spec.name, spec.is_complete)
     thinclient-local-devices True
     usplash-on-hibernation True
 
@@ -516,7 +516,7 @@ And there are four incomplete specs:
 
     >>> filter = [SpecificationFilter.INCOMPLETE]
     >>> for spec in kubuntu.specifications(None, filter=filter):
-    ...    print spec.name, spec.is_complete
+    ...    print(spec.name, spec.is_complete)
     cluster-installation False
     revu False
     kde-desktopfile-langpacks False
@@ -527,7 +527,7 @@ If we ask for all specs, we get them in the order of priority.
 
     >>> filter = [SpecificationFilter.ALL]
     >>> for spec in kubuntu.specifications(None, filter=filter):
-    ...    print spec.priority.title, spec.name
+    ...    print(spec.priority.title, spec.name)
     Essential cluster-installation
     High revu
     Medium thinclient-local-devices
@@ -539,7 +539,7 @@ If we ask for all specs, we get them in the order of priority.
 And if we ask just for specs, we get the incomplete ones.
 
     >>> for spec in kubuntu.specifications(None):
-    ...     print spec.name, spec.is_complete
+    ...     print(spec.name, spec.is_complete)
     cluster-installation False
     revu False
     kde-desktopfile-langpacks False
@@ -548,7 +548,7 @@ And if we ask just for specs, we get the incomplete ones.
 We can filter for specifications that contain specific text:
 
     >>> for spec in kubuntu.specifications(None, filter=[u'package']):
-    ...     print spec.name
+    ...     print(spec.name)
     revu
 
 We can get only valid specs (those that are not obsolete or superseded):
@@ -568,7 +568,7 @@ We can get only valid specs (those that are not obsolete or superseded):
     ...             SpecificationDefinitionStatus.SUPERSEDED)
     ...     shim = spec.updateLifecycleStatus(owner)
     >>> for spec in kubuntu.valid_specifications():
-    ...     print spec.name
+    ...     print(spec.name)
     kde-desktopfile-langpacks
 
 
@@ -624,8 +624,8 @@ A distribution archive (primary, partner, debug or copy) can be retrieved
 by name using IDistribution.getArchive.
 
     >>> def display_archive(archive):
-    ...     print '%s %s %s' % (
-    ...         archive.distribution.name, archive.owner.name, archive.name)
+    ...     print('%s %s %s' % (
+    ...         archive.distribution.name, archive.owner.name, archive.name))
     >>> display_archive(ubuntu.getArchive('primary'))
     ubuntu ubuntu-team primary
     >>> display_archive(ubuntu.getArchive('partner'))
diff --git a/lib/lp/registry/doc/distroseries.txt b/lib/lp/registry/doc/distroseries.txt
index a7deb34..735d7ef 100644
--- a/lib/lp/registry/doc/distroseries.txt
+++ b/lib/lp/registry/doc/distroseries.txt
@@ -33,9 +33,9 @@ The IDistroSeriesSet utility is accessed in the usual fashion:
 To retrieve a specific release of a distribution, use IDistroSeriesSet.get:
 
     >>> warty = distroseriesset.get(1)
-    >>> print warty.name
+    >>> print(warty.name)
     warty
-    >>> print warty.fullseriesname
+    >>> print(warty.fullseriesname)
     Ubuntu Warty
 
 To get one specific release by name, use queryByName:
@@ -45,14 +45,14 @@ To get one specific release by name, use queryByName:
     >>> warty = distroseriesset.queryByName(ubuntu, "warty")
     >>> warty.name
     u'warty'
-    >>> print distroseriesset.queryByName(ubuntu, "foobar")
+    >>> print(distroseriesset.queryByName(ubuntu, "foobar"))
     None
 
 Or IDistroSeriesSet.queryByVersion:
 
-    >>> print distroseriesset.queryByVersion(ubuntu, "5.04").name
+    >>> print(distroseriesset.queryByVersion(ubuntu, "5.04").name)
     hoary
-    >>> print distroseriesset.queryByVersion(ubuntu, "5.05")
+    >>> print(distroseriesset.queryByVersion(ubuntu, "5.05"))
     None
 
 queryByName works on series aliases too if follow_aliases is True.
@@ -60,10 +60,10 @@ queryByName works on series aliases too if follow_aliases is True.
     >>> ignored = login_person(ubuntu.owner.activemembers[0])
     >>> ubuntu.development_series_alias = "devel"
     >>> login(ANONYMOUS)
-    >>> print distroseriesset.queryByName(ubuntu, "devel")
+    >>> print(distroseriesset.queryByName(ubuntu, "devel"))
     None
-    >>> print distroseriesset.queryByName(
-    ...     ubuntu, "devel", follow_aliases=True).name
+    >>> print(distroseriesset.queryByName(
+    ...     ubuntu, "devel", follow_aliases=True).name)
     hoary
 
 We verify that a distroseries does in fact fully provide IDistroSeries:
@@ -98,17 +98,17 @@ Distroseries identifying attributes
 A distroseries has a set of attributes that identify it. The launchpad id is
 the name attribute.
 
-    >>> print warty.name
+    >>> print(warty.name)
     warty
 
 It has a title for heading and titles...
 
-    >>> print warty.title
+    >>> print(warty.title)
     The Warty Warthog Release
 
 And a display_name for referring to it in a sentence.
 
-    >>> print warty.display_name
+    >>> print(warty.display_name)
     Warty
 
 The fullseriesname attribute is used when the context of the series name
@@ -116,18 +116,18 @@ can be confused. Note that the value is created from the launchpad id names
 of the distribution and the series, though it may look like the display_name
 attributes were used.
 
-    >>> print warty.fullseriesname
+    >>> print(warty.fullseriesname)
     Ubuntu Warty
 
 The version attribute holds the debversion of the series.
 
-    >>> print warty.version
+    >>> print(warty.version)
     4.10
 
 The named_version attribute is used is used to present the series display_name
 and version values consistently.
 
-    >>> print warty.named_version
+    >>> print(warty.named_version)
     Warty (4.10)
 
 
@@ -204,7 +204,7 @@ through fti, and even for substrings:
     1
     >>> pkgs = warty.searchPackages(u'a')
     >>> for dsbp in pkgs:
-    ...     print "%s: %s" % (dsbp.__class__.__name__, dsbp.name)
+    ...     print("%s: %s" % (dsbp.__class__.__name__, dsbp.name))
     DistroSeriesBinaryPackage: foobar
     DistroSeriesBinaryPackage: mozilla-firefox
     DistroSeriesBinaryPackage: at
@@ -219,11 +219,11 @@ other things) the uploader for validating incoming uploads.
 
     >>> hoary = distroseriesset.get(3)
     >>> for c in hoary.components:
-    ...     print c.name
+    ...     print(c.name)
     main
     restricted
     >>> for s in hoary.sections:
-    ...     print s.name
+    ...     print(s.name)
     base
     web
     editors
@@ -238,12 +238,12 @@ other things) the uploader for validating incoming uploads.
     >>> hoary.addSection(python)
 
     >>> for c in hoary.components:
-    ...     print c.name
+    ...     print(c.name)
     main
     restricted
 
     >>> for s in hoary.sections:
-    ...     print s.name
+    ...     print(s.name)
     base
     web
     editors
@@ -257,7 +257,7 @@ Breezy-autotest has got a partner component, which is not reported:
     >>> breezyautotest = distroseriesset.queryByName(
     ...     ubuntu, "breezy-autotest")
     >>> for c in breezyautotest.components:
-    ...     print c.name
+    ...     print(c.name)
     main
     restricted
     universe
@@ -267,7 +267,7 @@ The upload_components property, however, reports all the available
 components since partner is allowed for upload:
 
     >>> for c in breezyautotest.upload_components:
-    ...     print c.name
+    ...     print(c.name)
     main
     restricted
     universe
@@ -358,7 +358,7 @@ getBinariesForSeries() should be inherited from parent release.
     3
 
     >>> for bin in bumpy_firefox_sp.currentrelease.getBinariesForSeries(bumpy):
-    ...     print bin.id, bin.title, bin.build.distro_arch_series.title
+    ...     print(bin.id, bin.title, bin.build.distro_arch_series.title)
     27 mozilla-firefox-data-0.9 The Warty Warthog Release for i386 (386)
     26 mozilla-firefox-0.9 The Warty Warthog Release for hppa (hppa)
     12 mozilla-firefox-0.9 The Warty Warthog Release for i386 (386)
@@ -366,7 +366,7 @@ getBinariesForSeries() should be inherited from parent release.
 The new series also has the same packaging links as its parent series.
 
     >>> for packaging in warty.packagings:
-    ...     print packaging.sourcepackagename.name
+    ...     print(packaging.sourcepackagename.name)
     a52dec
     alsa-utils
     evolution
@@ -374,7 +374,7 @@ The new series also has the same packaging links as its parent series.
     netapplet
 
     >>> for packaging in bumpy.packagings:
-    ...     print packaging.sourcepackagename.name
+    ...     print(packaging.sourcepackagename.name)
     a52dec
     alsa-utils
     evolution
@@ -390,7 +390,7 @@ distribution release:
 
     >>> translatables = hoary.getTranslatableSourcePackages()
     >>> for translatable in translatables:
-    ...    print translatable.name
+    ...    print(translatable.name)
     evolution
     mozilla
     pmount
@@ -408,8 +408,8 @@ packagings property:
 
     >>> packagings = hoary.packagings
     >>> for packaging in packagings:
-    ...     print packaging.sourcepackagename.name, \
-    ...           packaging.productseries.product.displayname
+    ...     print(packaging.sourcepackagename.name,
+    ...           packaging.productseries.product.displayname)
     evolution Evolution
     mozilla-firefox Mozilla Firefox
     netapplet NetApplet
@@ -428,9 +428,9 @@ translations, and code. Each item in the list is a dict with the 'package',
 total_bugs, and total_messages (translatable messages).
 
     >>> for summary in hoary.getPrioritizedUnlinkedSourcePackages():
-    ...     print  summary['package'].name
+    ...     print(summary['package'].name)
     ...     naked_summary = removeSecurityProxy(summary)
-    ...     print '%(bug_count)s %(total_messages)s' % naked_summary
+    ...     print('%(bug_count)s %(total_messages)s' % naked_summary)
     pmount  0  64
     alsa-utils  0  0
     cnews  0  0
@@ -443,7 +443,7 @@ list of `IPackaging` that need more information about the upstream project to
 share bugs, translations, and code.
 
     >>> for packaging in hoary.getPrioritizedPackagings():
-    ...     print packaging.sourcepackagename.name
+    ...     print(packaging.sourcepackagename.name)
     netapplet
     evolution
 
@@ -458,7 +458,7 @@ upstream.
     >>> distribution = factory.makeDistribution()
     >>> distroseries = factory.makeDistroSeries(distribution=distribution)
     >>> pkgs = distroseries.getMostRecentlyLinkedPackagings()
-    >>> print pkgs.count()
+    >>> print(pkgs.count())
     0
 
     >>> for name in ['aaron', 'bjorn', 'chex', 'deryck', 'edwin', 'francis']:
@@ -473,7 +473,7 @@ upstream.
 
     >>> pkgs = distroseries.getMostRecentlyLinkedPackagings()
     >>> for packaging in pkgs:
-    ...     print packaging.sourcepackagename.name
+    ...     print(packaging.sourcepackagename.name)
     francis
     edwin
     deryck
@@ -504,7 +504,7 @@ the future.
     >>> for name in sorted(set(
     ...         pkgpub.sourcepackagerelease.sourcepackagename.name
     ...         for pkgpub in spphs)):
-    ...     print name
+    ...     print(name)
     alsa-utils
     evolution
     libstdc++
@@ -598,12 +598,12 @@ and in the main archives for this distroseries:
     ...     print(
     ...         source.sourcepackagerelease.sourcepackagename.name,
     ...         source.sourcepackagerelease.version)
-    (u'netapplet', u'0.99.6-1')
-    (u'alsa-utils', u'1.0.8-1ubuntu1')
-    (u'alsa-utils', u'1.0.9a-4')
-    (u'mozilla-firefox', u'0.9')
-    (u'cdrkit', u'1.0')
-    (u'iceweasel', u'1.0')
+    netapplet 0.99.6-1
+    alsa-utils 1.0.8-1ubuntu1
+    alsa-utils 1.0.9a-4
+    mozilla-firefox 0.9
+    cdrkit 1.0
+    iceweasel 1.0
 
 Similarly for binary publications:
 
@@ -612,16 +612,16 @@ Similarly for binary publications:
     ...     print(
     ...         binary.binarypackagerelease.binarypackagename.name,
     ...         binary.binarypackagerelease.version)
-    (u'mozilla-firefox', u'0.9')
-    (u'pmount', u'0.1-1')
-    (u'linux-2.6.12', u'2.6.12.20')
-    (u'pmount', u'2:1.9-1')
-    (u'at', u'3.14156')
-    (u'cdrkit', u'1.0')
-    (u'mozilla-firefox', u'1.0')
-    (u'mozilla-firefox', u'0.9')
-    (u'mozilla-firefox-data', u'0.9')
-    (u'mozilla-firefox-data', u'0.9')
+    mozilla-firefox 0.9
+    pmount 0.1-1
+    linux-2.6.12 2.6.12.20
+    pmount 2:1.9-1
+    at 3.14156
+    cdrkit 1.0
+    mozilla-firefox 1.0
+    mozilla-firefox 0.9
+    mozilla-firefox-data 0.9
+    mozilla-firefox-data 0.9
 
 
 Creating DistroSeries
@@ -643,11 +643,11 @@ series' driver role so that they can edit it.
     ...     name='island', display_name='Island', title='YouBuntu Island',
     ...     summary='summary', description='description', version='09.07',
     ...     previous_series=warty, registrant=yo_driver)
-    >>> print yo_series.name
+    >>> print(yo_series.name)
     island
-    >>> print yo_series.registrant.name
+    >>> print(yo_series.registrant.name)
     yo-driver
-    >>> print yo_series.driver.name
+    >>> print(yo_series.driver.name)
     yo-driver
 
 Owners of derivative distributions, and admins can create series too, but
@@ -659,9 +659,9 @@ have permission to edit the series.
     ...     name='forest', display_name='Forest', title='YouBuntu Forest',
     ...     summary='summary', description='description', version='09.07',
     ...     previous_series=warty, registrant=youbuntu.owner)
-    >>> print yo_series.name
+    >>> print(yo_series.name)
     forest
-    >>> print yo_series.driver
+    >>> print(yo_series.driver)
     None
 
 Ubuntu uses Launchpad for package managemtn, so it requires special
@@ -688,11 +688,11 @@ series.
     ...     name='finch', display_name='Finch', title='Ubuntu Finch',
     ...     summary='summary', description='description', version='9.06',
     ...     previous_series=warty, registrant=ubuntu.owner)
-    >>> print u_series.name
+    >>> print(u_series.name)
     finch
-    >>> print u_series.registrant.name
+    >>> print(u_series.registrant.name)
     ubuntu-team
-    >>> print u_series.driver
+    >>> print(u_series.driver)
     None
 
 
@@ -721,7 +721,7 @@ There are 2 completed specs for Krunch:
 
     >>> filter = [SpecificationFilter.COMPLETE]
     >>> for spec in kubuntu.specifications(None, filter=filter):
-    ...    print spec.name, spec.is_complete
+    ...     print(spec.name, spec.is_complete)
     thinclient-local-devices True
     usplash-on-hibernation True
 
@@ -730,7 +730,7 @@ And there are 2 incomplete specs:
 
     >>> filter = [SpecificationFilter.INCOMPLETE]
     >>> for spec in krunch.specifications(None, filter=filter):
-    ...     print spec.name, spec.is_complete
+    ...     print(spec.name, spec.is_complete)
     cluster-installation False
     revu False
 
@@ -739,7 +739,7 @@ If we ask for all specs, we get them in the order of priority.
 
     >>> filter = [SpecificationFilter.ALL]
     >>> for spec in krunch.specifications(None, filter=filter):
-    ...    print spec.priority.title, spec.name
+    ...     print(spec.priority.title, spec.name)
     Essential cluster-installation
     High revu
     Medium thinclient-local-devices
@@ -752,7 +752,7 @@ With a distroseries, we can ask for ACCEPTED, PROPOSED and DECLINED specs:
 
     >>> filter=[SpecificationFilter.ACCEPTED]
     >>> for spec in krunch.specifications(None, filter=filter):
-    ...     print spec.name, spec.goalstatus.title
+    ...     print(spec.name, spec.goalstatus.title)
     cluster-installation Accepted
     revu Accepted
     thinclient-local-devices Accepted
@@ -760,12 +760,12 @@ With a distroseries, we can ask for ACCEPTED, PROPOSED and DECLINED specs:
 
     >>> filter=[SpecificationFilter.PROPOSED]
     >>> for spec in krunch.specifications(None, filter=filter):
-    ...     print spec.name, spec.goalstatus.title
+    ...     print(spec.name, spec.goalstatus.title)
     kde-desktopfile-langpacks Proposed
 
     >>> filter=[SpecificationFilter.DECLINED]
     >>> for spec in krunch.specifications(None, filter=filter):
-    ...     print spec.name, spec.goalstatus.title
+    ...     print(spec.name, spec.goalstatus.title)
     krunch-desktop-plan Declined
 
 
@@ -773,7 +773,7 @@ And if we ask just for specs, we get BOTH the incomplete and the complete
 ones that have been accepted.
 
     >>> for spec in krunch.specifications(None):
-    ...     print spec.name, spec.is_complete, spec.goalstatus.title
+    ...     print(spec.name, spec.is_complete, spec.goalstatus.title)
     cluster-installation False Accepted
     revu False Accepted
     thinclient-local-devices True Accepted
@@ -782,7 +782,7 @@ ones that have been accepted.
 We can filter for specifications that contain specific text:
 
     >>> for spec in krunch.specifications(None, filter=[u'usb']):
-    ...     print spec.name
+    ...     print(spec.name)
     thinclient-local-devices
 
 
@@ -815,7 +815,7 @@ drivers. Kubuntu should be a good example.
     >>> krunch.driver.name
     u'edgar'
     >>> for d in krunch.drivers:
-    ...     print d.name
+    ...     print(d.name)
     edgar
     jblack
 
@@ -824,15 +824,15 @@ Now, we look at a release where there is a driver on the release but not on
 the distribution.
 
     >>> debian = distroset.getByName('debian')
-    >>> print debian.driver
+    >>> print(debian.driver)
     None
-    >>> print debian.owner.name
+    >>> print(debian.owner.name)
     mark
     >>> sarge = debian.getSeries('sarge')
-    >>> print sarge.driver.name
+    >>> print(sarge.driver.name)
     jdub
     >>> for d in sarge.drivers:
-    ...     print d.name
+    ...     print(d.name)
     jdub
     mark
 
@@ -841,13 +841,13 @@ Now, a release where there is no driver on the release but there is a driver
 on the distribution.
 
     >>> redhat = distroset.getByName('redhat')
-    >>> print redhat.driver.name
+    >>> print(redhat.driver.name)
     jblack
     >>> six = redhat.getSeries('six')
-    >>> print six.driver
+    >>> print(six.driver)
     None
     >>> for d in six.drivers:
-    ...     print d.name
+    ...     print(d.name)
     jblack
 
 Finally, on a release where neither the distribution nor the release have a
@@ -855,17 +855,17 @@ driver. Here, we expect the driver to be the owner of the distribution
 (because this is the "commonest fallback").
 
     >>> sid = debian.getSeries('sid')
-    >>> print debian.driver
+    >>> print(debian.driver)
     None
-    >>> print debian.owner.name
+    >>> print(debian.owner.name)
     mark
-    >>> print sid.driver
+    >>> print(sid.driver)
     None
-    >>> print sid.registrant.name
+    >>> print(sid.registrant.name)
     jdub
 
     >>> for d in sid.drivers:
-    ...     print d.name
+    ...     print(d.name)
     mark
 
 
@@ -882,7 +882,7 @@ uploaded and published in its context.
 Each element is an IDistributionSourcePackageRelease instance:
 
     >>> for upload in latest_uploads:
-    ...     print upload.title
+    ...     print(upload.title)
     mozilla-firefox 0.9 source package in Ubuntu
 
 Also, empty results (caused obviously by lack of sample data or very
@@ -904,7 +904,7 @@ a getBuildRecords() method.
 
     >>> builds = ubuntu['warty'].getBuildRecords(name=u'firefox')
     >>> for build in builds:
-    ...     print build.title
+    ...     print(build.title)
     hppa build of mozilla-firefox 0.9 in ubuntu warty RELEASE
     i386 build of mozilla-firefox 0.9 in ubuntu warty RELEASE
 
diff --git a/lib/lp/registry/doc/featuredproject.txt b/lib/lp/registry/doc/featuredproject.txt
index 8400dc2..ebfa1ef 100644
--- a/lib/lp/registry/doc/featuredproject.txt
+++ b/lib/lp/registry/doc/featuredproject.txt
@@ -17,7 +17,7 @@ PillarNameSet.
 We can get a list of featured projects from the pillar name set:
 
     >>> for project in pillar_set.featured_projects:
-    ...     print project.name
+    ...     print(project.name)
     applets
     bazaar
     firefox
diff --git a/lib/lp/registry/doc/hasowner-authorization.txt b/lib/lp/registry/doc/hasowner-authorization.txt
index b4cc74b..4ba1a82 100644
--- a/lib/lp/registry/doc/hasowner-authorization.txt
+++ b/lib/lp/registry/doc/hasowner-authorization.txt
@@ -21,23 +21,23 @@ Salgado is the owner of any FooObject we create, so he can edit it.
     >>> from zope.component import queryAdapter
     >>> from lp.app.interfaces.security import IAuthorization
     >>> authorization = queryAdapter(foo, IAuthorization, 'launchpad.Edit')
-    >>> print authorization.checkAuthenticated(IPersonRoles(salgado))
+    >>> print(authorization.checkAuthenticated(IPersonRoles(salgado)))
     True
 
 So can a member of the Launchpad admins team.
 
     >>> mark = getUtility(IPersonSet).getByName('mark')
     >>> admins = getUtility(IPersonSet).getByName('admins')
-    >>> print mark.inTeam(admins)
+    >>> print(mark.inTeam(admins))
     True
-    >>> print authorization.checkAuthenticated(IPersonRoles(mark))
+    >>> print(authorization.checkAuthenticated(IPersonRoles(mark)))
     True
 
 But someone who's not salgado nor a member of the admins team won't be
 able to.
 
     >>> sample_person = getUtility(IPersonSet).getByName('name12')
-    >>> print sample_person.inTeam(admins)
+    >>> print(sample_person.inTeam(admins))
     False
-    >>> print authorization.checkAuthenticated(IPersonRoles(sample_person))
+    >>> print(authorization.checkAuthenticated(IPersonRoles(sample_person)))
     False
diff --git a/lib/lp/registry/doc/karmacontext.txt b/lib/lp/registry/doc/karmacontext.txt
index 6391c26..273257d 100644
--- a/lib/lp/registry/doc/karmacontext.txt
+++ b/lib/lp/registry/doc/karmacontext.txt
@@ -49,7 +49,7 @@ product/project group/distribution grouped by categories.
     >>> for category in sorted_categories:
     ...     people = [(person.name, karmavalue) 
     ...               for person, karmavalue in contributors[category]]
-    ...     print "%s: %s" % (category.title, people)
+    ...     print("%s: %s" % (category.title, people))
     Bug Management: [(u'name16', 26), (u'name12', 13)]
     Specification Tracking: [(u'mark', 37)]
 
diff --git a/lib/lp/registry/doc/launchpad-container.txt b/lib/lp/registry/doc/launchpad-container.txt
index e80514b..ac967bd 100644
--- a/lib/lp/registry/doc/launchpad-container.txt
+++ b/lib/lp/registry/doc/launchpad-container.txt
@@ -116,7 +116,7 @@ A branch is within its target.
 But it's not within anything other than its target.
 
     >>> junk = get_branch_namespace(sample_person).getByName('junk.dev')
-    >>> print junk.product
+    >>> print(junk.product)
     None
     >>> ILaunchpadContainer(junk).isWithin('/firefox')
     False
diff --git a/lib/lp/registry/doc/launchpadlib/project-registry.txt.disabled b/lib/lp/registry/doc/launchpadlib/project-registry.txt.disabled
index 229d096..08aefe1 100644
--- a/lib/lp/registry/doc/launchpadlib/project-registry.txt.disabled
+++ b/lib/lp/registry/doc/launchpadlib/project-registry.txt.disabled
@@ -26,7 +26,7 @@ It is possible to get a batched list of all the project groups.
     u'http://.../aaa'
 
     >>> for project_group in project_groups:
-    ...     print "%s (%s)" % (project_group.name, project_group.display_name)
+    ...     print("%s (%s)" % (project_group.name, project_group.display_name))
     aaa (the Test Project)
     apache (Apache)
     gimp (the GiMP Project)
@@ -41,7 +41,7 @@ It's possible to search the list and get a subset of the project groups.
     ...                                       'http://api.launchpad.test/')
     >>> project_groups = lp_anon.project_groups.search(text="Apache")
     >>> for project_group in project_groups:
-    ...   print project_group.display_name
+    ...   print(project_group.display_name)
     Apache
 
 Searching without providing a search string is the same as getting all
@@ -50,7 +50,7 @@ the project groups.
     >>> project_groups = lp_anon.project_groups.search()
     >>> project_groups = sorted(project_groups, key=lambda X: X.name)
     >>> for project_group in project_groups:
-    ...     print "%s (%s)" % (project_group.name, project_group.display_name)
+    ...     print("%s (%s)" % (project_group.name, project_group.display_name))
     aaa (the Test Project)
     apache (Apache)
     gimp (the GiMP Project)
@@ -79,7 +79,7 @@ A project group supplies many attributes, collections, operations.
     ...     items.remove('http_etag')
     ...     for item in sorted(items):
     ...         value = attrgetter(item)(obj)
-    ...         print "%s: %s" % (item, value)
+    ...         print("%s: %s" % (item, value))
 
 The project group object has a large set of properties that can be
 accessed directly.
@@ -119,7 +119,7 @@ collection and the all_milestones collection.
     >>> def print_collection(collection, attrs=None):
     ...     items = [str(item) for item in collection]
     ...     for item in sorted(items):
-    ...         print item
+    ...         print(item)
 
     >>> print_collection(sorted(mozilla.active_milestones))
     http://api.launchpad.test/.../mozilla/+milestone/1.0
@@ -136,10 +136,10 @@ collection and the all_milestones collection.
 An individual milestone can be retrieved.  None is returned if it
 doesn't exist.
 
-    >>> print mozilla.getMilestone(name="1.0")
+    >>> print(mozilla.getMilestone(name="1.0"))
     http://.../mozilla/+milestone/1.0
 
-    >>> print mozilla.getMilestone(name="fnord")
+    >>> print(mozilla.getMilestone(name="fnord"))
     None
 
 
@@ -201,10 +201,10 @@ allows the previously redacted attributes to be seen.
 
     >>> lp_mark = launchpadlib_for(
     ...     'launchpadlib test', 'mark', 'READ_PRIVATE')
-    >>> print lp_mark.me.name
+    >>> print(lp_mark.me.name)
     mark
     >>> firefox = lp_mark.projects['firefox']
-    >>> print firefox.project_reviewed
+    >>> print(firefox.project_reviewed)
     False
 
 In Launchpad project names may not have uppercase letters in their
@@ -212,7 +212,7 @@ name.  As a convenience, requests for projects using the wrong case
 return the correct project.
 
     >>> firefox = lp_anon.projects['Firefox']
-    >>> print firefox.title
+    >>> print(firefox.title)
     Mozilla Firefox
 
 The milestones can be accessed through the active_milestones
@@ -234,10 +234,10 @@ collection and the all_milestones collection.
 An individual milestone can be retrieved.  None is returned if it
 doesn't exist.
 
-    >>> print firefox.getMilestone(name="1.0")
+    >>> print(firefox.getMilestone(name="1.0"))
     http://.../firefox/+milestone/1.0
 
-    >>> print firefox.getMilestone(name="fnord")
+    >>> print(firefox.getMilestone(name="fnord"))
     None
 
 A list of series can be accessed through the series_collection_link.
@@ -249,7 +249,7 @@ A list of series can be accessed through the series_collection_link.
 "getSeries" returns the series for the given name.
 
     >>> series = firefox.getSeries(name="1.0")
-    >>> print series.self_link
+    >>> print(series.self_link)
     http://.../firefox/1.0
 
 A list of releases can be accessed through the releases_collection_link.
@@ -263,13 +263,13 @@ A list of releases can be accessed through the releases_collection_link.
 "getRelease" returns the release for the given version.
 
     >>> release = firefox.getRelease(version="0.9.1")
-    >>> print release.self_link
+    >>> print(release.self_link)
     http://.../firefox/trunk/0.9.1
 
 The development focus series can be accessed through the
 development_focus attribute.
 
-    >>> print firefox.development_focus.self_link
+    >>> print(firefox.development_focus.self_link)
     http://.../firefox/trunk
 
 Attributes can be edited, but not by the anonymous user.
@@ -289,9 +289,9 @@ A project administrator can modify attributes on the project.
     >>> firefox.homepage_url = 'http://sf.net/firefox'
     >>> firefox.lp_save()
 
-    >>> print firefox.driver.self_link
+    >>> print(firefox.driver.self_link)
     http://.../~mark
-    >>> print firefox.homepage_url
+    >>> print(firefox.homepage_url)
     http://sf.net/firefox
 
 Changing the owner of a project can change other attributes as well.
@@ -315,14 +315,14 @@ Changing the owner of a project can change other attributes as well.
     >>> test_project = lp_mark.projects['test-project']
     >>> test_project.owner = nopriv
     >>> test_project.lp_save()
-    >>> print test_project.owner.self_link
+    >>> print(test_project.owner.self_link)
     http://.../~name12
     >>> test_series = test_project.getSeries(name="test-series")
-    >>> print test_series.owner.self_link
+    >>> print(test_series.owner.self_link)
     http://.../~name12
 
     >>> release = test_project.getMilestone(name='test-milestone')
-    >>> print release.owner.self_link
+    >>> print(release.owner.self_link)
     http://.../~name12
 
 Read-only attributes cannot be changed.
@@ -336,7 +336,7 @@ Read-only attributes cannot be changed.
 "get_timeline" returns a list of dictionaries, corresponding to each
 milestone and release.
 
-    >>> print pretty(firefox.get_timeline())
+    >>> print(pretty(firefox.get_timeline()))
     [{'is_development_focus': False,
       'landmarks': [{'code_name': 'First Stable Release',
                      'date': '2004-06-28',
diff --git a/lib/lp/registry/doc/milestone.txt b/lib/lp/registry/doc/milestone.txt
index e4fd929..1d6a839 100644
--- a/lib/lp/registry/doc/milestone.txt
+++ b/lib/lp/registry/doc/milestone.txt
@@ -36,58 +36,58 @@ dateexpected=None) method of a ProductSeries or DistroSeries:
     >>> firefox_ms = ff_onedotzero.newMilestone(
     ...     name="1.0rc1", code_name="Candidate One",
     ...     summary="A beta version that is feature complete.")
-    >>> print firefox_ms.name
+    >>> print(firefox_ms.name)
     1.0rc1
 
 Milestone's have many descriptive names. The name and code_name are
 atomic attributes. The display and and title attributes are composed.
 
-    >>> print firefox_ms.name
+    >>> print(firefox_ms.name)
     1.0rc1
 
-    >>> print firefox_ms.code_name
+    >>> print(firefox_ms.code_name)
     Candidate One
 
-    >>> print firefox_ms.displayname
+    >>> print(firefox_ms.displayname)
     Mozilla Firefox 1.0rc1
 
-    >>> print firefox_ms.title
+    >>> print(firefox_ms.title)
     Mozilla Firefox 1.0rc1 "Candidate One"
 
 The summary describes the intent of the milestone.
 
-    >>> print firefox_ms.summary
+    >>> print(firefox_ms.summary)
     A beta version that is feature complete.
 
 A milestones can access their product and series targets.
 
-    >>> print firefox_ms.target.displayname
+    >>> print(firefox_ms.target.displayname)
     Mozilla Firefox
 
-    >>> print firefox_ms.series_target.name
+    >>> print(firefox_ms.series_target.name)
     1.0
 
 To retrieve a specific Milestone, use IMilestoneSet.get:
 
     >>> firefox_ms_1_0 = milestoneset.get(1)
-    >>> print firefox_ms_1_0.name
+    >>> print(firefox_ms_1_0.name)
     1.0
 
-    >>> print firefox_ms_1_0.displayname
+    >>> print(firefox_ms_1_0.displayname)
     Mozilla Firefox 1.0
 
 Of course, you can also get them off a Product or Distribution using the
 getMilestone() method:
 
     >>> ms = upstream_firefox.getMilestone('1.0rc1')
-    >>> print ms.name
+    >>> print(ms.name)
     1.0rc1
 
 Trying to retrieve a milestone that does not exist from a product will
 return None:
 
     >>> non_ms = upstream_firefox.getMilestone('0.99x1')
-    >>> print non_ms
+    >>> print(non_ms)
     None
 
 Now, lets test all of that for DistroSeriess too!
@@ -100,28 +100,28 @@ Now, lets test all of that for DistroSeriess too!
 
     >>> login('mark@xxxxxxxxxxx')
     >>> new_ms = krunch.newMilestone('1.3rc2')
-    >>> print new_ms.name
+    >>> print(new_ms.name)
     1.3rc2
 
-    >>> print new_ms.code_name
+    >>> print(new_ms.code_name)
     None
 
-    >>> print new_ms.displayname
+    >>> print(new_ms.displayname)
     Kubuntu 1.3rc2
 
-    >>> print new_ms.title
+    >>> print(new_ms.title)
     Kubuntu 1.3rc2
 
-    >>> print new_ms.target.name
+    >>> print(new_ms.target.name)
     kubuntu
 
-    >>> print new_ms.series_target.name
+    >>> print(new_ms.series_target.name)
     krunch
 
-    >>> print kubuntu.getMilestone('foo2.3')
+    >>> print(kubuntu.getMilestone('foo2.3'))
     None
 
-    >>> print kubuntu.getMilestone('1.3rc2').dateexpected
+    >>> print(kubuntu.getMilestone('1.3rc2').dateexpected)
     None
 
 Trying to retrieve a milestone that doesn't exist will raise a
@@ -152,16 +152,16 @@ itself has neither any milestones.
     >>> from lp.registry.interfaces.projectgroup import IProjectGroupSet
     >>> gnome = getUtility(IProjectGroupSet)['gnome']
     >>> for product in gnome.products:
-    ...     print '%s %s' % (
+    ...     print('%s %s' % (
     ...         product.name,
-    ...         [milestone.title for milestone in product.all_milestones])
+    ...         [milestone.title for milestone in product.all_milestones]))
     evolution [u'Evolution 2.1.6']
     gnome-terminal []
     applets []
     netapplet [u'NetApplet 1.0']
     gnomebaker []
 
-    >>> print [milestone.title for milestone in gnome.all_milestones]
+    >>> print([milestone.title for milestone in gnome.all_milestones])
     [u'GNOME 2.1.6', u'GNOME 1.0']
 
 When a milestone for a product is defined, this milestone is "inherited"
@@ -173,10 +173,10 @@ by the project.
     >>> evolution_1_1 = test_helper.createProductMilestone(
     ...     '1.1', 'evolution', date_expected=None)
     >>> evolution = productset['evolution']
-    >>> print [milestone.name for milestone in evolution.all_milestones]
+    >>> print([milestone.name for milestone in evolution.all_milestones])
     [u'2.1.6', u'1.1']
 
-    >>> print [milestone.name for milestone in gnome.all_milestones]
+    >>> print([milestone.name for milestone in gnome.all_milestones])
     [u'2.1.6', u'1.1', u'1.0']
 
 Adding a milestone with the same name to another Gnome product does not
@@ -185,10 +185,10 @@ increase the number of Gnome milestones.
     >>> applets_1_1 = test_helper.createProductMilestone(
     ...     '1.1', 'applets', date_expected=None)
     >>> applets = productset['applets']
-    >>> print [milestone.name for milestone in applets.all_milestones]
+    >>> print([milestone.name for milestone in applets.all_milestones])
     [u'1.1']
 
-    >>> print [milestone.name for milestone in gnome.all_milestones]
+    >>> print([milestone.name for milestone in gnome.all_milestones])
     [u'2.1.6', u'1.1', u'1.0']
 
 Since project milestones are generated from the names of the product
@@ -198,10 +198,10 @@ appear as separate project milestones.
     >>> netapplet_1_1 = test_helper.createProductMilestone(
     ...     '1.1.', 'netapplet', date_expected=None)
     >>> netapplet = productset['netapplet']
-    >>> print [milestone.name for milestone in netapplet.all_milestones]
+    >>> print([milestone.name for milestone in netapplet.all_milestones])
     [u'1.1.', u'1.0']
 
-    >>> print [milestone.name for milestone in gnome.all_milestones]
+    >>> print([milestone.name for milestone in gnome.all_milestones])
     [u'2.1.6', u'1.1.', u'1.1', u'1.0']
 
 A project milestone has the same attributes as product and distribution
@@ -209,45 +209,45 @@ milestones, but most are None because project milestones are
 aggregations. The code_name and series attributes are always none.
 
     >>> project_milestone = gnome.all_milestones[0]
-    >>> print project_milestone.name
+    >>> print(project_milestone.name)
     2.1.6
 
-    >>> print project_milestone.code_name
+    >>> print(project_milestone.code_name)
     None
 
-    >>> print project_milestone.displayname
+    >>> print(project_milestone.displayname)
     GNOME 2.1.6
 
-    >>> print project_milestone.title
+    >>> print(project_milestone.title)
     GNOME 2.1.6
 
-    >>> print project_milestone.target.name
+    >>> print(project_milestone.target.name)
     gnome
 
-    >>> print project_milestone.series_target
+    >>> print(project_milestone.series_target)
     None
 
 A project milestone is active, if at least one product milestone with
 the same name is active.
 
-    >>> print applets_1_1.active, evolution_1_1.active
+    >>> print(applets_1_1.active, evolution_1_1.active)
     True True
 
-    >>> print gnome.getMilestone('1.1').active
+    >>> print(gnome.getMilestone('1.1').active)
     True
 
     >>> applets_1_1.active = False
-    >>> print gnome.getMilestone('1.1').active
+    >>> print(gnome.getMilestone('1.1').active)
     True
 
     >>> evolution_1_1.active = False
-    >>> print gnome.getMilestone('1.1').active
+    >>> print(gnome.getMilestone('1.1').active)
     False
 
 A project milestone is not shown for active milestones from inactive
 products.
 
-    >>> print [milestone.name for milestone in gnome.milestones]
+    >>> print([milestone.name for milestone in gnome.milestones])
     [u'1.1.']
 
     # Unlink the source packages so the project can be deactivated.
@@ -255,7 +255,7 @@ products.
     >>> from lp.testing import unlink_source_packages
     >>> unlink_source_packages(netapplet)
     >>> netapplet.active = False
-    >>> print [milestone.name for milestone in gnome.milestones]
+    >>> print([milestone.name for milestone in gnome.milestones])
     []
 
     # Reset the product back to original status so future tests pass.
@@ -265,19 +265,19 @@ products.
 The dateexpected attribute is set to the minimum of the dateexpected
 values of the product milestones.
 
-    >>> print applets_1_1.dateexpected, evolution_1_1.dateexpected
+    >>> print(applets_1_1.dateexpected, evolution_1_1.dateexpected)
     None None
 
-    >>> print gnome.getMilestone('1.1').dateexpected
+    >>> print(gnome.getMilestone('1.1').dateexpected)
     None
 
     >>> from datetime import datetime
     >>> applets_1_1.dateexpected = datetime(2007, 4, 2)
-    >>> print gnome.getMilestone('1.1').dateexpected
+    >>> print(gnome.getMilestone('1.1').dateexpected)
     2007-04-02 00:00:00
 
     >>> evolution_1_1.dateexpected = datetime(2007, 4, 1)
-    >>> print gnome.getMilestone('1.1').dateexpected
+    >>> print(gnome.getMilestone('1.1').dateexpected)
     2007-04-01 00:00:00
 
 All bugtasks that are associated with a product milestone are also
@@ -289,14 +289,14 @@ associated with the project milestone of the same name. No product of
 the Gnome project has yet any specifications.
 
     >>> for product in gnome.products:
-    ...     print product.name, list(product.visible_specifications)
+    ...     print(product.name, list(product.visible_specifications))
     evolution []
     gnome-terminal []
     applets []
     netapplet []
     gnomebaker []
 
-    >>> print list(gnome.getMilestone('1.1').getSpecifications(None))
+    >>> print(list(gnome.getMilestone('1.1').getSpecifications(None)))
     []
 
 When a specification for a product is created and assigned to a product
@@ -355,12 +355,12 @@ list of recipients.
     >>> from lp.services.database.interfaces import IStore
     >>> notification = IStore(BugNotification).find(
     ...     BugNotification, date_emailed=None).order_by('id').last()
-    >>> print notification.message.chunks[0].content
+    >>> print(notification.message.chunks[0].content)
     ** Changed in: firefox
         Milestone: 1.0 => 2.0
 
     >>> for recipient in notification.recipients:
-    ...     print recipient.person.name, recipient.reason_header
+    ...     print(recipient.person.name, recipient.reason_header)
     cprov Subscriber (Mozilla Firefox 1.0)
     ddaa Subscriber (Mozilla Firefox 2.0)
     ...
@@ -377,22 +377,22 @@ editable.
     >>> ignored = login_person(upstream_firefox.owner)
     >>> fizzy_milestone = ff_onedotzero.newMilestone('fuzzy')
 
-    >>> print fizzy_milestone.name
+    >>> print(fizzy_milestone.name)
     fuzzy
 
     >>> fizzy_milestone.name = 'fizzy'
-    >>> print fizzy_milestone.name
+    >>> print(fizzy_milestone.name)
     fizzy
 
-    >>> print fizzy_milestone.code_name
+    >>> print(fizzy_milestone.code_name)
     None
 
     >>> fizzy_milestone.code_name = 'dizzy'
-    >>> print fizzy_milestone.code_name
+    >>> print(fizzy_milestone.code_name)
     dizzy
 
     >>> fizzy_milestone.summary = 'fizzy love'
-    >>> print fizzy_milestone.summary
+    >>> print(fizzy_milestone.summary)
     fizzy love
 
     >>> date = datetime(2007, 4, 2)
@@ -410,13 +410,13 @@ editable.
 The productseries attribute can be edited if the milestones belongs to a
 product.
 
-    >>> print fizzy_milestone.productseries.name
+    >>> print(fizzy_milestone.productseries.name)
     1.0
 
     >>> two_series = upstream_firefox.newSeries(
     ...     upstream_firefox.owner, '2.0', 'Two dot n')
     >>> fizzy_milestone.productseries = two_series
-    >>> print fizzy_milestone.productseries.name
+    >>> print(fizzy_milestone.productseries.name)
     2.0
 
 The driver of a milestone's target or series can make changes.
@@ -448,11 +448,11 @@ specifications targeted to it.
     >>> owner = getUtility(IPersonSet).getByName('name12')
     >>> ignored = login_person(owner)
     >>> milestone = ff_onedotzero.newMilestone('1.0.10')
-    >>> print milestone.product_release
+    >>> print(milestone.product_release)
     None
 
     >>> milestone.destroySelf()
-    >>> print upstream_firefox.getMilestone('1.0.10')
+    >>> print(upstream_firefox.getMilestone('1.0.10'))
     None
 
 If a milestone has a product release associated with it though, it can
@@ -516,9 +516,9 @@ event is signaled for each changed bug task.
     >>> from lp.testing.fixture import ZopeEventHandlerFixture
 
     >>> def print_event(object, event):
-    ...     print "Received %s on %s" % (
+    ...     print("Received %s on %s" % (
     ...         event.__class__.__name__.split('.')[-1],
-    ...         object.__class__.__name__.split('.')[-1])
+    ...         object.__class__.__name__.split('.')[-1]))
 
     >>> milestone = ff_onedotzero.newMilestone('kia')
     >>> fixed_bugtask = factory.makeBugTask(target=upstream_firefox)
diff --git a/lib/lp/registry/doc/person-account.txt b/lib/lp/registry/doc/person-account.txt
index 9de6e28..d37bcb0 100644
--- a/lib/lp/registry/doc/person-account.txt
+++ b/lib/lp/registry/doc/person-account.txt
@@ -25,7 +25,7 @@ process. Matsubara's account was created during a code import.
     False
     >>> matsubara.account_status
     <DBItem AccountStatus.NOACCOUNT, ...>
-    >>> print matsubara.preferredemail
+    >>> print(matsubara.preferredemail)
     None
 
 The account can only be activated by the user who is claiming
@@ -163,7 +163,7 @@ adds a '-deactivatedaccount' suffix to the person's name...
     >>> [email.email for email in foobar.validatedemails]
     []
 
-    >>> print getattr(foobar.preferredemail, 'email', None)
+    >>> print(getattr(foobar.preferredemail, 'email', None))
     None
 
 ...no signed codes of conduct...
diff --git a/lib/lp/registry/doc/person-karma.txt b/lib/lp/registry/doc/person-karma.txt
index da52f64..8dbfc03 100644
--- a/lib/lp/registry/doc/person-karma.txt
+++ b/lib/lp/registry/doc/person-karma.txt
@@ -95,7 +95,7 @@ show the 5 most active projects.
     >>> foobar = getUtility(IPersonSet).getByName('name16')
     >>> for contrib in foobar.getProjectsAndCategoriesContributedTo(None):
     ...     categories = sorted(cat.name for cat in contrib['categories'])
-    ...     print contrib['project'].title, categories
+    ...     print(contrib['project'].title, categories)
     Evolution [u'bugs', u'translations']
     Ubuntu [u'bugs']
     gnomebaker [u'bugs']
@@ -123,7 +123,7 @@ is updated by the foaf-update-karma-cache.py cronscript.
     ...     stdin=subprocess.PIPE, stdout=subprocess.PIPE,
     ...     stderr=subprocess.PIPE, universal_newlines=True)
     >>> (out, err) = process.communicate()
-    >>> print err
+    >>> print(err)
     INFO    Creating lockfile: /var/lock/launchpad-karma-update.lock
     INFO    Updating Launchpad karma caches
     INFO    Step A: Calculating individual KarmaCache entries
@@ -135,7 +135,7 @@ is updated by the foaf-update-karma-cache.py cronscript.
     INFO    Step C: Calculating KarmaCache sums
     INFO    Finished updating Launchpad karma caches
     <BLANKLINE>
-    >>> print out
+    >>> print(out)
     <BLANKLINE>
     >>> process.returncode
     0
@@ -164,14 +164,14 @@ Management category was calculated to be 2.667, but reduced to 2 because this
 was the maximum specified in config.karmacacheupdater.max_scaling.
 
     >>> for karma in salgado.latestKarma():
-    ...     print karma.action.title, karma.action.points
+    ...     print(karma.action.title, karma.action.points)
     Specification Review     10
     Bug Marked as Fixed      10
     Registered Specification 30
     Bug Marked as Duplicate   5
 
     >>> for cache in salgado.karma_category_caches:
-    ...     print "%s: %d" % (cache.category.title, cache.karmavalue)
+    ...     print("%s: %d" % (cache.category.title, cache.karmavalue))
     Bug Management: 30
     Specification Tracking: 40
 
diff --git a/lib/lp/registry/doc/person-merge.txt b/lib/lp/registry/doc/person-merge.txt
index ebe2ced..fd6a721 100644
--- a/lib/lp/registry/doc/person-merge.txt
+++ b/lib/lp/registry/doc/person-merge.txt
@@ -58,7 +58,7 @@ Marilize and save it for later comparison.
     >>> firefox = getUtility(IProductSet).getByName('firefox')
     >>> marilize_karma = marilize.assignKarma('bugfixed', product=firefox)
     >>> saved_marilize_karma_id = marilize_karma.id
-    >>> print marilize_karma.person.name
+    >>> print(marilize_karma.person.name)
     marilize
 
     >>> sampleperson_old_karma = sample.karma
@@ -167,7 +167,7 @@ name12 (Sample Person).
     >>> saved_marilize_karma_id == marilize_karma.id
     True
 
-    >>> print marilize_karma.person.name
+    >>> print(marilize_karma.person.name)
     name12
 
 Note that we don't bother migrating karma caches - it will just be reset
@@ -226,13 +226,13 @@ email and mailing list subscription settings.
     1
 
     >>> notification = notifications[0]
-    >>> print notification.person.name
+    >>> print(notification.person.name)
     name12
 
-    >>> print notification.subject
+    >>> print(notification.subject)
     Launchpad accounts merged
 
-    >>> print notification.body
+    >>> print(notification.body)
     The Launchpad account named 'marilize-merged' was merged into the account
     named 'name12'. ...
 
@@ -295,7 +295,7 @@ create, and then delete, the needed two people.
 First, we will test a merge where there is no decoration.
 
     >>> winner, loser = next(endless_supply_of_players)
-    >>> print decorator_refs(store, winner, loser)
+    >>> print(decorator_refs(store, winner, loser))
     <BLANKLINE>
 
     >>> from lp.registry.personmerge import _merge_person_decoration
@@ -310,7 +310,7 @@ column name.
 
 There should still be no columns that reference the winner or loser.
 
-    >>> print decorator_refs(store, winner, loser)
+    >>> print(decorator_refs(store, winner, loser))
     <BLANKLINE>
 
 OK, now, this time, we will add some decorator information to the winner
@@ -318,7 +318,7 @@ but not the loser.
 
     >>> winner, loser = next(endless_supply_of_players)
     >>> winner.setLocation(None, None, 'America/Santiago', winner)
-    >>> print decorator_refs(store, winner, loser)
+    >>> print(decorator_refs(store, winner, loser))
     winner, winner,
 
     >>> _merge_person_decoration(winner, loser, skip,
@@ -327,7 +327,7 @@ but not the loser.
 There should now still be one decorator, with all columns pointing to
 the winner:
 
-    >>> print decorator_refs(store, winner, loser)
+    >>> print(decorator_refs(store, winner, loser))
     winner, winner,
 
 This time, we will have a decorator for the person that is being merged
@@ -335,7 +335,7 @@ INTO another person, but nothing on the target person.
 
     >>> winner, loser = next(endless_supply_of_players)
     >>> loser.setLocation(None, None, 'America/Santiago', loser)
-    >>> print decorator_refs(store, winner, loser)
+    >>> print(decorator_refs(store, winner, loser))
     loser, loser,
 
     >>> _merge_person_decoration(winner, loser, skip,
@@ -344,7 +344,7 @@ INTO another person, but nothing on the target person.
 There should now still be one decorator, with all columns pointing to
 the winner:
 
-    >>> print decorator_refs(store, winner, loser)
+    >>> print(decorator_refs(store, winner, loser))
     winner, winner,
 
 Now, we want to show what happens when there is a decorator for both the
@@ -355,13 +355,13 @@ point to the winner, and the to_person will be unaffected.
     >>> winner, loser = next(endless_supply_of_players)
     >>> winner.setLocation(None, None, 'America/Santiago', winner)
     >>> loser.setLocation(None, None, 'America/New_York', loser)
-    >>> print decorator_refs(store, winner, loser)
+    >>> print(decorator_refs(store, winner, loser))
     winner, winner,
     loser, loser,
 
     >>> _merge_person_decoration(winner, loser, skip,
     ...     'PersonLocation', 'person', ['last_modified_by',])
-    >>> print decorator_refs(store, winner, loser)
+    >>> print(decorator_refs(store, winner, loser))
     winner, winner,
     loser, winner,
 
diff --git a/lib/lp/registry/doc/person-notification.txt b/lib/lp/registry/doc/person-notification.txt
index beaf428..2821e18 100644
--- a/lib/lp/registry/doc/person-notification.txt
+++ b/lib/lp/registry/doc/person-notification.txt
@@ -25,7 +25,7 @@ subject.
     u'mark'
     >>> notification.date_created
     datetime.datetime(...
-    >>> print notification.date_emailed
+    >>> print(notification.date_emailed)
     None
 
 The notifications that need to be sent can be retrieved with
diff --git a/lib/lp/registry/doc/person.txt b/lib/lp/registry/doc/person.txt
index 7147f77..331fcf6 100644
--- a/lib/lp/registry/doc/person.txt
+++ b/lib/lp/registry/doc/person.txt
@@ -203,7 +203,7 @@ Unlike people, teams don't need a contact address, so we can pass None
 to setContactAddress() to leave a team without a contact address.
 
     >>> team.setContactAddress(None)
-    >>> print team.preferredemail
+    >>> print(team.preferredemail)
     None
 
 When a new sourcepackage is imported and a Person entry has to be
@@ -264,7 +264,7 @@ We can't adapt an account which has no person associated with, though.
     ...     AccountCreationRationale, IAccountSet)
     >>> personless_account = getUtility(IAccountSet).new(
     ...     AccountCreationRationale.UNKNOWN, 'Display name')
-    >>> print IPerson(personless_account, None)
+    >>> print(IPerson(personless_account, None))
     None
 
 Our security adapters expect to get passed an IPerson, but we use
@@ -281,7 +281,7 @@ done.
 
     >>> from lp.services.webapp.servers import LaunchpadTestRequest
     >>> request = LaunchpadTestRequest()
-    >>> print request.annotations.get('launchpad.person_to_account_cache')
+    >>> print(request.annotations.get('launchpad.person_to_account_cache'))
     None
 
 Now we log in with the request so that whenever we adapt an account into
@@ -331,7 +331,7 @@ A person also has a reason for why their standing is what it is.  The
 default value of None means that no reason for the personal_standing
 value is available.
 
-    >>> print lifeless.personal_standing_reason
+    >>> print(lifeless.personal_standing_reason)
     None
 
 A Launchpad administrator may change a person's standing, and may give a
@@ -344,7 +344,7 @@ reason for the change.
     >>> lifeless.personal_standing
     <DBItem PersonalStanding.GOOD...
 
-    >>> print lifeless.personal_standing_reason
+    >>> print(lifeless.personal_standing_reason)
     Such a cool guy!
 
 Non-administrators may not change a person's standing.
@@ -366,7 +366,7 @@ Non-administrators may not change a person's standing.
     >>> lifeless.personal_standing
     <DBItem PersonalStanding.GOOD...
 
-    >>> print lifeless.personal_standing_reason
+    >>> print(lifeless.personal_standing_reason)
     Such a cool guy!
 
     >>> login(ANONYMOUS)
@@ -447,7 +447,7 @@ created team.
     >>> from zope.lifecycleevent.interfaces import IObjectCreatedEvent
     >>> from lp.testing.fixture import ZopeEventHandlerFixture
     >>> def print_event(team, event):
-    ...     print "ObjectCreatedEvent fired for team '%s'" % team.name
+    ...     print("ObjectCreatedEvent fired for team '%s'" % team.name)
 
     >>> listener = ZopeEventHandlerFixture(
     ...     print_event, (ITeam, IObjectCreatedEvent))
@@ -733,7 +733,7 @@ team list is actually sorted by date joined.
     >>> foobar = personset.getByName('name16')
     >>> membership_list = foobar.getLatestApprovedMembershipsForPerson()
     >>> for membership in membership_list:
-    ...     print membership.datejoined
+    ...     print(membership.datejoined)
     2009-07-09 11:58:38.122886+00:00
     2008-05-14 12:07:14.227450+00:00
     2007-01-17 14:13:39.692693+00:00
@@ -760,8 +760,8 @@ address:
     ...     for person in results:
     ...         emails = [email.email
     ...                   for email in naked_emailset.getByPerson(person)]
-    ...         print "%s (%s): %s" % (
-    ...             person.displayname, person.name, emails)
+    ...         print("%s (%s): %s" % (
+    ...             person.displayname, person.name, emails))
 
     >>> print_people(personset.find('ubuntu'))
     Mirror Administrators (ubuntu-mirror-admins): []
@@ -938,7 +938,7 @@ You can get the top overall contributors, that is, the people with the
 most karma.
 
     >>> for person in personset.getTopContributors(limit=3):
-    ...     print "%s: %s" % (person.name, person.karma)
+    ...     print("%s: %s" % (person.name, person.karma))
     name16: 241
     name12: 138
     mark: 130
@@ -974,9 +974,9 @@ related packages:
     >>> mark.hasMaintainedPackages()
     True
     >>> for sprelease in mark.getLatestMaintainedPackages():
-    ...     print (sprelease.name,
+    ...     print((sprelease.name,
     ...            sprelease.upload_distroseries.fullseriesname,
-    ...            sprelease.version)
+    ...            sprelease.version))
     (u'alsa-utils', u'Debian Sid', u'1.0.9a-4')
     (u'pmount', u'Ubuntu Hoary', u'0.1-2')
     (u'netapplet', u'Ubuntu Warty', u'0.99.6-1')
@@ -988,9 +988,9 @@ related packages:
     >>> mark.hasUploadedButNotMaintainedPackages()
     True
     >>> for sprelease in mark.getLatestUploadedButNotMaintainedPackages():
-    ...     print (sprelease.name,
+    ...     print((sprelease.name,
     ...            sprelease.upload_distroseries.fullseriesname,
-    ...            sprelease.version)
+    ...            sprelease.version))
     (u'foobar', u'Ubuntu Breezy-autotest', u'1.0')
     (u'cdrkit', u'Ubuntu Breezy-autotest', u'1.0')
     (u'libstdc++', u'Ubuntu Hoary', u'b8p')
@@ -1002,12 +1002,12 @@ related packages:
     True
     >>> mark_spreleases = mark.getLatestUploadedPPAPackages()
     >>> for sprelease in mark_spreleases:
-    ...     print (sprelease.name,
+    ...     print((sprelease.name,
     ...            sprelease.version,
     ...            sprelease.creator.name,
     ...            sprelease.maintainer.name,
     ...            sprelease.upload_archive.owner.name,
-    ...            sprelease.upload_distroseries.fullseriesname)
+    ...            sprelease.upload_distroseries.fullseriesname))
     (u'iceweasel', u'1.0', u'mark', u'name16', u'mark', u'Ubuntu Warty')
 
 We will change modify the first SourcePackageRelease to reproduce the
@@ -1021,12 +1021,12 @@ maintainer got omitted from the results:
 
     >>> mark_spreleases = mark.getLatestUploadedPPAPackages()
     >>> for sprelease in mark_spreleases:
-    ...     print (sprelease.name,
+    ...     print((sprelease.name,
     ...            sprelease.version,
     ...            sprelease.creator.name,
     ...            sprelease.maintainer.name,
     ...            sprelease.upload_archive.owner.name,
-    ...            sprelease.upload_distroseries.fullseriesname)
+    ...            sprelease.upload_distroseries.fullseriesname))
     (u'iceweasel', u'1.0', u'mark', u'mark', u'mark', u'Ubuntu Warty')
 
 Unlike Mark, this next person is very lazy and has no related packages:
@@ -1071,14 +1071,14 @@ getOwnedProjects() method of IPerson.  This method returns projects
 ordered by displayname.
 
     >>> for project in mark.getOwnedProjects():
-    ...     print project.displayname
+    ...     print(project.displayname)
     Derby
     alsa-utils
 
 We can also ask for projects owned through team memberships.
 
     >>> for project in mark.getOwnedProjects(transitive=True):
-    ...     print project.displayname
+    ...     print(project.displayname)
     Derby
     Tomcat
     alsa-utils
@@ -1096,12 +1096,12 @@ The method does not return inactive projects.
     >>> derby = getUtility(IProductSet).getByName('derby')
     >>> derby.active = False
     >>> for project in mark.getOwnedProjects(transitive=True):
-    ...     print project.displayname
+    ...     print(project.displayname)
     Tomcat
     alsa-utils
 
     >>> for project in ubuntu_team.getOwnedProjects():
-    ...     print project.displayname
+    ...     print(project.displayname)
     Tomcat
 
 David does not own any projects.
@@ -1114,7 +1114,7 @@ search.
 
     >>> for project in mark.getOwnedProjects(
     ...     match_name=u'java', transitive=True):
-    ...     print project.displayname
+    ...     print(project.displayname)
     Tomcat
 
 Searching for a non-existent project returns no matches.
@@ -1133,7 +1133,7 @@ Person.languages.
     >>> carlos = personset.getByName('carlos')
 
     >>> for language in carlos.languages:
-    ...     print language.code, language.englishname
+    ...     print(language.code, language.englishname)
     ca     Catalan
     en     English
     es     Spanish
@@ -1170,7 +1170,7 @@ The Person.languages list is ordered alphabetically by the languages'
 English names.
 
     >>> for language in daf.languages:
-    ...     print language.code, language.englishname
+    ...     print(language.code, language.englishname)
     en_GB  English (United Kingdom)
     ja     Japanese
     cy     Welsh
@@ -1195,7 +1195,7 @@ Next, Carlos has two incomplete specs *related* to him:
 
     >>> filter = []
     >>> for spec in carlos.specifications(None, filter=filter):
-    ...     print spec.name, spec.is_complete, spec.informational
+    ...     print(spec.name, spec.is_complete, spec.informational)
     svg-support False False
     extension-manager-upgrades False True
 
@@ -1204,7 +1204,7 @@ These 2 specifications are assigned to Carlos:
     >>> assigned_specs = carlos.specifications(
     ...     carlos, filter=[SpecificationFilter.ASSIGNEE])
     >>> for spec in assigned_specs:
-    ...     print spec.name
+    ...     print(spec.name)
     svg-support
     extension-manager-upgrades
 
@@ -1220,13 +1220,13 @@ is the approver.
     >>> mark = getUtility(IPersonSet).getByName('mark')
     >>> filter = [SpecificationFilter.APPROVER]
     >>> for spec in mark.specifications(None, filter=filter):
-    ...     print spec.name
+    ...     print(spec.name)
     extension-manager-upgrades
 
 But has registered 5 of them:
 
     >>> filter = [SpecificationFilter.CREATOR]
-    >>> print foobar.specifications(None, filter=filter).count()
+    >>> print(foobar.specifications(None, filter=filter).count())
     5
 
 Now Celso, on the other hand, has 2 specs related to him:
@@ -1239,20 +1239,20 @@ On one of those, he is the approver:
 
     >>> filter = [SpecificationFilter.APPROVER]
     >>> for spec in cprov.specifications(None, filter=filter):
-    ...     print spec.name
+    ...     print(spec.name)
     svg-support
 
 And on another one, he is the drafter
 
     >>> filter = [SpecificationFilter.DRAFTER]
     >>> for spec in cprov.specifications(None, filter=filter):
-    ...     print spec.name
+    ...     print(spec.name)
     e4x
 
 We can filter for specifications that contain specific text:
 
     >>> for spec in cprov.specifications(None, filter=[u'svg']):
-    ...     print spec.name
+    ...     print(spec.name)
     svg-support
 
 Inactive products are excluded from the listings.
@@ -1356,19 +1356,19 @@ takes no parameters regarding to emails.
     ...     comment="when importing bugs", displayname="Ford Prefect",
     ...     registrant=foo_bar)
 
-    >>> print new_person.name
+    >>> print(new_person.name)
     ix
 
-    >>> print new_person.displayname
+    >>> print(new_person.displayname)
     Ford Prefect
 
-    >>> print new_person.preferredemail
+    >>> print(new_person.preferredemail)
     None
 
-    >>> print new_person.creation_rationale.name
+    >>> print(new_person.creation_rationale.name)
     BUGIMPORT
 
-    >>> print new_person.registrant.name
+    >>> print(new_person.registrant.name)
     name16
 
 
diff --git a/lib/lp/registry/doc/personlocation.txt b/lib/lp/registry/doc/personlocation.txt
index a926b8d..779d3d9 100644
--- a/lib/lp/registry/doc/personlocation.txt
+++ b/lib/lp/registry/doc/personlocation.txt
@@ -11,11 +11,11 @@ PersonLocation). Until we move the time zone back to the Person table
     >>> personset = getUtility(IPersonSet)
 
     >>> marilize = personset.getByName('marilize')
-    >>> print marilize.time_zone
+    >>> print(marilize.time_zone)
     Africa/Maseru
-    >>> print marilize.latitude
+    >>> print(marilize.latitude)
     None
-    >>> print marilize.longitude
+    >>> print(marilize.longitude)
     None
 
 setLocation() will always set the time zone to the given value and both
@@ -24,11 +24,11 @@ latitude and longitude to None, regardless of what was passed in.
     >>> cprov = personset.getByName('cprov')
     >>> ignored = login_person(cprov)
     >>> cprov.setLocation(-43.2, -61.93, 'America/Sao_Paulo', cprov)
-    >>> print cprov.time_zone
+    >>> print(cprov.time_zone)
     America/Sao_Paulo
-    >>> print cprov.latitude
+    >>> print(cprov.latitude)
     None
-    >>> print cprov.longitude
+    >>> print(cprov.longitude)
     None
 
 We cannot store a location for a team, though.
diff --git a/lib/lp/registry/doc/personroles.txt b/lib/lp/registry/doc/personroles.txt
index 4453884..9fe4308 100644
--- a/lib/lp/registry/doc/personroles.txt
+++ b/lib/lp/registry/doc/personroles.txt
@@ -23,13 +23,13 @@ PersonRoles is registered as an unnamed adapter for IPersonRoles.
 
     >>> from lp.registry.interfaces.role import IPersonRoles
     >>> person = factory.makePerson()
-    >>> print IPersonRoles(person)
+    >>> print(IPersonRoles(person))
     <lp.registry.model.personroles.PersonRoles object at ...>
 
 The original Person object can be reached through the person attribute.
 
     >>> roles = IPersonRoles(person)
-    >>> print roles.person is person
+    >>> print(roles.person is person)
     True
 
 
@@ -42,10 +42,10 @@ this celebrity. The following tests are identical.
 
     >>> from lp.app.interfaces.launchpad import ILaunchpadCelebrities
     >>> rosetta_experts = getUtility(ILaunchpadCelebrities).rosetta_experts
-    >>> print person.inTeam(rosetta_experts)
+    >>> print(person.inTeam(rosetta_experts))
     False
 
-    >>> print roles.in_rosetta_experts
+    >>> print(roles.in_rosetta_experts)
     False
 
 The test will succeed once we make person a member of the team. Need to be an
@@ -54,7 +54,7 @@ admin to do that.
     >>> login("foo.bar@xxxxxxxxxxxxx")
     >>> rosetta_experts.addMember(person, rosetta_experts.teamowner)
     (True, ...Approved>)
-    >>> print roles.in_rosetta_experts
+    >>> print(roles.in_rosetta_experts)
     True
 
 To stay consistent, all attributes are prefixed with "in_" although the
@@ -62,14 +62,14 @@ attribute names of ILaunchpadCelebrities are not all lexically correct
 plurals, nor are all the attributes teams. This makes for odd sounding
 attribute names in IPersonRoles.
 
-    >>> print roles.in_admin
+    >>> print(roles.in_admin)
     False
-    >>> print roles.in_janitor
+    >>> print(roles.in_janitor)
     False
 
     >>> janitor = getUtility(ILaunchpadCelebrities).janitor
     >>> janitor_roles = IPersonRoles(janitor)
-    >>> print janitor_roles.in_janitor
+    >>> print(janitor_roles.in_janitor)
     True
 
 
@@ -81,10 +81,10 @@ be used to check for any non-celebrity team.
     >>> new_team = factory.makeTeam()
     >>> new_team.addMember(person, new_team.teamowner)
     (True, ...Approved>)
-    >>> print person.inTeam(new_team)
+    >>> print(person.inTeam(new_team))
     True
 
-    >>> print roles.inTeam(new_team)
+    >>> print(roles.inTeam(new_team))
     True
 
 
@@ -94,18 +94,18 @@ We can easily check for ownership and drivership. If an object
 provides IHasDrivers, its ancestors' drivers will be checked too.
 
     >>> product = factory.makeProduct(owner=person)
-    >>> print roles.isOwner(product)
+    >>> print(roles.isOwner(product))
     True
 
     >>> driver = factory.makePerson()
     >>> driver_roles = IPersonRoles(driver)
-    >>> print driver_roles.isDriver(product)
+    >>> print(driver_roles.isDriver(product))
     False
     >>> product.driver = driver
-    >>> print driver_roles.isDriver(product)
+    >>> print(driver_roles.isDriver(product))
     True
     >>> productseries = factory.makeProductSeries(product=product)
-    >>> print driver_roles.isDriver(productseries)
+    >>> print(driver_roles.isDriver(productseries))
     True
 
 
@@ -116,7 +116,7 @@ method isOneOf makes checking all of these a breeze.
 
     >>> spec = factory.makeSpecification()
     >>> spec.assignee = person
-    >>> print roles.isOwner(spec)
+    >>> print(roles.isOwner(spec))
     False
-    >>> print roles.isOneOf(spec, ['owner', 'approver', 'assignee'])
+    >>> print(roles.isOneOf(spec, ['owner', 'approver', 'assignee']))
     True
diff --git a/lib/lp/registry/doc/pillar.txt b/lib/lp/registry/doc/pillar.txt
index f92a318..65040f5 100644
--- a/lib/lp/registry/doc/pillar.txt
+++ b/lib/lp/registry/doc/pillar.txt
@@ -193,8 +193,8 @@ Distributions.
 
     >>> for row in pillar_set.search(
     ...         getUtility(ILaunchBag).user, 'mozilla', limit=3):
-    ...     print ("%s: %s (%s)"
-    ...            % (row.__class__.__name__, row.title, row.name))
+    ...     print("%s: %s (%s)"
+    ...           % (row.__class__.__name__, row.title, row.name))
     ProjectGroup: The Mozilla Project (mozilla)
     Product: Mozilla Firefox (firefox)
     Product: Mozilla Thunderbird (thunderbird)
@@ -205,8 +205,8 @@ Distributions.
     <Product ...>
     >>> for row in pillar_set.search(
     ...         getUtility(ILaunchBag).user, 'ubuntu', limit=6):
-    ...     print ("%s: %s (%s)"
-    ...            % (row.__class__.__name__, row.title, row.name))
+    ...     print("%s: %s (%s)"
+    ...           % (row.__class__.__name__, row.title, row.name))
     Distribution: Ubuntu (ubuntu)
     Product: Ubuntu-sekrit (ubuntu-sekrit)
     Distribution: ubuntutest (ubuntutest)
@@ -218,8 +218,8 @@ We can search by any of the pillar's aliases too.
 
     >>> for row in pillar_set.search(
     ...         getUtility(ILaunchBag).user, 'iceweasel', limit=5):
-    ...     print ("%s: %s (%s)"
-    ...            % (row.__class__.__name__, row.title, row.name))
+    ...     print("%s: %s (%s)"
+    ...           % (row.__class__.__name__, row.title, row.name))
     Product: Mozilla Firefox (firefox)
 
 Note that inaccessible private or inactive products and projects won't
@@ -231,15 +231,15 @@ be included in the results.
 
     >>> for row in pillar_set.search(
     ...         getUtility(ILaunchBag).user, 'mozilla', limit=3):
-    ...     print ("%s: %s (%s)"
-    ...            % (row.__class__.__name__, row.title, row.name))
+    ...     print("%s: %s (%s)"
+    ...           % (row.__class__.__name__, row.title, row.name))
     ProjectGroup: The Mozilla Project (mozilla)
     Product: Mozilla Thunderbird (thunderbird)
 
     >>> for row in pillar_set.search(
     ...         getUtility(ILaunchBag).user, 'ubuntu', limit=6):
-    ...     print ("%s: %s (%s)"
-    ...            % (row.__class__.__name__, row.title, row.name))
+    ...     print("%s: %s (%s)"
+    ...           % (row.__class__.__name__, row.title, row.name))
     Distribution: Ubuntu (ubuntu)
     Distribution: ubuntutest (ubuntutest)
     Product: Evolution (evolution)
diff --git a/lib/lp/registry/doc/private-team-roles.txt b/lib/lp/registry/doc/private-team-roles.txt
index e4862ce..6919c9d 100644
--- a/lib/lp/registry/doc/private-team-roles.txt
+++ b/lib/lp/registry/doc/private-team-roles.txt
@@ -51,7 +51,7 @@ A private team can be the assignee for a bug task.
 
     >>> bugtask = bug.default_bugtask
     >>> bugtask.transitionToAssignee(priv_team)
-    >>> print bugtask.assignee.name
+    >>> print(bugtask.assignee.name)
     private-team
 
 Branches
@@ -80,7 +80,7 @@ Private teams can subscribe to branches.
     ...     BranchSubscriptionNotificationLevel.DIFFSONLY,
     ...     BranchSubscriptionDiffSize.WHOLEDIFF,
     ...     CodeReviewNotificationLevel.STATUS, team_owner)
-    >>> print subscription.person.name
+    >>> print(subscription.person.name)
     private-team
 
 
@@ -106,7 +106,7 @@ Private teams can subscribe to Git repositories.
     ...     BranchSubscriptionNotificationLevel.DIFFSONLY,
     ...     BranchSubscriptionDiffSize.WHOLEDIFF,
     ...     CodeReviewNotificationLevel.STATUS, team_owner)
-    >>> print subscription.person.name
+    >>> print(subscription.person.name)
     private-team
 
 
@@ -304,13 +304,13 @@ Mixing public and private teams can create interesting situations.
     ...                               visibility=joined_type)
     ...     joiner = factory.makeTeam(owner=team_owner,
     ...                               visibility=joiner_type)
-    ...     print "%s <- %s: " % (joined_type, joiner_type),
+    ...     print("%s <- %s: " % (joined_type, joiner_type), end="")
     ...     try:
     ...         joined.addMember(joiner, reviewer=reviewer)
     ...     except PrivatePersonLinkageError:
-    ...         print "Not Allowed"
+    ...         print("Not Allowed")
     ...     else:
-    ...         print "Allowed"
+    ...         print("Allowed")
 
     >>> public = PersonVisibility.PUBLIC
     >>> private = PersonVisibility.PRIVATE
@@ -320,7 +320,7 @@ Mixing public and private teams can create interesting situations.
     >>> for joined in visibility_list:
     ...     for joiner in visibility_list:
     ...         join_team(joined, joiner)
-    ...     print "---"
+    ...     print("---")
     Public <- Public:  Allowed
     Public <- Private: Allowed
     ---
diff --git a/lib/lp/registry/doc/product-widgets.txt b/lib/lp/registry/doc/product-widgets.txt
index e08d8d8..20cd4a5 100644
--- a/lib/lp/registry/doc/product-widgets.txt
+++ b/lib/lp/registry/doc/product-widgets.txt
@@ -39,7 +39,7 @@ in a specified external location.
 
 Firefox has not yet selected a bug tracker.
 
-    >>> print firefox.projectgroup.bugtracker
+    >>> print(firefox.projectgroup.bugtracker)
     None
 
     >>> from bs4.element import Tag
@@ -51,9 +51,9 @@ Firefox has not yet selected a bug tracker.
     ...     for label in labels:
     ...         control = label.previous.previous
     ...         if control['type'] == 'radio' and control.get('checked'):
-    ...             print '[X]', extract_text(label)
+    ...             print('[X]', extract_text(label))
     ...         elif control['type'] == 'radio':
-    ...             print '[ ]', extract_text(label)
+    ...             print('[ ]', extract_text(label))
     ...         else:
     ...             pass
     >>> print_items(widget())
@@ -141,7 +141,7 @@ Launchpad.
 The bugtracker value passed to the widget caused the sub-widget used to select
 the bug tracker to have the correct value.
 
-    >>> print widget.bugtracker_widget.getInputValue().name
+    >>> print(widget.bugtracker_widget.getInputValue().name)
     debbugs
 
 By indicating an external bug tracker, the selected bug tracker will be
@@ -152,13 +152,13 @@ returned.
     ...     product_bugtracker, product_bugtracker.vocabulary,
     ...     LaunchpadTestRequest(form=form))
     >>> debbugs = widget.getInputValue()
-    >>> print debbugs.name
+    >>> print(debbugs.name)
     debbugs
 
 The sub-widget for selecting the external bug tracker also has debbugs as its
 input value.
 
-    >>> print widget.getInputValue().name
+    >>> print(widget.getInputValue().name)
     debbugs
 
 The project's bug tracker, or no bug tracker, at all is selected.
@@ -167,7 +167,7 @@ The project's bug tracker, or no bug tracker, at all is selected.
     >>> widget = ProductBugTrackerWidget(
     ...     product_bugtracker, product_bugtracker.vocabulary,
     ...     LaunchpadTestRequest(form=form))
-    >>> print widget.getInputValue()
+    >>> print(widget.getInputValue())
     None
 
 We can't use the value returned from getInputValue() to set an attribute on
@@ -180,7 +180,7 @@ marker object.
 
     >>> firefox.official_malone
     True
-    >>> print firefox.bugtracker
+    >>> print(firefox.bugtracker)
     None
     >>> product_bugtracker.get(firefox) is product_bugtracker.malone_marker
     True
@@ -192,7 +192,7 @@ set the bug tracker.
     >>> product_bugtracker.set(firefox, debbugs)
     >>> firefox.official_malone
     False
-    >>> print firefox.bugtracker.name
+    >>> print(firefox.bugtracker.name)
     debbugs
 
 Choosing to use Malone again, the changes above will be reverted.
@@ -200,7 +200,7 @@ Choosing to use Malone again, the changes above will be reverted.
     >>> product_bugtracker.set(firefox, product_bugtracker.malone_marker)
     >>> firefox.official_malone
     True
-    >>> print firefox.bugtracker
+    >>> print(firefox.bugtracker)
     None
 
 Passing None to the field's set method, Firefox will once again switch to not
@@ -209,7 +209,7 @@ using Malone, and its bug tracker will be set to None.
     >>> product_bugtracker.set(firefox, None)
     >>> firefox.official_malone
     False
-    >>> print firefox.bugtracker
+    >>> print(firefox.bugtracker)
     None
 
 The ProductBugTrackerWidget renders two fields that are subordinate to
@@ -221,8 +221,8 @@ the 4 choices.
     ...     for control in controls:
     ...         if control['type'] != 'hidden':
     ...             if 'subordinate' in control.parent.get('class', ''):
-    ...                 print '--'
-    ...             print control['id'], control['type']
+    ...                 print('--')
+    ...             print(control['id'], control['type'])
 
     >>> print_controls(widget())
     field.bugtracker.0 radio
@@ -257,7 +257,7 @@ presented ordered to appear in a 3 column list.
     >>> from lp.testing.pages import find_tag_by_id
 
     >>> html = license_widget()
-    >>> print extract_text(find_tag_by_id(html, 'recommended'))
+    >>> print(extract_text(find_tag_by_id(html, 'recommended')))
     Apache Licence view licence
     GNU Affero GPL v3 view licence
     GNU LGPL v2.1 view licence
@@ -268,7 +268,7 @@ presented ordered to appear in a 3 column list.
     GNU GPL v3 view licence
     MIT / X / Expat Licence view licence
 
-    >>> print extract_text(find_tag_by_id(html, 'more'))
+    >>> print(extract_text(find_tag_by_id(html, 'more')))
     Academic Free Licence view licence
     Eclipse Public Licence view licence
     PHP Licence view licence
@@ -287,14 +287,14 @@ presented ordered to appear in a 3 column list.
     Open Software Licence v 3.0 view licence
 
 
-    >>> print extract_text(find_tag_by_id(html, 'special'))
+    >>> print(extract_text(find_tag_by_id(html, 'special')))
     I don't know yet
     Other/Proprietary
     Other/Open Source
 
 There is a deprecated section that is generally not visible...
 
-    >>> print find_tag_by_id(html, 'deprecated')
+    >>> print(find_tag_by_id(html, 'deprecated'))
     None
 
 ...unless the old "Perl licence" is selected.
@@ -303,7 +303,7 @@ There is a deprecated section that is generally not visible...
     >>> request = LaunchpadTestRequest(form=form)
     >>> license_widget = LicenseWidget(licenses_field, vtype, request)
     >>> html = license_widget()
-    >>> print extract_text(find_tag_by_id(html, 'deprecated'))
+    >>> print(extract_text(find_tag_by_id(html, 'deprecated')))
     Perl Licence
 
 One licence, the GNU GPL v2, is selected.
@@ -318,14 +318,14 @@ One licence, the GNU GPL v2, is selected.
     ...         if not isinstance(label.next, Tag):
     ...             continue
     ...         if label.next.get('checked'):
-    ...             print '[X]',
+    ...             print('[X]', end=' ')
     ...         else:
-    ...             print '[ ]',
-    ...         print extract_text(label),
+    ...             print('[ ]', end=' ')
+    ...         print(extract_text(label), end='')
     ...         if links and label.a is not None:
-    ...             print '<%s>' % label.a.get('href')
+    ...             print(' <%s>' % label.a.get('href'))
     ...         else:
-    ...             print
+    ...             print()
 
     >>> for item in license_widget.getInputValue():
     ...     print(repr(item))
diff --git a/lib/lp/registry/doc/product.txt b/lib/lp/registry/doc/product.txt
index 088eaa7..ed35ae8 100644
--- a/lib/lp/registry/doc/product.txt
+++ b/lib/lp/registry/doc/product.txt
@@ -94,13 +94,13 @@ translatable for that product:
 
 We can also see how many translatables it has:
 
-    >>> print [series.displayname for series in evo.translatable_series]
+    >>> print([series.displayname for series in evo.translatable_series])
     [u'trunk']
 
 But for a52dec, where we have no translatable series or Ubuntu package, the
 primary_translatable is nonexistent:
 
-    >>> print a52dec.primary_translatable
+    >>> print(a52dec.primary_translatable)
     None
 
 Now, to test the active flag. If we disabled a product:
@@ -124,7 +124,7 @@ But it should be retrievable via getByname().
 
 getByName() also accepts an argument to ignore inactive products.
 
-    >>> print productset.getByName('a52dec', ignore_inactive=True)
+    >>> print(productset.getByName('a52dec', ignore_inactive=True))
     None
 
 You can also use the IProductSet to see some statistics on products.
@@ -144,11 +144,11 @@ ILaunchpadStatisticSet is stored in the 'stats' attribute.
     ...     """Provide fake statistics, not to depend on sample data."""
     ...     stats = FakeStatistics()
 
-    >>> print FakeStatsProductSet().count_translatable()
+    >>> print(FakeStatsProductSet().count_translatable())
     1000
-    >>> print FakeStatsProductSet().count_buggy()
+    >>> print(FakeStatsProductSet().count_buggy())
     2000
-    >>> print FakeStatsProductSet().count_reviewed()
+    >>> print(FakeStatsProductSet().count_reviewed())
     3000
 
 IProductSet can also retrieve the latest products registered.  By
@@ -157,7 +157,7 @@ default the latest five are returned.
     >>> latest = productset.latest(None)
     >>> projects = [project.displayname for project in latest]
     >>> for project in sorted(projects):
-    ...     print project
+    ...     print(project)
     Bazaar
     Derby
     Mega Money Maker
@@ -170,7 +170,7 @@ returned.
     >>> latest = productset.latest(None, quantity=3)
     >>> projects = [project.displayname for project in latest]
     >>> for project in sorted(projects):
-    ...     print project
+    ...     print(project)
     Derby
     Mega Money Maker
     Obsolete Junk
@@ -182,7 +182,7 @@ Translatable Products
 IProductSet will also tell us which products can be translated:
 
     >>> for product in productset.getTranslatables():
-    ...    print product.name
+    ...    print(product.name)
     evolution
     alsa-utils
 
@@ -193,7 +193,7 @@ Only active products are listed as translatables.
     >>> unlink_source_packages(evo)
     >>> evo.active = False
     >>> for product in productset.getTranslatables():
-    ...    print product.name
+    ...    print(product.name)
     alsa-utils
 
     >>> evo.active = True
@@ -233,7 +233,7 @@ one.
     >>> firefox = getUtility(IProductSet).getByName('firefox')
     >>> firefox.bug_tracking_usage
     <DBItem ServiceUsage.LAUNCHPAD, (20) Launchpad>
-    >>> print firefox.bug_tracking_usage.name
+    >>> print(firefox.bug_tracking_usage.name)
     LAUNCHPAD
     >>> firefox.getExternalBugTracker() is None
     True
@@ -255,7 +255,7 @@ tracker will be returned.
     >>> firefox.official_malone = False
     >>> firefox.bugtracker is None
     True
-    >>> print firefox.bug_tracking_usage.name
+    >>> print(firefox.bug_tracking_usage.name)
     UNKNOWN
     >>> firefox.getExternalBugTracker().name
     u'gnome-bugzilla'
@@ -268,7 +268,7 @@ specify its own.
     >>> firefox.bugtracker = debbugs
     >>> firefox.getExternalBugTracker().name
     u'debbugs'
-    >>> print firefox.bug_tracking_usage.name
+    >>> print(firefox.bug_tracking_usage.name)
     EXTERNAL
 
 
@@ -287,12 +287,12 @@ Answer Tracking
 Firefox uses the Answer Tracker as the official application to provide
 answers to questions.
 
-    >>> print firefox.answers_usage.name
+    >>> print(firefox.answers_usage.name)
     LAUNCHPAD
 
 Alsa does not use Launchpad to track answers.
 
-    >>> print alsa.answers_usage.name
+    >>> print(alsa.answers_usage.name)
     UNKNOWN
 
 Product Creation
@@ -319,7 +319,7 @@ When creating a product, a default product series is created for it:
     >>> product.series.count()
     1
     >>> trunk = product.series[0]
-    >>> print trunk.name
+    >>> print(trunk.name)
     trunk
 
 This series is set as the development focus for the product:
@@ -335,14 +335,14 @@ We should be able to set whether or not a Product uses specifications
 officially.  It defaults to UNKNOWN.
 
     >>> firefox = productset.getByName('firefox')
-    >>> print firefox.blueprints_usage.name
+    >>> print(firefox.blueprints_usage.name)
     UNKNOWN
 
 We can change it to use LAUNCHPAD.
 
     >>> from lp.app.enums import ServiceUsage
     >>> firefox.blueprints_usage = ServiceUsage.LAUNCHPAD
-    >>> print firefox.blueprints_usage.name
+    >>> print(firefox.blueprints_usage.name)
     LAUNCHPAD
 
 We should be able to get lists of specifications in different states
@@ -358,7 +358,7 @@ First, there should be only one informational spec for firefox:
 
     >>> filter = [SpecificationFilter.INFORMATIONAL]
     >>> for spec in firefox.specifications(None, filter=filter):
-    ...    print spec.name
+    ...    print(spec.name)
     extension-manager-upgrades
 
 
@@ -366,7 +366,7 @@ There are no completed specs for firefox:
 
     >>> filter = [SpecificationFilter.COMPLETE]
     >>> for spec in firefox.specifications(None, filter=filter):
-    ...    print spec.name
+    ...    print(spec.name)
 
 
 And there are five incomplete specs:
@@ -378,7 +378,7 @@ And there are five incomplete specs:
 We can filter for specifications that contain specific text:
 
     >>> for spec in firefox.specifications(None, filter=[u'new']):
-    ...     print spec.name
+    ...     print(spec.name)
     canvas
     e4x
 
@@ -406,7 +406,7 @@ registry experts, or admins.
 They're ordered by dateexpected.
 
     >>> for milestone in firefox.milestones:
-    ...     print '%-7s %s' % (milestone.name, milestone.dateexpected)
+    ...     print('%-7s %s' % (milestone.name, milestone.dateexpected))
     1.0     2056-10-16
     1.0-rc1 2018-10-01
 
@@ -429,7 +429,7 @@ Release
 All the releases for a Product can be retrieved through the releases property.
 
     >>> for release in firefox.releases:
-    ...     print release.version
+    ...     print(release.version)
     0.9
     0.9.1
     0.9.2
@@ -439,7 +439,7 @@ A single release can be retrieved via the getRelease() method by passing the
 version argument.
 
     >>> release = firefox.getRelease('0.9.1')
-    >>> print release.version
+    >>> print(release.version)
     0.9.1
 
 
@@ -450,16 +450,16 @@ Products are considered to officially support Launchpad as a location
 for their branches after a branch is set for the development focus
 series.
 
-    >>> print firefox.development_focus.branch
+    >>> print(firefox.development_focus.branch)
     None
-    >>> print firefox.official_codehosting
+    >>> print(firefox.official_codehosting)
     False
-    >>> print firefox.codehosting_usage.name
+    >>> print(firefox.codehosting_usage.name)
     UNKNOWN
     >>> firefox.development_focus.branch = factory.makeBranch(product=firefox)
-    >>> print firefox.official_codehosting
+    >>> print(firefox.official_codehosting)
     True
-    >>> print firefox.codehosting_usage.name
+    >>> print(firefox.codehosting_usage.name)
     LAUNCHPAD
 
 We can also find all the products that have branches.
@@ -467,7 +467,7 @@ We can also find all the products that have branches.
     >>> productset.getProductsWithBranches().count()
     6
     >>> for product in productset.getProductsWithBranches():
-    ...     print product.name
+    ...     print(product.name)
     evolution
     firefox
     gnome-terminal
@@ -494,7 +494,7 @@ no longer appear in the result set.
     ...     branch.lifecycle_status = BranchLifecycleStatus.ABANDONED
 
     >>> for product in productset.getProductsWithBranches():
-    ...     print product.name
+    ...     print(product.name)
     evolution
     firefox
     gnome-terminal
@@ -505,7 +505,7 @@ The getProductsWithBranches method takes an optional parameter that limits
 the number of products returned.
 
     >>> for product in productset.getProductsWithBranches(3):
-    ...     print product.name
+    ...     print(product.name)
     evolution
     firefox
     gnome-terminal
@@ -514,7 +514,7 @@ Only active products are returned.
 
     >>> evo.active = False
     >>> for product in productset.getProductsWithBranches():
-    ...     print product.name
+    ...     print(product.name)
     firefox
     gnome-terminal
     iso-codes
@@ -529,15 +529,15 @@ their code if they have a default Git repository.
 
     >>> from lp.code.interfaces.gitrepository import IGitRepositorySet
     >>> firefox.development_focus.branch = None
-    >>> print firefox.official_codehosting
+    >>> print(firefox.official_codehosting)
     False
-    >>> print firefox.codehosting_usage.name
+    >>> print(firefox.codehosting_usage.name)
     UNKNOWN
     >>> getUtility(IGitRepositorySet).setDefaultRepository(
     ...     firefox, factory.makeGitRepository(target=firefox))
-    >>> print firefox.official_codehosting
+    >>> print(firefox.official_codehosting)
     True
-    >>> print firefox.codehosting_usage.name
+    >>> print(firefox.codehosting_usage.name)
     LAUNCHPAD
 
 
@@ -566,18 +566,18 @@ Firefox has two series, but no translatable series either:
 
     >>> firefox = productset.getByName('firefox')
     >>> for firefoxseries in firefox.series:
-    ...     print '%s %s' % (
+    ...     print('%s %s' % (
     ...         firefoxseries.displayname,
-    ...         list(firefoxseries.getCurrentTranslationTemplates()))
+    ...         list(firefoxseries.getCurrentTranslationTemplates())))
     1.0 []
     trunk []
-    >>> print firefox.primary_translatable
+    >>> print(firefox.primary_translatable)
     None
 
 Development focus series for Firefox is trunk.
 
     >>> firefox_trunk = firefox.development_focus
-    >>> print firefox_trunk.displayname
+    >>> print(firefox_trunk.displayname)
     trunk
 
 But, there's also a 1.0 series for Firefox.
@@ -600,7 +600,7 @@ translations are available.
 
 The primary_translatable now points at firefox 1.0:
 
-    >>> print firefox.primary_translatable.displayname
+    >>> print(firefox.primary_translatable.displayname)
     1.0
 
 If we associate a potemplate with Firefox trunk, it will become the primary
@@ -612,13 +612,13 @@ translatable because it's a series with development focus.
     ...                                          'firefox',
     ...                                          'firefox.pot',
     ...                                          translations_admin)
-    >>> print firefox.primary_translatable.displayname
+    >>> print(firefox.primary_translatable.displayname)
     trunk
 
 If we change the development_focus, primary_translatable changes as well.
 
     >>> firefox.development_focus = firefox_10
-    >>> print firefox.primary_translatable.displayname
+    >>> print(firefox.primary_translatable.displayname)
     1.0
 
 
@@ -631,7 +631,7 @@ exception that the current development focus is first.
     >>> firefox_view = create_initialized_view(firefox, '+index')
     >>> sorted_series = firefox_view.sorted_series_list
     >>> for series in sorted_series:
-    ...     print series.name
+    ...     print(series.name)
     1.0
     trunk
 
@@ -644,7 +644,7 @@ view to see the data change reflected.
     >>> firefox_view = create_initialized_view(firefox, '+index')
     >>> sorted_series = firefox_view.sorted_series_list
     >>> for series in sorted_series:
-    ...     print series.name
+    ...     print(series.name)
     trunk
     1.0
 
@@ -653,7 +653,7 @@ It is also possible to view just the set of sorted active series.
     >>> firefox_view = create_initialized_view(firefox, '+index')
     >>> sorted_series = firefox_view.sorted_active_series_list
     >>> for series in sorted_series:
-    ...     print series.name
+    ...     print(series.name)
     trunk
     1.0
 
@@ -666,7 +666,7 @@ sorted active series.
     >>> last_series.status = SeriesStatus.OBSOLETE
     >>> firefox_view = create_initialized_view(firefox, '+index')
     >>> for series in firefox_view.sorted_active_series_list:
-    ...     print series.name
+    ...     print(series.name)
     trunk
 
 It is possible for the development series to be obsolete, and in that case, it
@@ -675,7 +675,7 @@ still shows up in the list.
     >>> firefox.development_focus.status = SeriesStatus.OBSOLETE
     >>> firefox_view = create_initialized_view(firefox, '+index')
     >>> for series in firefox_view.sorted_active_series_list:
-    ...     print series.name
+    ...     print(series.name)
     trunk
 
 
@@ -684,15 +684,15 @@ Changing ownership
 
 A product owner can be changed by the current owner.
 
-    >>> print firefox.owner.name
+    >>> print(firefox.owner.name)
     name12
 
     >>> mark = getUtility(IPersonSet).getByEmail('mark@xxxxxxxxxxx')
-    >>> print mark.name
+    >>> print(mark.name)
     mark
 
     >>> ignored = login_person(firefox.owner)
     >>> firefox.owner = mark
 
-    >>> print firefox.owner.name
+    >>> print(firefox.owner.name)
     mark
diff --git a/lib/lp/registry/doc/productrelease-file-download.txt b/lib/lp/registry/doc/productrelease-file-download.txt
index 0c83563..034c8ef 100644
--- a/lib/lp/registry/doc/productrelease-file-download.txt
+++ b/lib/lp/registry/doc/productrelease-file-download.txt
@@ -41,7 +41,7 @@ Pick the first release from the set.
 
     >>> rel = list(releases)[0]
     >>> files = rel.files
-    >>> print files.count()
+    >>> print(files.count())
     1
 
 Add a file alias to the productrelease.
@@ -68,23 +68,23 @@ Add a file alias to the productrelease.
     >>> product_release_file = add_release_file(
     ...    rel, b'Some useful information.',
     ...    'foo.txt', 'Foo file')
-    >>> print product_release_file.description
+    >>> print(product_release_file.description)
     Foo file
 
 The number of files in the ProductRelease has increased.
 
-    >>> print rel.files.count()
+    >>> print(rel.files.count())
     2
 
 The number of files on the series has increased
 
-    >>> print len(trunk.release_files)
+    >>> print(len(trunk.release_files))
     2
 
 The alias can be retrieved by name.
 
     >>> file_alias = rel.getFileAliasByName('foo.txt')
-    >>> print file_alias.filename
+    >>> print(file_alias.filename)
     foo.txt
 
 Attempting to retrieve an alias that does not exist is an error.
@@ -98,7 +98,7 @@ Attempting to retrieve an alias that does not exist is an error.
 The ProductReleaseFile can also be retrieved by name.
 
     >>> prf = rel.getProductReleaseFileByName('foo.txt')
-    >>> print prf.libraryfile.filename
+    >>> print(prf.libraryfile.filename)
     foo.txt
 
 Attempting to retrieve a ProductReleaseFile  that does not exist is an
@@ -125,7 +125,7 @@ delete a product file.
     ...     if release_file.libraryfile.id == file_alias.id:
     ...         release_file.destroySelf()
     ...         break
-    >>> print rel.files.count()
+    >>> print(rel.files.count())
     1
 
 The deleted release file will no longer appear in ProductRelease.files.
@@ -159,7 +159,7 @@ reverse order.
     >>> releases = release_set.getReleasesForSeries(series)
     >>> for release in releases:
     ...     date = release.datereleased.strftime('%Y-%m-%d %H:%M:%S')
-    ...     print release.version, date
+    ...     print(release.version, date)
     0.9.2 2004-10-15 18:32:35
     0.9.1 2004-10-15 18:31:19
     0.9 2004-10-15 18:27:09
@@ -184,7 +184,7 @@ Let's add some release files to the releases for firefox.
 
     >>> files = release_set.getFilesForReleases(releases)
     >>> for file in files:
-    ...     print file.libraryfile.filename
+    ...     print(file.libraryfile.filename)
     name3
     name2
     name1
@@ -206,7 +206,7 @@ Only the product owner can create a new release.
     ...                                changelog='New in v2')
     <ProductRelease at ...>
     >>> for release in release_set.getReleasesForSeries(series):
-    ...     print release.version
+    ...     print(release.version)
     8.0
     0.9.2
     0.9.1
diff --git a/lib/lp/registry/doc/productrelease.txt b/lib/lp/registry/doc/productrelease.txt
index 132cfb7..b2ed7ad 100644
--- a/lib/lp/registry/doc/productrelease.txt
+++ b/lib/lp/registry/doc/productrelease.txt
@@ -46,7 +46,7 @@ as it doesn't have any IProductReleaseFiles associated with it.
     >>> firefox_109.files.count()
     0
     >>> firefox_109.destroySelf()
-    >>> print firefox_1_0.getRelease('1.0.9')
+    >>> print(firefox_1_0.getRelease('1.0.9'))
     None
 
 If a product release has files associated with it, though, it can't be
diff --git a/lib/lp/registry/doc/productseries.txt b/lib/lp/registry/doc/productseries.txt
index e9b90f9..dc7f9fb 100644
--- a/lib/lp/registry/doc/productseries.txt
+++ b/lib/lp/registry/doc/productseries.txt
@@ -44,7 +44,7 @@ And verify that it looks like the series we think it should be.
 
     >>> trunk.product == firefox
     True
-    >>> print trunk.name
+    >>> print(trunk.name)
     trunk
 
 It's also possible to ask a product for all its associated series.
@@ -58,9 +58,9 @@ A ProductSeries can also be fetched with the IProductSeriesSet utility.
     >>> from lp.registry.interfaces.productseries import IProductSeriesSet
 
     >>> firefox_1_0 = getUtility(IProductSeriesSet).get(2)
-    >>> print firefox_1_0.product.name
+    >>> print(firefox_1_0.product.name)
     firefox
-    >>> print firefox_1_0.name
+    >>> print(firefox_1_0.name)
     1.0
 
 New ProductSeries are created using Product.newSeries(). Only the product
@@ -78,13 +78,13 @@ owner or driver can call Product.newSeries().
     >>> emacs_series = firefox.newSeries(
     ...     firefox.owner , 'emacs', summary,
     ...     releasefileglob='ftp://gnu.org/emacs*.gz')
-    >>> print emacs_series.name
+    >>> print(emacs_series.name)
     emacs
 
-    >>> print emacs_series.summary
+    >>> print(emacs_series.summary)
     Port of Firefox to the Emacs operating system.
 
-    >>> print emacs_series.releasefileglob
+    >>> print(emacs_series.releasefileglob)
     ftp://gnu.org/emacs*.gz
 
 When a driver creates a series, they are also the driver of the new series
@@ -93,13 +93,13 @@ to make them the release manager.
     >>> firefox.driver = series_driver
     >>> ignored = login_person(series_driver)
     >>> emacs2 = firefox.newSeries(series_driver , 'emacs2', summary)
-    >>> print emacs2.driver.name
+    >>> print(emacs2.driver.name)
     driver
 
 A newly created series is assumed to be in the development state.
 
     >>> login(ANONYMOUS)
-    >>> print emacs_series.status.title
+    >>> print(emacs_series.status.title)
     Active Development
 
 Let's check that the new series is properly associated to its product.
@@ -234,7 +234,7 @@ If we ask for ALL specs we should see them both.
 
     >>> filter = [SpecificationFilter.ALL]
     >>> for s in onezero.specifications(None, filter=filter):
-    ...     print s.name
+    ...     print(s.name)
     a
     b
 
@@ -243,7 +243,7 @@ specs:
 
     >>> filter=[SpecificationFilter.ACCEPTED]
     >>> for spec in onezero.specifications(None, filter=filter):
-    ...     print spec.name, spec.goalstatus.title
+    ...     print(spec.name, spec.goalstatus.title)
     a Accepted
 
     >>> filter=[SpecificationFilter.PROPOSED]
@@ -259,7 +259,7 @@ accepted one.
 
     >>> filter = [SpecificationFilter.INFORMATIONAL]
     >>> for s in onezero.specifications(None, filter=filter):
-    ...     print s.name
+    ...     print(s.name)
     a
 
 If we specifically ask for declined informational, we will get that:
@@ -267,21 +267,21 @@ If we specifically ask for declined informational, we will get that:
     >>> filter = [
     ...    SpecificationFilter.INFORMATIONAL, SpecificationFilter.DECLINED]
     >>> for s in onezero.specifications(None, filter=filter):
-    ...     print s.name
+    ...     print(s.name)
     b
 
 There are is one completed, accepted spec for 1.0:
 
     >>> filter = [SpecificationFilter.COMPLETE]
     >>> for spec in onezero.specifications(None, filter=filter):
-    ...    print spec.name, spec.is_complete, spec.goalstatus.title
+    ...    print(spec.name, spec.is_complete, spec.goalstatus.title)
     a True Accepted
 
 There is one completed, declined spec:
 
     >>> filter = [SpecificationFilter.COMPLETE, SpecificationFilter.DECLINED]
     >>> for spec in onezero.specifications(None, filter=filter):
-    ...    print spec.name, spec.is_complete, spec.goalstatus.title
+    ...    print(spec.name, spec.is_complete, spec.goalstatus.title)
     b True Declined
 
 Now lets make b incomplete, but accepted.
@@ -296,14 +296,14 @@ And if we ask just for specs, we get BOTH the incomplete and the
 complete ones that have been accepted.
 
     >>> for spec in onezero.specifications(None):
-    ...     print spec.name, spec.is_complete, spec.goalstatus.title
+    ...     print(spec.name, spec.is_complete, spec.goalstatus.title)
     a True Accepted
     b False Accepted
 
 We can search for text in specifications (in this case there are no
 matches):
 
-    >>> print len(list(onezero.specifications(None, filter=[u'new'])))
+    >>> print(len(list(onezero.specifications(None, filter=[u'new']))))
     0
 
 
@@ -326,7 +326,7 @@ change the overall state of the spec to "completed".
     >>> jdub = getUtility(IPersonSet).getByName('jdub')
     >>> b.definition_status = SpecificationDefinitionStatus.APPROVED
     >>> b.implementation_status = SpecificationImplementationStatus.INFORMATIONAL
-    >>> print b.updateLifecycleStatus(jdub).title
+    >>> print(b.updateLifecycleStatus(jdub).title)
     Complete
     >>> b.completer.name
     u'jdub'
@@ -387,10 +387,10 @@ anything actually set.
 If there is a project group on the product, we would expect the project
 group owner:
 
-    >>> print series.product.projectgroup.name
+    >>> print(series.product.projectgroup.name)
     testproj
     >>> for d in series.drivers:
-    ...     print d.name
+    ...     print(d.name)
     carlos
 
 If there is NO project group on the product, then we expect the product
@@ -398,7 +398,7 @@ owner:
 
     >>> product.projectgroup = None
     >>> for d in series.drivers:
-    ...     print d.name
+    ...     print(d.name)
     mark
 
 Now let's put the project group back:
@@ -416,14 +416,14 @@ series.
 
     >>> projectgroup.driver = edgar
     >>> for d in series.drivers:
-    ...     print d.name
+    ...     print(d.name)
     edgar
 
 In addition cprov is made driver of the series. Both are drivers now.
 
     >>> series.driver = cprov
     >>> for d in series.drivers:
-    ...     print d.name
+    ...     print(d.name)
     cprov
     edgar
 
@@ -432,7 +432,7 @@ as driver, too.
 
     >>> projectgroup.driver = None
     >>> for d in series.drivers:
-    ...     print d.name
+    ...     print(d.name)
     carlos
     cprov
 
@@ -440,6 +440,6 @@ Without a project group, the driver role falls back to the product owner.
 
     >>> product.projectgroup = None
     >>> for d in series.drivers:
-    ...     print d.name
+    ...     print(d.name)
     cprov
     mark
diff --git a/lib/lp/registry/doc/projectgroup.txt b/lib/lp/registry/doc/projectgroup.txt
index fcbe5d1..e9519d6 100644
--- a/lib/lp/registry/doc/projectgroup.txt
+++ b/lib/lp/registry/doc/projectgroup.txt
@@ -112,7 +112,7 @@ IProjectGroupSet.getByName(), though.
 getByName() also accepts an argument to ignore inactive projects.
 
     >>> projectgroups = getUtility(IProjectGroupSet)
-    >>> print projectgroups.getByName('gnome', ignore_inactive=True)
+    >>> print(projectgroups.getByName('gnome', ignore_inactive=True))
     None
 
 Products which are part of a project
@@ -155,7 +155,7 @@ First, there should be only one informational spec for mozilla:
 
     >>> filter = [SpecificationFilter.INFORMATIONAL]
     >>> for spec in mozilla.specifications(None, filter=filter):
-    ...    print spec.name
+    ...    print(spec.name)
     extension-manager-upgrades
 
 
@@ -163,7 +163,7 @@ There are no completed specs for mozilla:
 
     >>> filter = [SpecificationFilter.COMPLETE]
     >>> for spec in mozilla.specifications(None, filter=filter):
-    ...    print spec.name
+    ...    print(spec.name)
 
 
 And there are five incomplete specs:
@@ -175,7 +175,7 @@ And there are five incomplete specs:
 We can filter for specifications that contain specific text:
 
     >>> for spec in mozilla.specifications(None, filter=[u'install']):
-    ...     print spec.name
+    ...     print(spec.name)
     extension-manager-upgrades
 
 
@@ -206,7 +206,7 @@ We can get all the specifications via the visible_specifications property,
 and all valid specifications via the valid_specifications method:
 
     >>> for spec in mozilla.visible_specifications:
-    ...    print spec.name
+    ...    print(spec.name)
     svg-support
     canvas
     extension-manager-upgrades
@@ -214,7 +214,7 @@ and all valid specifications via the valid_specifications method:
     e4x
 
     >>> for spec in mozilla.valid_specifications():
-    ...    print spec.name
+    ...    print(spec.name)
     svg-support
     canvas
     extension-manager-upgrades
@@ -237,7 +237,7 @@ An IProjectGroupSeries object can be retrieved by IProjectGroup.getSeries.
 
 If no series with the given name exists, IProjectGroup.getSeries returns None.
 
-    >>> print mozilla.getSeries('nonsense')
+    >>> print(mozilla.getSeries('nonsense'))
     None
 
 IProjectGroupSeries.visible_specifications lists all specifications
@@ -257,20 +257,20 @@ mozilla_1_0_series.visible_specifications.
     >>> series_1_0 = firefox.getSeries('1.0')
     >>> extension_manager_upgrades.proposeGoal(series_1_0, no_priv)
     >>> for spec in mozilla_series_1_0.visible_specifications:
-    ...     print spec.name
+    ...     print(spec.name)
     extension-manager-upgrades
 
 This specification is not listed for other series.
 
     >>> mozilla_trunk = mozilla.getSeries('trunk')
-    >>> print mozilla_trunk.visible_specifications.count()
+    >>> print(mozilla_trunk.visible_specifications.count())
     0
 
 Filtered lists of project series related specifications are generated
 the same way as for project related specifications.
 
     >>> for spec in mozilla_series_1_0.specifications(None, filter=filter):
-    ...     print spec.name
+    ...     print(spec.name)
     extension-manager-upgrades
 
 If all existing specifications are assigned to the 1.0 series,...
@@ -283,7 +283,7 @@ project itself.
 
     >>> filter = [SpecificationFilter.INCOMPLETE]
     >>> for spec in mozilla_series_1_0.specifications(None, filter=filter):
-    ...     print spec.name
+    ...     print(spec.name)
     svg-support
     canvas
     extension-manager-upgrades
@@ -294,14 +294,14 @@ project itself.
 
     >>> for spec in mozilla_series_1_0.specifications(
     ...     None, filter=[u'install']):
-    ...     print spec.name
+    ...     print(spec.name)
     extension-manager-upgrades
 
 Inactive products are excluded from the series listings.
 
     >>> filter = [SpecificationFilter.INCOMPLETE]
     >>> specs = mozilla_series_1_0.specifications(None, filter=filter)
-    >>> print specs.count()
+    >>> print(specs.count())
     5
 
     >>> firefox = getUtility(IProductSet).getByName('firefox')
@@ -318,7 +318,7 @@ We can get all the specifications via the visible_specifications property,
 and all valid specifications via the valid_specifications method:
 
     >>> for spec in mozilla_series_1_0.visible_specifications:
-    ...    print spec.name
+    ...    print(spec.name)
     svg-support
     canvas
     extension-manager-upgrades
@@ -326,7 +326,7 @@ and all valid specifications via the valid_specifications method:
     e4x
 
     >>> for spec in mozilla_series_1_0.valid_specifications():
-    ...    print spec.name
+    ...    print(spec.name)
     svg-support
     canvas
     extension-manager-upgrades
@@ -367,7 +367,7 @@ It has one translatable product.
 And that translatable product is 'Evolution'.
 
     >>> evolution = translatables[0]
-    >>> print evolution.title
+    >>> print(evolution.title)
     Evolution
 
 With its 'trunk' series translatable.
@@ -376,24 +376,24 @@ With its 'trunk' series translatable.
     >>> len(evo_series)
     1
     >>> evo_trunk = evo_series[0]
-    >>> print evo_trunk.name
+    >>> print(evo_trunk.name)
     trunk
 
 That is using Rosetta officially.
 
-    >>> print evolution.translations_usage.name
+    >>> print(evolution.translations_usage.name)
     LAUNCHPAD
 
 GNOME project has also another product, netapplet.
 
     >>> netapplet = gnome.getProduct('netapplet')
-    >>> print netapplet.title
+    >>> print(netapplet.title)
     NetApplet
 
 But it was not returned from 'translatables' method because it's not using
 Rosetta officially.
 
-    >>> print netapplet.translations_usage.name
+    >>> print(netapplet.translations_usage.name)
     UNKNOWN
 
 And thus, it doesn't have any translatable series.
@@ -426,7 +426,7 @@ a project.
     >>> gnome = getUtility(IProjectGroupSet)['gnome']
     >>> milestones = gnome.milestones
     >>> for milestone in milestones:
-    ...     print milestone.name, 'active:', milestone.active
+    ...     print(milestone.name, 'active:', milestone.active)
     1.2 active: True
     1.1. active: True
     1.1 active: True
@@ -436,7 +436,7 @@ project.
 
     >>> milestones = gnome.all_milestones
     >>> for milestone in milestones:
-    ...     print milestone.name, 'active:', milestone.active
+    ...     print(milestone.name, 'active:', milestone.active)
     2.1.6 active: False
     1.0 active: False
     1.3 active: False
@@ -448,10 +448,10 @@ ProjectGroup.getMilestone(name) returns the project milestone with the name
 `name' or None, if no milestone with this name exists.
 
     >>> milestone = gnome.getMilestone('1.1')
-    >>> print milestone.name
+    >>> print(milestone.name)
     1.1
     >>> milestone = gnome.getMilestone('invalid')
-    >>> print milestone
+    >>> print(milestone)
     None
 
 For details see doc/milestone.txt and tests/test_project_milestone.py.
diff --git a/lib/lp/registry/doc/sourcepackage.txt b/lib/lp/registry/doc/sourcepackage.txt
index 9c3af77..c07d4dd 100644
--- a/lib/lp/registry/doc/sourcepackage.txt
+++ b/lib/lp/registry/doc/sourcepackage.txt
@@ -32,14 +32,14 @@ To retrieve a specific source package name, use
 ISourcePackageNameSet.get:
 
     >>> firefox = sourcepackagenameset.get(1)
-    >>> print firefox.name
+    >>> print(firefox.name)
     mozilla-firefox
 
 To retrieve a specific source package name by its name, use
 ISourcePackageNameSet.queryByName:
 
     >>> firefox = sourcepackagenameset.queryByName("mozilla-firefox")
-    >>> print firefox.name
+    >>> print(firefox.name)
     mozilla-firefox
 
 Source packages have useful string representations containing their name in
@@ -51,7 +51,7 @@ quotes.
 If the package doesn't exist, queryByName returns None:
 
     >>> biscoito = sourcepackagenameset.queryByName("biscoito")
-    >>> print biscoito
+    >>> print(biscoito)
     None
 
 
@@ -85,16 +85,16 @@ Descriptive attributes
 
 A source package has a name, displayname, title, and a summary.
 
-    >>> print firefox_warty.name
+    >>> print(firefox_warty.name)
     mozilla-firefox
 
-    >>> print firefox_warty.displayname
+    >>> print(firefox_warty.displayname)
     mozilla-firefox in Ubuntu Warty
 
     >>> print(firefox_warty.title)
     mozilla-firefox source package in Warty
 
-    >>> print firefox_warty.summary
+    >>> print(firefox_warty.summary)
     mozilla-firefox: Mozilla Firefox Web Browser
     mozilla-firefox-data: No summary available for mozilla-firefox-data
     in ubuntu warty.
@@ -123,7 +123,7 @@ upload, even though it gets changed in the publishing record.
     >>> publishing_history = removeSecurityProxy(
     ...     firefox_warty)._getPublishingHistory()
     >>> for publishing in publishing_history:
-    ...     print publishing.status.name, publishing.component.name
+    ...     print(publishing.status.name, publishing.component.name)
     PENDING main
     PUBLISHED main
 
@@ -140,7 +140,7 @@ upload, even though it gets changed in the publishing record.
     >>> flush_database_caches()
 
     >>> for release in firefox_warty.distinctreleases:
-    ...     print release.component.name
+    ...     print(release.component.name)
     main
 
     >>> firefox_warty.latest_published_component.name
@@ -152,7 +152,7 @@ component. If there are no PUBLISHED records, None is returned.
     >>> from lp.soyuz.enums import PackagePublishingStatus
 
     >>> latest_publishing.status = PackagePublishingStatus.SUPERSEDED
-    >>> print firefox_warty.latest_published_component
+    >>> print(firefox_warty.latest_published_component)
     None
 
 SourcePackage traversing is also provided through the available
@@ -162,7 +162,7 @@ SourcePackage context will be reachable.
     >>> pmount_hoary = ubuntu['hoary'].getSourcePackage('pmount')
 
     >>> for release in pmount_hoary.releases:
-    ...     print release.title, release.publishing_history[0].status.name
+    ...     print(release.title, release.publishing_history[0].status.name)
     pmount 0.1-1 source package in Ubuntu SUPERSEDED
     pmount 0.1-2 source package in Ubuntu PUBLISHED
 
@@ -186,7 +186,7 @@ See bug #179028 for further information.
     >>> pub.dateremoved = pub.datesuperseded + timedelta(days=1)
 
     >>> for release in pmount_hoary.releases:
-    ...     print release.title, release.publishing_history[0].status.name
+    ...     print(release.title, release.publishing_history[0].status.name)
     pmount 0.1-1 source package in Ubuntu SUPERSEDED
     pmount 0.1-2 source package in Ubuntu PUBLISHED
 
@@ -215,13 +215,13 @@ method on a distribution:
     >>> IDistributionSourcePackage.providedBy(ubuntu_firefox)
     True
 
-    >>> print ubuntu_firefox.name
+    >>> print(ubuntu_firefox.name)
     mozilla-firefox
 
     >>> print(backslashreplace(ubuntu_firefox.title))
     mozilla-firefox package in Ubuntu
 
-    >>> print ubuntu_firefox.displayname
+    >>> print(ubuntu_firefox.displayname)
     mozilla-firefox in Ubuntu
 
     >>> ubuntu_firefox.distribution == ubuntu
@@ -278,7 +278,7 @@ package.
 
     >>> from lp.registry.model.sourcepackage import SourcePackage
     >>> sp = SourcePackage(sourcepackagename=firefox, distroseries=hoary)
-    >>> print sp.productseries.name
+    >>> print(sp.productseries.name)
     1.0
 
 
@@ -293,12 +293,12 @@ be more like the bug number linkification just below.
     >>> dsp = ubuntu.getSourcePackage(pmount)
     >>> dspr = dsp.getVersion('0.1-2')
     >>> dspr_view = queryMultiAdapter((dspr, request), name="+changelog")
-    >>> print dspr_view.changelog_entry
+    >>> print(dspr_view.changelog_entry)
     This is a placeholder changelog for pmount 0.1-2
 
     >>> dspr = dsp.getVersion('0.1-1')
     >>> dspr_view = queryMultiAdapter((dspr, request), name="+changelog")
-    >>> print dspr_view.changelog_entry
+    >>> print(dspr_view.changelog_entry)
     pmount (0.1-1) hoary; urgency=low
     <BLANKLINE>
      * Fix description (Malone #1)
@@ -360,13 +360,13 @@ The direct packaging returns the IPackaging related to the source
 package.
 
     >>> sp = hoary.getSourcePackage(pmount)
-    >>> print sp.direct_packaging
+    >>> print(sp.direct_packaging)
     None
 
-    >>> print hoary_firefox_one.direct_packaging.productseries.title
+    >>> print(hoary_firefox_one.direct_packaging.productseries.title)
     Mozilla Firefox 1.0 series
 
-    >>> print warty_firefox.direct_packaging.productseries.title
+    >>> print(warty_firefox.direct_packaging.productseries.title)
     Mozilla Firefox trunk series
 
 
@@ -402,10 +402,10 @@ versions, their history is isolated by series.
     >>> def print_releases(sourcepackage):
     ...     releases = sourcepackage.distinctreleases
     ...     if releases.count() == 0:
-    ...         print 'No releases available'
+    ...         print('No releases available')
     ...         return
     ...     for release in releases:
-    ...         print release.title
+    ...         print(release.title)
 
     >>> warty_sp = ubuntu_warty.getSourcePackage('test-source')
     >>> print_releases(warty_sp)
diff --git a/lib/lp/registry/doc/standing.txt b/lib/lp/registry/doc/standing.txt
index 02ce8ce..b657b35 100644
--- a/lib/lp/registry/doc/standing.txt
+++ b/lib/lp/registry/doc/standing.txt
@@ -235,9 +235,9 @@ standing untouched.
     ...     stdin=subprocess.PIPE, stdout=subprocess.PIPE,
     ...     stderr=subprocess.PIPE, universal_newlines=True)
     >>> stdout, stderr = process.communicate()
-    >>> print stdout
+    >>> print(stdout)
     <BLANKLINE>
-    >>> print stderr
+    >>> print(stderr)
     INFO    Creating lockfile: /var/lock/launchpad-update-personal-standing.lock
     INFO    Updating personal standings
     INFO    Done.
@@ -266,9 +266,9 @@ update-standing script bumps his standing to Good too.
     ...     stdin=subprocess.PIPE, stdout=subprocess.PIPE,
     ...     stderr=subprocess.PIPE, universal_newlines=True)
     >>> stdout, stderr = process.communicate()
-    >>> print stdout
+    >>> print(stdout)
     <BLANKLINE>
-    >>> print stderr
+    >>> print(stderr)
     INFO    Creating lockfile: /var/lock/launchpad-update-personal-standing.lock
     INFO    Updating personal standings
     INFO    Done.
diff --git a/lib/lp/registry/doc/team-nav-menus.txt b/lib/lp/registry/doc/team-nav-menus.txt
index 7890521..b4518a3 100644
--- a/lib/lp/registry/doc/team-nav-menus.txt
+++ b/lib/lp/registry/doc/team-nav-menus.txt
@@ -13,7 +13,7 @@ The team pages have their own navigation menu.
 
 The default navigation menu is registered for the 'overview' facet.
 
-    >>> print queryAdapter(ubuntu_team, INavigationMenu, name='overview')
+    >>> print(queryAdapter(ubuntu_team, INavigationMenu, name='overview'))
     <...TeamOverviewNavigationMenu ...>
 
     # Set up the test request so the MenuAPI knows what facet to use for
diff --git a/lib/lp/registry/doc/teammembership-email-notification.txt b/lib/lp/registry/doc/teammembership-email-notification.txt
index 181afe0..f93f506 100644
--- a/lib/lp/registry/doc/teammembership-email-notification.txt
+++ b/lib/lp/registry/doc/teammembership-email-notification.txt
@@ -780,10 +780,10 @@ notification is sent to all team admins.
     >>> karl_on_mirroradmins = membershipset.getByPersonAndTeam(
     ...     karl, mirror_admins)
     >>> tomorrow = datetime.now(pytz.timezone('UTC')) + timedelta(days=1)
-    >>> print karl_on_mirroradmins.status.title
+    >>> print(karl_on_mirroradmins.status.title)
     Approved
 
-    >>> print karl_on_mirroradmins.dateexpires
+    >>> print(karl_on_mirroradmins.dateexpires)
     None
 
     >>> ignored = login_person(mirror_admins.teamowner)
@@ -976,7 +976,7 @@ notifications sent) by Launchpad Administrators.
     >>> hwdb_admins = personset.getByName('hwdb-team')
     >>> dumper_hwdb_membership = membershipset.getByPersonAndTeam(dumper,
     ...     hwdb_admins)
-    >>> print dumper_hwdb_membership.status.title
+    >>> print(dumper_hwdb_membership.status.title)
     Approved
 
     >>> ignored = login_person(admin_person)
@@ -986,7 +986,7 @@ notifications sent) by Launchpad Administrators.
     >>> len(stub.test_emails)
     0
 
-    >>> print dumper_hwdb_membership.status.title
+    >>> print(dumper_hwdb_membership.status.title)
     Deactivated
 
 People who are not Launchpad Administrators, may not change other's
@@ -1000,10 +1000,10 @@ membership statues silently.
     ...     kamion, ubuntu_team)
     >>> stevea_ubuntu_team_membership = membershipset.getByPersonAndTeam(
     ...     stevea, ubuntu_team)
-    >>> print kamion_ubuntu_team_membership.status.title
+    >>> print(kamion_ubuntu_team_membership.status.title)
     Administrator
 
-    >>> print stevea_ubuntu_team_membership.status.title
+    >>> print(stevea_ubuntu_team_membership.status.title)
     Approved
 
     >>> setStatus(stevea_ubuntu_team_membership,
@@ -1012,7 +1012,7 @@ membership statues silently.
     Traceback (most recent call last):
     lp.registry.errors.UserCannotChangeMembershipSilently: ...
 
-    >>> print stevea_ubuntu_team_membership.status.title
+    >>> print(stevea_ubuntu_team_membership.status.title)
     Approved
 
 
diff --git a/lib/lp/registry/doc/teammembership.txt b/lib/lp/registry/doc/teammembership.txt
index 8dbeb5e..fd85feb 100644
--- a/lib/lp/registry/doc/teammembership.txt
+++ b/lib/lp/registry/doc/teammembership.txt
@@ -470,11 +470,11 @@ good work, so we'll approve their membership.
 
     >>> warty_team = getUtility(IPersonSet).getByName('name20')
     >>> membership = membershipset.getByPersonAndTeam(foobar, warty_team)
-    >>> print membership.status.title
+    >>> print(membership.status.title)
     Proposed
-    >>> print membership.date_created.strftime("%Y-%m-%d")
+    >>> print(membership.date_created.strftime("%Y-%m-%d"))
     2006-01-26
-    >>> print membership.datejoined
+    >>> print(membership.datejoined)
     None
 
 When we approve their membership, the datejoined will contain the date that it
@@ -482,7 +482,7 @@ was approved. It returns True to indicate that the status was changed.
 
     >>> membership.setStatus(TeamMembershipStatus.APPROVED, foobar)
     True
-    >>> print membership.status.title
+    >>> print(membership.status.title)
     Approved
     >>> utc_now = datetime.now(pytz.timezone('UTC'))
     >>> membership.datejoined.date() == utc_now.date()
@@ -502,7 +502,7 @@ made active.
     ...     'launchpad-buildd-admins')
     >>> foobar_on_buildd = membershipset.getByPersonAndTeam(
     ...     foobar, buildd_admins)
-    >>> print foobar_on_buildd.status.title
+    >>> print(foobar_on_buildd.status.title)
     Administrator
     >>> foobar_on_buildd.datejoined <= utc_now
     True
@@ -510,7 +510,7 @@ made active.
     >>> foobar_on_buildd.setStatus(
     ...     TeamMembershipStatus.DEACTIVATED, foobar)
     True
-    >>> print foobar_on_buildd.status.title
+    >>> print(foobar_on_buildd.status.title)
     Deactivated
     >>> foobar_on_buildd.datejoined <= utc_now
     True
@@ -518,7 +518,7 @@ made active.
     >>> foobar_on_buildd.setStatus(
     ...     TeamMembershipStatus.APPROVED, foobar)
     True
-    >>> print foobar_on_buildd.status.title
+    >>> print(foobar_on_buildd.status.title)
     Approved
     >>> foobar_on_buildd.datejoined <= utc_now
     True
@@ -562,7 +562,7 @@ own or administer.
     ...     cprov, buildd_admins)
     >>> buildd_admins.teamowner.name
     u'name16'
-    >>> print cprov_on_buildd.status.title
+    >>> print(cprov_on_buildd.status.title)
     Administrator
     >>> foobar_on_buildd.canChangeExpirationDate(cprov)
     True
@@ -657,9 +657,9 @@ still active.
     >>> karl_on_mirroradmins = membershipset.getByPersonAndTeam(
     ...     karl, mirror_admins)
     >>> tomorrow = datetime.now(pytz.timezone('UTC')) + timedelta(days=1)
-    >>> print karl_on_mirroradmins.status.title
+    >>> print(karl_on_mirroradmins.status.title)
     Approved
-    >>> print karl_on_mirroradmins.dateexpires
+    >>> print(karl_on_mirroradmins.dateexpires)
     None
 
 The member themselves can't change the expiration date of their membership.
@@ -683,7 +683,7 @@ If the team's renewal policy is ONDEMAND, the membership can be renewed
 by the member themselves. (That is only true because this membership is
 active and set to expire tomorrow).
 
-    >>> print karl_on_mirroradmins.team.renewal_policy.name
+    >>> print(karl_on_mirroradmins.team.renewal_policy.name)
     NONE
     >>> karl_on_mirroradmins.canBeRenewedByMember()
     False
@@ -710,7 +710,7 @@ expire soon.
     True
     >>> karl_on_mirroradmins.canBeRenewedByMember()
     False
-    >>> print karl_on_mirroradmins.status.title
+    >>> print(karl_on_mirroradmins.status.title)
     Approved
 
 
@@ -838,8 +838,8 @@ person is an active member of as well as teams those teams are an active
 member of.
 
     >>> login('celso.providelo@xxxxxxxxxxxxx')
-    >>> print '\n'.join(sorted(
-    ...     team.name for team in salgado.teams_participated_in))
+    >>> print('\n'.join(sorted(
+    ...     team.name for team in salgado.teams_participated_in)))
     admins
     hwdb-team
     landscape-developers
@@ -853,8 +853,8 @@ Adding admins as a member of t1 will make Salgado a member of t1 as well.
     >>> t1.addMember(admins, reviewer=t1.teamowner, force_team_add=True)
     (True, <DBItem TeamMembershipStatus.APPROVED...)
     >>> flush_database_updates()
-    >>> print '\n'.join(sorted(
-    ...     team.name for team in salgado.teams_participated_in))
+    >>> print('\n'.join(sorted(
+    ...     team.name for team in salgado.teams_participated_in)))
     admins
     hwdb-team
     landscape-developers
@@ -869,8 +869,8 @@ for Salgado.
     >>> admins.addMember(t3, reviewer=admins.teamowner, force_team_add=True)
     (True, <DBItem TeamMembershipStatus.APPROVED...)
     >>> flush_database_updates()
-    >>> print '\n'.join(sorted(
-    ...     team.name for team in salgado.teams_participated_in))
+    >>> print('\n'.join(sorted(
+    ...     team.name for team in salgado.teams_participated_in)))
     admins
     hwdb-team
     landscape-developers
diff --git a/lib/lp/registry/doc/vocabularies.txt b/lib/lp/registry/doc/vocabularies.txt
index c1e6185..e1ca904 100644
--- a/lib/lp/registry/doc/vocabularies.txt
+++ b/lib/lp/registry/doc/vocabularies.txt
@@ -204,7 +204,7 @@ Reflects the available distribution series.  Results are ordered by
     >>> distroseries_vocabulary = get_naked_vocab(
     ...     None, "DistroSeries")
     >>> for term in distroseries_vocabulary:
-    ...     print "%30s %s" % (term.token, term.title)
+    ...     print("%30s %s" % (term.token, term.title))
             ubuntu/breezy-autotest Ubuntu: Breezy Badger Autotest
                      ubuntu/grumpy Ubuntu: The Grumpy Groundhog Release
                       ubuntu/hoary Ubuntu: The Hoary Hedgehog Release
@@ -252,7 +252,7 @@ All the teams the person is an active member of.
     10
 
     >>> for term in person_active_membership:
-    ...     print term.token, term.value.displayname, term.title
+    ...     print(term.token, term.value.displayname, term.title)
     canonical-partner-dev Canonical Partner Developers
         Canonical Partner Developers
     guadamen GuadaMen GuadaMen
@@ -281,7 +281,7 @@ membership is public.
     ...                            displayname="Public Team",
     ...                            visibility=PersonVisibility.PUBLIC)
     >>> for term in person_active_membership:
-    ...     print term.token, term.value.displayname, term.title
+    ...     print(term.token, term.value.displayname, term.title)
     canonical-partner-dev Canonical Partner Developers
         Canonical Partner Developers
     guadamen GuadaMen GuadaMen
@@ -297,7 +297,7 @@ membership is public.
 
     >>> pubteam.visibility = PersonVisibility.PRIVATE
     >>> for term in person_active_membership:
-    ...     print term.token, term.value.displayname, term.title
+    ...     print(term.token, term.value.displayname, term.title)
     canonical-partner-dev Canonical Partner Developers
         Canonical Partner Developers
     guadamen GuadaMen GuadaMen
@@ -311,7 +311,7 @@ membership is public.
     vcs-imports VCS imports VCS imports
 
     >>> term = person_active_membership.getTerm(launchpad_team)
-    >>> print term.token, term.value.displayname, term.title
+    >>> print(term.token, term.value.displayname, term.title)
     launchpad Launchpad Developers Launchpad Developers
 
     >>> term = person_active_membership.getTerm(mirrors_admins)
@@ -320,7 +320,7 @@ membership is public.
     LookupError:...
 
     >>> term = person_active_membership.getTermByToken('launchpad')
-    >>> print term.token, term.value.displayname, term.title
+    >>> print(term.token, term.value.displayname, term.title)
     launchpad Launchpad Developers Launchpad Developers
 
     >>> term = person_active_membership.getTermByToken('mirrors-admins')
@@ -362,7 +362,7 @@ but we need the big default vocabulary for form input validation.
     3
 
     >>> for term in all_milestones:
-    ...     print "%s: %s" % (term.value.target.name, term.value.name)
+    ...     print("%s: %s" % (term.value.target.name, term.value.name))
     debian: 3.1
     debian: 3.1-rc1
     firefox: 1.0
@@ -373,7 +373,7 @@ vocabulary.
     >>> firefox = product_set.getByName('firefox')
     >>> firefox_milestones = get_naked_vocab(firefox, 'Milestone')
     >>> for term in firefox_milestones:
-    ...     print "%s: %s" % (term.value.target.name, term.value.name)
+    ...     print("%s: %s" % (term.value.target.name, term.value.name))
     firefox: 1.0
 
 If the context is a productseries, milestones for the series and for the
@@ -385,7 +385,7 @@ product itself are included in the vocabulary.
     >>> firefox_trunk_milestones = get_naked_vocab(firefox_trunk,
     ...                                                    'Milestone')
     >>> for term in firefox_trunk_milestones:
-    ...     print "%s: %s" % (term.value.target.name, term.value.name)
+    ...     print("%s: %s" % (term.value.target.name, term.value.name))
     firefox: 1.0
     firefox: firefox-milestone-no-series
 
@@ -399,13 +399,13 @@ specification target are in the vocabulary.
     >>> spec_target_milestones = get_naked_vocab(
     ...     canvas_spec, 'Milestone')
     >>> for term in spec_target_milestones:
-    ...     print "%s: %s" % (term.value.target.name, term.value.name)
+    ...     print("%s: %s" % (term.value.target.name, term.value.name))
     firefox: 1.0
 
 The vocabulary contains only active milestones.
 
     >>> for milestone in firefox.milestones:
-    ...     print milestone.name, milestone.active
+    ...     print(milestone.name, milestone.active)
     1.0 True
 
     >>> one_dot_o = firefox.milestones[0]
@@ -429,7 +429,7 @@ All the products in a project.
     ...     mozilla_project,'ProjectProducts')
 
     >>> for term in mozilla_products_vocabulary:
-    ...     print "%s: %s" %(term.token, term.title)
+    ...     print("%s: %s" %(term.token, term.title))
     firefox: Mozilla Firefox
     thunderbird: Mozilla Thunderbird
 
@@ -601,7 +601,7 @@ The set of non-merged people.
 Unlike PersonAccountToMerge, this vocabulary includes people who don't
 have a single email address, as it's fine for admins to merge them.
 
-    >>> print fooperson.preferredemail
+    >>> print(fooperson.preferredemail)
     None
 
     >>> list(fooperson.validatedemails) + list(fooperson.guessedemails)
@@ -737,7 +737,7 @@ The PRIVATE team can be looked up via getTermByToken for a member of the
 team.
 
     >>> term = vocab.getTermByToken('private-team')
-    >>> print term.title
+    >>> print(term.title)
     Private Team
 
 The PRIVATE team is not returned for a user who is not part of the team.
@@ -860,11 +860,11 @@ Search for names with '%' and '?' is supported.
     ...     symbolic_person, 'irc.fnord.net', 'question?')
 
     >>> for person in vocab.search('%percent'):
-    ...     print person.name
+    ...     print(person.name)
     symbolic
 
     >>> for person in vocab.search('question?'):
-    ...     print person.name
+    ...     print(person.name)
     symbolic
 
 ValidOwner
@@ -1032,19 +1032,19 @@ All 'valid' persons who are not a team.
 
     >>> invalid_people = [
     ...     person for person in people if not person.is_valid_person]
-    >>> print len(invalid_people)
+    >>> print(len(invalid_people))
     0
 
 There are two 'Carlos' in the sample data but only one is a valid
 person.
 
     >>> carlos_people = vocab.search('Carlos')
-    >>> print len(list(carlos_people))
+    >>> print(len(list(carlos_people)))
     1
 
     >>> invalid_carlos = [
     ...     person for person in carlos_people if not person.is_valid_person]
-    >>> print len(invalid_carlos)
+    >>> print(len(invalid_carlos))
     0
 
 ValidPerson does not include teams.
@@ -1054,14 +1054,14 @@ ValidPerson does not include teams.
     ...     owner=carlos, name='carlos-team')
     >>> person_or_team_vocab = get_naked_vocab(None, "ValidPersonOrTeam")
     >>> carlos_people_or_team = person_or_team_vocab.search('carlos')
-    >>> print len(list(carlos_people_or_team))
+    >>> print(len(list(carlos_people_or_team)))
     2
 
     >>> carlos_team in carlos_people_or_team
     True
 
     >>> carlos_people = vocab.search('carlos')
-    >>> print len(list(carlos_people))
+    >>> print(len(list(carlos_people)))
     1
 
     >>> carlos_team in carlos_people
@@ -1077,7 +1077,7 @@ heterogeneous.
     >>> vocab = get_naked_vocab(None, "DistributionOrProduct")
     >>> for term in vocab:
     ...     if 'buntu' in term.title:
-    ...         print term.title, '- class', term.value.__class__.__name__
+    ...         print(term.title, '- class', term.value.__class__.__name__)
     Kubuntu - class Distribution
     Ubuntu - class Distribution
     ubuntutest - class Distribution
@@ -1110,7 +1110,7 @@ Inactive projects and project groups are not available.
 
     >>> for term in vocab:
     ...     if 'Tomcat' in term.title:
-    ...         print term.title, '- class', term.value.__class__.__name__
+    ...         print(term.title, '- class', term.value.__class__.__name__)
     Tomcat - class Product
 
     >>> tomcat = product_set.getByName('tomcat')
@@ -1145,7 +1145,7 @@ is heterogeneous.
     >>> vocab = get_naked_vocab(None, "DistributionOrProductOrProjectGroup")
     >>> for term in vocab:
     ...     if 'buntu' in term.title:
-    ...         print term.title, '- class', term.value.__class__.__name__
+    ...         print(term.title, '- class', term.value.__class__.__name__)
     Kubuntu - class Distribution
     Ubuntu - class Distribution
     ubuntutest - class Distribution
@@ -1187,22 +1187,22 @@ Inactive projects and project groups are not available.
     >>> vocab = get_naked_vocab(None, "DistributionOrProductOrProjectGroup")
     >>> for term in vocab:
     ...     if 'Apache' in term.title:
-    ...         print term.title, '- class', term.value.__class__.__name__
+    ...         print(term.title, '- class', term.value.__class__.__name__)
     >>> for term in vocab:
     ...     if 'Tomcat' in term.title:
-    ...         print term.title, '- class', term.value.__class__.__name__
+    ...         print(term.title, '- class', term.value.__class__.__name__)
     >>> product_set.getByName('tomcat').active = True
     >>> getUtility(IProjectGroupSet).getByName('apache').active = True
     >>> flush_database_updates()
     >>> vocab = get_naked_vocab(None, "DistributionOrProductOrProjectGroup")
     >>> for term in vocab:
     ...     if 'Apache' in term.title:
-    ...         print term.title, '- class', term.value.__class__.__name__
+    ...         print(term.title, '- class', term.value.__class__.__name__)
     Apache - class ProjectGroup
 
     >>> for term in vocab:
     ...     if 'Tomcat' in term.title:
-    ...         print term.title, '- class', term.value.__class__.__name__
+    ...         print(term.title, '- class', term.value.__class__.__name__)
     Tomcat - class Product
 
 
@@ -1220,7 +1220,7 @@ _clauseTables).
     9
 
     >>> for term in featured_project_vocabulary:
-    ...     print term.token, term.title
+    ...     print(term.token, term.title)
     applets         Gnome Applets
     bazaar          Bazaar
     firefox         Mozilla Firefox
diff --git a/lib/lp/registry/doc/wikiname.txt b/lib/lp/registry/doc/wikiname.txt
index dc42ffe..d33300b 100644
--- a/lib/lp/registry/doc/wikiname.txt
+++ b/lib/lp/registry/doc/wikiname.txt
@@ -28,6 +28,6 @@ All wiki names of a person can be obtained, ordered alphabetically by wiki URL
 and name, through IPerson.wiki_names.
 
     >>> for wiki in salgado.wiki_names:
-    ...     print "%s%s" % (wiki.wiki, wiki.wikiname)
+    ...     print("%s%s" % (wiki.wiki, wiki.wikiname))
     https://wiki.canonical.com/Salgado
     https://wiki.ubuntu.com/GuilhermeSalgado
diff --git a/lib/lp/registry/interfaces/distribution.py b/lib/lp/registry/interfaces/distribution.py
index a28d103..5ec5271 100644
--- a/lib/lp/registry/interfaces/distribution.py
+++ b/lib/lp/registry/interfaces/distribution.py
@@ -742,9 +742,9 @@ class IDistribution(
         ubuntu = launchpad.distributions["ubuntu"]
         archive = ubuntu.main_archive
         series = ubuntu.current_series
-        print archive.getPublishedSources(exact_match=True,
+        print(archive.getPublishedSources(exact_match=True,
             source_name="apport",
-            distro_series=series)[0].source_package_version
+            distro_series=series)[0].source_package_version)
     """
 
 
diff --git a/lib/lp/registry/tests/test_doc.py b/lib/lp/registry/tests/test_doc.py
index 6279433..ec4302c 100644
--- a/lib/lp/registry/tests/test_doc.py
+++ b/lib/lp/registry/tests/test_doc.py
@@ -38,65 +38,68 @@ def peopleKarmaTearDown(test):
 special = {
     'distribution-mirror.txt': LayeredDocFileSuite(
         '../doc/distribution-mirror.txt',
-        setUp=setUp, tearDown=tearDown,
+        setUp=lambda test: setUp(test, future=True), tearDown=tearDown,
         layer=LaunchpadFunctionalLayer,
         ),
     'person-karma.txt': LayeredDocFileSuite(
         '../doc/person-karma.txt',
-        setUp=setUp, tearDown=peopleKarmaTearDown,
+        setUp=lambda test: setUp(test, future=True),
+        tearDown=peopleKarmaTearDown,
         layer=LaunchpadFunctionalLayer,
         stdout_logging_level=logging.WARNING
         ),
     'product.txt': LayeredDocFileSuite(
         '../doc/product.txt',
-        setUp=setUp,
+        setUp=lambda test: setUp(test, future=True),
         tearDown=tearDown,
         layer=LaunchpadFunctionalLayer,
         ),
     'private-team-roles.txt': LayeredDocFileSuite(
         '../doc/private-team-roles.txt',
-        setUp=setUp,
+        setUp=lambda test: setUp(test, future=True),
         tearDown=tearDown,
         layer=LaunchpadFunctionalLayer,
         ),
     'productrelease.txt': LayeredDocFileSuite(
         '../doc/productrelease.txt',
-        setUp=setUp,
+        setUp=lambda test: setUp(test, future=True),
         tearDown=tearDown,
         layer=LaunchpadFunctionalLayer,
         ),
     'productrelease-file-download.txt': LayeredDocFileSuite(
         '../doc/productrelease-file-download.txt',
-        setUp=setUp,
+        setUp=lambda test: setUp(test, future=True),
         tearDown=tearDown,
         layer=LaunchpadFunctionalLayer,
         ),
     'standing.txt': LayeredDocFileSuite(
         '../doc/standing.txt',
         layer=LaunchpadZopelessLayer,
-        setUp=setUp, tearDown=tearDown,
+        setUp=lambda test: setUp(test, future=True), tearDown=tearDown,
         ),
     'karmacache.txt': LayeredDocFileSuite(
         '../doc/karmacache.txt',
         layer=LaunchpadZopelessLayer,
-        setUp=setUp, tearDown=tearDown),
+        setUp=lambda test: setUp(test, future=True), tearDown=tearDown),
     'sourcepackage.txt': LayeredDocFileSuite(
         '../doc/sourcepackage.txt',
         layer=LaunchpadFunctionalLayer,
-        setUp=setUp, tearDown=tearDown),
+        setUp=lambda test: setUp(test, future=True), tearDown=tearDown),
     'distribution-sourcepackage.txt': LayeredDocFileSuite(
         '../doc/distribution-sourcepackage.txt',
         layer=LaunchpadZopelessLayer,
-        setUp=setUp, tearDown=tearDown),
+        setUp=lambda test: setUp(test, future=True), tearDown=tearDown),
     }
 
 
 def test_suite():
     suite = build_test_suite(
         here, special, layer=DatabaseFunctionalLayer,
+        setUp=lambda test: setUp(test, future=True),
         pageTestsSetUp=lambda test: setUpGlobs(test, future=True))
     launchpadlib_path = os.path.join(os.path.pardir, 'doc', 'launchpadlib')
-    lplib_suite = build_doctest_suite(here, launchpadlib_path,
-                                      layer=DatabaseFunctionalLayer)
+    lplib_suite = build_doctest_suite(
+        here, launchpadlib_path, layer=DatabaseFunctionalLayer,
+        setUp=lambda test: setUp(test, future=True))
     suite.addTest(lplib_suite)
     return suite
diff --git a/lib/lp/registry/tests/test_teammembership.py b/lib/lp/registry/tests/test_teammembership.py
index 31e6e44..3d69231 100644
--- a/lib/lp/registry/tests/test_teammembership.py
+++ b/lib/lp/registry/tests/test_teammembership.py
@@ -1340,6 +1340,7 @@ def test_suite():
     suite = TestLoader().loadTestsFromName(__name__)
     bug_249185 = LayeredDocFileSuite(
         'bug-249185.txt', optionflags=default_optionflags,
-        layer=DatabaseFunctionalLayer, setUp=setUp, tearDown=tearDown)
+        layer=DatabaseFunctionalLayer,
+        setUp=lambda test: setUp(test, future=True), tearDown=tearDown)
     suite.addTest(bug_249185)
     return suite