← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/hardwaredb-tests-future-imports into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/hardwaredb-tests-future-imports into lp:launchpad.

Commit message:
Convert lp.hardwaredb to Launchpad's preferred __future__ imports.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/hardwaredb-tests-future-imports/+merge/366133
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/hardwaredb-tests-future-imports into lp:launchpad.
=== modified file 'lib/lp/hardwaredb/browser/tests/test_views.py'
--- lib/lp/hardwaredb/browser/tests/test_views.py	2011-12-28 17:03:06 +0000
+++ lib/lp/hardwaredb/browser/tests/test_views.py	2019-04-16 17:22:40 +0000
@@ -5,6 +5,8 @@
 Run the view tests.
 """
 
+from __future__ import absolute_import, print_function, unicode_literals
+
 import logging
 import os
 import unittest
@@ -33,7 +35,8 @@
     for filename in filenames:
         path = filename
         one_test = LayeredDocFileSuite(
-            path, setUp=setUp, tearDown=tearDown,
+            path,
+            setUp=lambda test: setUp(test, future=True), tearDown=tearDown,
             layer=LaunchpadFunctionalLayer,
             stdout_logging_level=logging.WARNING
             )

=== modified file 'lib/lp/hardwaredb/doc/hwdb-access.txt'
--- lib/lp/hardwaredb/doc/hwdb-access.txt	2011-12-08 20:24:09 +0000
+++ lib/lp/hardwaredb/doc/hwdb-access.txt	2019-04-16 17:22:40 +0000
@@ -21,9 +21,9 @@
     ...         getattr(obj, attribute)
     ...     except Unauthorized:
     ...         has_access = False
-    ...         print "Access for %s denied" % person_name_or_address
+    ...         print("Access for %s denied" % person_name_or_address)
     ...     if has_access:
-    ...         print "Access for %s allowed" % person_name_or_address
+    ...         print("Access for %s allowed" % person_name_or_address)
     ...     logout()
 
     >>> def check_authorized_only_for_hwdb_team(obj, attribute):

=== modified file 'lib/lp/hardwaredb/doc/hwdb-device-tables.txt'
--- lib/lp/hardwaredb/doc/hwdb-device-tables.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/hardwaredb/doc/hwdb-device-tables.txt	2019-04-16 17:22:40 +0000
@@ -14,7 +14,7 @@
     >>> from lp.hardwaredb.interfaces.hwdb import IHWVendorNameSet
     >>> vendor_name_set = getUtility(IHWVendorNameSet)
     >>> intel_name = vendor_name_set.create(name='Intel')
-    >>> print intel_name.name
+    >>> print(intel_name.name)
     Intel
 
 Each name in the table must be unique. The attempt to create a second
@@ -61,7 +61,7 @@
     >>> a_umlaut_lower = u'\N{LATIN SMALL LETTER A WITH DIAERESIS}'
     >>> a_umlaut_name = vendor_name_set.create(name=a_umlaut_upper)
     >>> LaunchpadZopelessLayer.txn.commit()
-    >>> print repr(a_umlaut_name.name)
+    >>> print(repr(a_umlaut_name.name))
     u'\xc4'
 
     >>> vendor_name_set.create(name=a_umlaut_lower)
@@ -78,7 +78,7 @@
     >>> cyrillic_de_upper = u'\N{CYRILLIC CAPITAL LETTER DE}'
     >>> cyrillic_de_lower = u'\N{CYRILLIC SMALL LETTER DE}'
     >>> cyrillic_de_name = vendor_name_set.create(name=cyrillic_de_upper)
-    >>> print repr(cyrillic_de_name.name)
+    >>> print(repr(cyrillic_de_name.name))
     u'\u0414'
 
     >>> vendor_name_set.create(name=cyrillic_de_lower)
@@ -95,7 +95,7 @@
     >>> alpha_upper = u'\N{GREEK CAPITAL LETTER ALPHA}'
     >>> alpha_lower = u'\N{GREEK SMALL LETTER ALPHA}'
     >>> cyrillic_de_name = vendor_name_set.create(name=alpha_upper)
-    >>> print repr(cyrillic_de_name.name)
+    >>> print(repr(cyrillic_de_name.name))
     u'\u0391'
 
     >>> vendor_name_set.create(name=alpha_lower)
@@ -110,33 +110,33 @@
 Existing IHWVendorName records are retrieved by IHWVendorName.getByName().
 
     >>> intel_name = vendor_name_set.getByName('Intel')
-    >>> print intel_name.name
+    >>> print(intel_name.name)
     Intel
 
 The capitalization of the name does not metter.
 
     >>> intel_name = vendor_name_set.getByName('INTEL')
-    >>> print intel_name.name
+    >>> print(intel_name.name)
     Intel
 
     >>> intel_name = vendor_name_set.getByName('intel')
-    >>> print intel_name.name
+    >>> print(intel_name.name)
     Intel
 
     >>> umlaut_name = vendor_name_set.getByName(
     ...     u'\N{LATIN CAPITAL LETTER A WITH DIAERESIS}')
-    >>> print repr(umlaut_name.name)
+    >>> print(repr(umlaut_name.name))
     u'\xc4'
 
     >>> umlaut_name = vendor_name_set.getByName(
     ...     u'\N{LATIN SMALL LETTER A WITH DIAERESIS}')
-    >>> print repr(umlaut_name.name)
+    >>> print(repr(umlaut_name.name))
     u'\xc4'
 
 If no record matching the given name exists, IHWVendorName.getByName()
 returns None.
 
-    >>> print vendor_name_set.getByName('Babbage Computers')
+    >>> print(vendor_name_set.getByName('Babbage Computers'))
     None
 
 
@@ -153,9 +153,9 @@
     >>> intel_pci_id = vendor_id_set.create(bus=HWBus.PCI,
     ...                                     vendor_id='0x8086',
     ...                                     vendor_name=intel_name)
-    >>> print intel_pci_id.bus.title, intel_pci_id.vendor_id_for_bus
+    >>> print(intel_pci_id.bus.title, intel_pci_id.vendor_id_for_bus)
     PCI 0x8086
-    >>> print intel_pci_id.vendor_name.name
+    >>> print(intel_pci_id.vendor_name.name)
     Intel
 
 The tuple (bus, vendor id, vendor name) must be unique.
@@ -187,31 +187,31 @@
     >>> another_pci_vendor_id = vendor_id_set.create(bus=HWBus.PCI,
     ...                                              vendor_id='0x10ae',
     ...                                              vendor_name=intel_name)
-    >>> print another_pci_vendor_id.bus.title
+    >>> print(another_pci_vendor_id.bus.title)
     PCI
-    >>> print another_pci_vendor_id.vendor_id_for_bus
+    >>> print(another_pci_vendor_id.vendor_id_for_bus)
     0x10ae
-    >>> print another_pci_vendor_id.vendor_name.name
+    >>> print(another_pci_vendor_id.vendor_name.name)
     Intel
 
     >>> another_pci_vendor_id = vendor_id_set.create(bus=HWBus.PCCARD,
     ...                                              vendor_id='0x10ae',
     ...                                              vendor_name=intel_name)
-    >>> print another_pci_vendor_id.bus.title
+    >>> print(another_pci_vendor_id.bus.title)
     PC Card (32 bit)
-    >>> print another_pci_vendor_id.vendor_id_for_bus
+    >>> print(another_pci_vendor_id.vendor_id_for_bus)
     0x10ae
-    >>> print another_pci_vendor_id.vendor_name.name
+    >>> print(another_pci_vendor_id.vendor_name.name)
     Intel
 
     >>> another_usb_vendor_id = vendor_id_set.create(bus=HWBus.USB,
     ...                                              vendor_id='0x10ae',
     ...                                              vendor_name=intel_name)
-    >>> print another_usb_vendor_id.bus.title
+    >>> print(another_usb_vendor_id.bus.title)
     USB
-    >>> print another_usb_vendor_id.vendor_id_for_bus
+    >>> print(another_usb_vendor_id.vendor_id_for_bus)
     0x10ae
-    >>> print another_usb_vendor_id.vendor_name.name
+    >>> print(another_usb_vendor_id.vendor_name.name)
     Intel
 
 A..F is rejected.
@@ -221,7 +221,7 @@
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0x10AE' is not a valid vendor ID for PCI
+    ParameterError: u'0x10AE' is not a valid vendor ID for PCI
     >>> from storm.tracer import debug; debug(True)
     >>> store.flush()
     >>> debug(False)
@@ -231,14 +231,14 @@
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0x10AE' is not a valid vendor ID for PC Card (32 bit)
+    ParameterError: u'0x10AE' is not a valid vendor ID for PC Card (32 bit)
 
     >>> vendor_id_set.create(bus=HWBus.USB,
     ...                      vendor_id='0x10AE',
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0x10AE' is not a valid vendor ID for USB
+    ParameterError: u'0x10AE' is not a valid vendor ID for USB
 
 The ID must have the prefix "0x".
 
@@ -247,21 +247,21 @@
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '8086' is not a valid vendor ID for PCI
+    ParameterError: u'8086' is not a valid vendor ID for PCI
 
     >>> vendor_id_set.create(bus=HWBus.PCCARD,
     ...                      vendor_id='8086',
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '8086' is not a valid vendor ID for PC Card (32 bit)
+    ParameterError: u'8086' is not a valid vendor ID for PC Card (32 bit)
 
     >>> vendor_id_set.create(bus=HWBus.USB,
     ...                      vendor_id='8086',
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '8086' is not a valid vendor ID for USB
+    ParameterError: u'8086' is not a valid vendor ID for USB
 
 The number must have four digits.
 
@@ -270,42 +270,42 @@
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0x123' is not a valid vendor ID for PCI
+    ParameterError: u'0x123' is not a valid vendor ID for PCI
 
     >>> vendor_id_set.create(bus=HWBus.PCCARD,
     ...                      vendor_id='0x123',
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0x123' is not a valid vendor ID for PC Card (32 bit)
+    ParameterError: u'0x123' is not a valid vendor ID for PC Card (32 bit)
 
     >>> vendor_id_set.create(bus=HWBus.USB,
     ...                      vendor_id='0x123',
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0x123' is not a valid vendor ID for USB
+    ParameterError: u'0x123' is not a valid vendor ID for USB
 
     >>> vendor_id_set.create(bus=HWBus.PCI,
     ...                      vendor_id='0x12345',
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0x12345' is not a valid vendor ID for PCI
+    ParameterError: u'0x12345' is not a valid vendor ID for PCI
 
     >>> vendor_id_set.create(bus=HWBus.PCCARD,
     ...                      vendor_id='0x12345',
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0x12345' is not a valid vendor ID for PC Card (32 bit)
+    ParameterError: u'0x12345' is not a valid vendor ID for PC Card (32 bit)
 
     >>> vendor_id_set.create(bus=HWBus.USB,
     ...                      vendor_id='0x12345',
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0x12345' is not a valid vendor ID for USB
+    ParameterError: u'0x12345' is not a valid vendor ID for USB
 
 Only hex digits are allowed.
 
@@ -314,21 +314,21 @@
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0xblah' is not a valid vendor ID for PCI
+    ParameterError: u'0xblah' is not a valid vendor ID for PCI
 
     >>> vendor_id_set.create(bus=HWBus.PCCARD,
     ...                      vendor_id='0xblah',
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0xblah' is not a valid vendor ID for PC Card (32 bit)
+    ParameterError: u'0xblah' is not a valid vendor ID for PC Card (32 bit)
 
     >>> vendor_id_set.create(bus=HWBus.USB,
     ...                      vendor_id='0xblah',
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0xblah' is not a valid vendor ID for USB
+    ParameterError: u'0xblah' is not a valid vendor ID for USB
 
 IEEE1394 IDs are represented as strings with a six-digit hexadecimal
 number, prefixed by '0x'; the digits a..f must be lower cases characters.
@@ -337,11 +337,11 @@
     >>> vendor_id_1394 = vendor_id_set.create(bus=HWBus.IEEE1394,
     ...                                       vendor_id='0x0010e0',
     ...                                       vendor_name=intel_name)
-    >>> print vendor_id_1394.bus.title
+    >>> print(vendor_id_1394.bus.title)
     IEEE1394
-    >>> print vendor_id_1394.vendor_id_for_bus
+    >>> print(vendor_id_1394.vendor_id_for_bus)
     0x0010e0
-    >>> print vendor_id_1394.vendor_name.name
+    >>> print(vendor_id_1394.vendor_name.name)
     Intel
 
 A..F is rejected.
@@ -351,7 +351,7 @@
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0x0010E0' is not a valid vendor ID for IEEE1394
+    ParameterError: u'0x0010E0' is not a valid vendor ID for IEEE1394
 
 The ID must have the prefix "0x".
 
@@ -360,7 +360,7 @@
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0010E0' is not a valid vendor ID for IEEE1394
+    ParameterError: u'0010E0' is not a valid vendor ID for IEEE1394
 
 The number must have six digits.
 
@@ -369,14 +369,14 @@
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0x12345' is not a valid vendor ID for IEEE1394
+    ParameterError: u'0x12345' is not a valid vendor ID for IEEE1394
 
     >>> vendor_id_set.create(bus=HWBus.IEEE1394,
     ...                      vendor_id='0x1234567',
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0x1234567' is not a valid vendor ID for IEEE1394
+    ParameterError: u'0x1234567' is not a valid vendor ID for IEEE1394
 
 Only hex digits are allowed.
 
@@ -385,18 +385,18 @@
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '0xfoobar' is not a valid vendor ID for IEEE1394
+    ParameterError: u'0xfoobar' is not a valid vendor ID for IEEE1394
 
 SCSI vendor IDs are ASCII strings with exactly eight characters.
 
     >>> intel_scsi_id = vendor_id_set.create(bus=HWBus.SCSI,
     ...                                      vendor_id='INTEL   ',
     ...                                      vendor_name=intel_name)
-    >>> print intel_scsi_id.bus.title
+    >>> print(intel_scsi_id.bus.title)
     SCSI
     >>> intel_scsi_id.vendor_id_for_bus
     u'INTEL   '
-    >>> print intel_scsi_id.vendor_name.name
+    >>> print(intel_scsi_id.vendor_name.name)
     Intel
 
 Strings with less than eight characters are not allowed as SCSI vendor IDs...
@@ -406,7 +406,7 @@
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '1234567' is not a valid vendor ID for SCSI
+    ParameterError: u'1234567' is not a valid vendor ID for SCSI
 
 ...as well as strings with more than eight characters.
 
@@ -415,15 +415,15 @@
     ...                      vendor_name=intel_name)
     Traceback (most recent call last):
     ...
-    ParameterError: '123456789' is not a valid vendor ID for SCSI
+    ParameterError: u'123456789' is not a valid vendor ID for SCSI
 
 HWVendorIDSet.getByBusAndVendorID() is used to look up a HWVendorID record.
 
     >>> vendor_id = vendor_id_set.getByBusAndVendorID(bus=HWBus.PCI,
     ...                                               vendor_id='0x8086')
-    >>> print vendor_id.bus.title
+    >>> print(vendor_id.bus.title)
     PCI
-    >>> print vendor_id.vendor_name.name
+    >>> print(vendor_id.vendor_name.name)
     Intel
 
 If no record exists for the given bus and vendor ID,
@@ -431,7 +431,7 @@
 
     >>> vendor_id = vendor_id_set.getByBusAndVendorID(bus=HWBus.PCI,
     ...                                               vendor_id='0xffff')
-    >>> print vendor_id
+    >>> print(vendor_id)
     None
 
 HWVendorIDSet.getByBusAndVendorID() performs the same validity tests of
@@ -441,23 +441,23 @@
     >>> vendor_id_set.getByBusAndVendorID(bus=HWBus.PCI, vendor_id='8086')
     Traceback (most recent call last):
     ...
-    ParameterError: '8086' is not a valid vendor ID for PCI
+    ParameterError: u'8086' is not a valid vendor ID for PCI
 
 HWVendorIDSet.get() returns the HWVendorID record with the given ID...
 
     >>> vendor_id = vendor_id_set.get(1)
-    >>> print vendor_id.bus.name, vendor_id.vendor_id_for_bus
+    >>> print(vendor_id.bus.name, vendor_id.vendor_id_for_bus)
     SYSTEM MSI
 
 ...or None, if no such record exists.
 
-    >>> print vendor_id_set.get(1000000)
+    >>> print(vendor_id_set.get(1000000))
     None
 
 HWVendorIDSet.idsForBus() returns all known HWVendorIDs for a given bus.
 
     >>> for vendor_id in vendor_id_set.idsForBus(HWBus.PCI):
-    ...     print vendor_id.bus.name, vendor_id.vendor_id_for_bus
+    ...     print(vendor_id.bus.name, vendor_id.vendor_id_for_bus)
     PCI 0x10ae
     PCI 0x10de
     PCI 0x8086
@@ -491,33 +491,33 @@
 access them, as well as the vendor name, either via the attribute
 bus_vendor, which references HWVendorID...
 
-    >>> print usb_controller.bus_vendor.bus.title
+    >>> print(usb_controller.bus_vendor.bus.title)
     PCI
-    >>> print usb_controller.bus_vendor.vendor_id_for_bus
+    >>> print(usb_controller.bus_vendor.vendor_id_for_bus)
     0x8086
-    >>> print usb_controller.bus_vendor.vendor_name.name
+    >>> print(usb_controller.bus_vendor.vendor_name.name)
     Intel
 
 ...or via the (read-only) HWDevice properties bus, vendor_id, vendor_name.
 
-    >>> print usb_controller.bus.title
+    >>> print(usb_controller.bus.title)
     PCI
-    >>> print usb_controller.vendor_id
+    >>> print(usb_controller.vendor_id)
     0x8086
-    >>> print usb_controller.vendor_name
+    >>> print(usb_controller.vendor_name)
     Intel
 
 Other attributes stored in HWDevice are the product ID, the product name,
 the product variant and submissions. submissions is a counter of the
 number of submissions with this device.
 
-    >>> print usb_controller.bus_product_id
+    >>> print(usb_controller.bus_product_id)
     0x27cc
-    >>> print usb_controller.name
+    >>> print(usb_controller.name)
     82801GBM/GHM (ICH7 Family) USB2 EHCI Controller
-    >>> print usb_controller.variant
+    >>> print(usb_controller.variant)
     None
-    >>> print usb_controller.submissions
+    >>> print(usb_controller.submissions)
     0
 
 Like vendor IDs, product IDs of some busses have certain constraints.
@@ -533,21 +533,21 @@
     ...                                         vendor_id='0x8086',
     ...                                         product_id='0xabcd',
     ...                                         product_name='A PCI card')
-    >>> print another_pci_product.bus_product_id
+    >>> print(another_pci_product.bus_product_id)
     0xabcd
 
     >>> another_pci_product = device_set.create(bus=HWBus.PCCARD,
     ...                                         vendor_id='0x8086',
     ...                                         product_id='0xabcd',
     ...                                         product_name='A PC Card')
-    >>> print another_pci_product.bus_product_id
+    >>> print(another_pci_product.bus_product_id)
     0xabcd
 
     >>> another_usb_product = device_set.create(bus=HWBus.USB,
     ...                                         vendor_id='0x8086',
     ...                                         product_id='0xabcd',
     ...                                         product_name='A USB device')
-    >>> print another_usb_product.bus_product_id
+    >>> print(another_usb_product.bus_product_id)
     0xabcd
 
 A..F is rejected.
@@ -558,7 +558,7 @@
     ...                   product_name='A PCI card')
     Traceback (most recent call last):
     ...
-    ParameterError: '0xABCD' is not a valid product ID for PCI
+    ParameterError: u'0xABCD' is not a valid product ID for PCI
 
     >>> device_set.create(bus=HWBus.PCCARD,
     ...                   vendor_id='0x8086',
@@ -566,7 +566,7 @@
     ...                   product_name='A PC Card')
     Traceback (most recent call last):
     ...
-    ParameterError: '0xABCD' is not a valid product ID for PC Card (32 bit)
+    ParameterError: u'0xABCD' is not a valid product ID for PC Card (32 bit)
 
     >>> device_set.create(bus=HWBus.USB,
     ...                   vendor_id='0x8086',
@@ -574,7 +574,7 @@
     ...                   product_name='A USB device')
     Traceback (most recent call last):
     ...
-    ParameterError: '0xABCD' is not a valid product ID for USB
+    ParameterError: u'0xABCD' is not a valid product ID for USB
 
 The ID must have the prefix "0x".
 
@@ -584,7 +584,7 @@
     ...                   product_name='A PCI card')
     Traceback (most recent call last):
     ...
-    ParameterError: '1234' is not a valid product ID for PCI
+    ParameterError: u'1234' is not a valid product ID for PCI
 
     >>> device_set.create(bus=HWBus.PCCARD,
     ...                   vendor_id='0x8086',
@@ -592,7 +592,7 @@
     ...                   product_name='A PC Card')
     Traceback (most recent call last):
     ...
-    ParameterError: '1234' is not a valid product ID for PC Card (32 bit)
+    ParameterError: u'1234' is not a valid product ID for PC Card (32 bit)
 
     >>> device_set.create(bus=HWBus.USB,
     ...                   vendor_id='0x8086',
@@ -600,7 +600,7 @@
     ...                   product_name='A USB device')
     Traceback (most recent call last):
     ...
-    ParameterError: '1234' is not a valid product ID for USB
+    ParameterError: u'1234' is not a valid product ID for USB
 
 The number must have four digits.
 
@@ -610,7 +610,7 @@
     ...                   product_name='A PCI card')
     Traceback (most recent call last):
     ...
-    ParameterError: '0x123' is not a valid product ID for PCI
+    ParameterError: u'0x123' is not a valid product ID for PCI
 
     >>> device_set.create(bus=HWBus.PCCARD,
     ...                   vendor_id='0x8086',
@@ -618,7 +618,7 @@
     ...                   product_name='A PC Card')
     Traceback (most recent call last):
     ...
-    ParameterError: '0x123' is not a valid product ID for PC Card (32 bit)
+    ParameterError: u'0x123' is not a valid product ID for PC Card (32 bit)
 
     >>> device_set.create(bus=HWBus.USB,
     ...                   vendor_id='0x8086',
@@ -626,7 +626,7 @@
     ...                   product_name='A USB device')
     Traceback (most recent call last):
     ...
-    ParameterError: '0x123' is not a valid product ID for USB
+    ParameterError: u'0x123' is not a valid product ID for USB
 
     >>> device_set.create(bus=HWBus.PCI,
     ...                   vendor_id='0x8086',
@@ -634,7 +634,7 @@
     ...                   product_name='A PCI card')
     Traceback (most recent call last):
     ...
-    ParameterError: '0x12345' is not a valid product ID for PCI
+    ParameterError: u'0x12345' is not a valid product ID for PCI
 
     >>> device_set.create(bus=HWBus.PCCARD,
     ...                   vendor_id='0x8086',
@@ -642,7 +642,7 @@
     ...                   product_name='A PC Card')
     Traceback (most recent call last):
     ...
-    ParameterError: '0x12345' is not a valid product ID for PC Card (32 bit)
+    ParameterError: u'0x12345' is not a valid product ID for PC Card (32 bit)
 
     >>> device_set.create(bus=HWBus.USB,
     ...                   vendor_id='0x8086',
@@ -650,7 +650,7 @@
     ...                   product_name='A USB device')
     Traceback (most recent call last):
     ...
-    ParameterError: '0x12345' is not a valid product ID for USB
+    ParameterError: u'0x12345' is not a valid product ID for USB
 
 Only hex digits are allowed.
 
@@ -660,7 +660,7 @@
     ...                   product_name='A PCI card')
     Traceback (most recent call last):
     ...
-    ParameterError: '0xblah' is not a valid product ID for PCI
+    ParameterError: u'0xblah' is not a valid product ID for PCI
 
     >>> device_set.create(bus=HWBus.PCCARD,
     ...                   vendor_id='0x8086',
@@ -668,7 +668,7 @@
     ...                   product_name='A PC Card')
     Traceback (most recent call last):
     ...
-    ParameterError: '0xblah' is not a valid product ID for PC Card (32 bit)
+    ParameterError: u'0xblah' is not a valid product ID for PC Card (32 bit)
 
     >>> device_set.create(bus=HWBus.USB,
     ...                   vendor_id='0x8086',
@@ -676,7 +676,7 @@
     ...                   product_name='A USB device')
     Traceback (most recent call last):
     ...
-    ParameterError: '0xblah' is not a valid product ID for USB
+    ParameterError: u'0xblah' is not a valid product ID for USB
 
 SCSI product IDs are ASCII strings with 16 characters.
 
@@ -695,7 +695,7 @@
     ...                   product_name='A SCSI device')
     Traceback (most recent call last):
     ...
-    ParameterError: '123456789012345' is not a valid product ID for SCSI
+    ParameterError: u'123456789012345' is not a valid product ID for SCSI
 
 ...as well as strings with more than 16 characters.
 
@@ -705,7 +705,7 @@
     ...                   product_name='A SCSI device')
     Traceback (most recent call last):
     ...
-    ParameterError: '12345678901234567' is not a valid product ID for SCSI
+    ParameterError: u'12345678901234567' is not a valid product ID for SCSI
 
 
 Unknown Vendor IDs
@@ -730,7 +730,7 @@
     ...                                       vendor_id='0x4321',
     ...                                       product_id='0x8765',
     ...                                       product_name='mind sensor')
-    >>> print new_vendor_device.bus_vendor.vendor_name.name
+    >>> print(new_vendor_device.bus_vendor.vendor_name.name)
     Unknown
 
 
@@ -762,13 +762,13 @@
     ...                                          vendor_id='0x07b3',
     ...                                          product_id='0x0017',
     ...                                          product_name='some scanner')
-    >>> print some_plustek_scanner.bus_vendor.vendor_id_for_bus
+    >>> print(some_plustek_scanner.bus_vendor.vendor_id_for_bus)
     0x07b3
-    >>> print some_plustek_scanner.bus_vendor.vendor_name.name
+    >>> print(some_plustek_scanner.bus_vendor.vendor_name.name)
     Plustek
-    >>> print some_plustek_scanner.name
+    >>> print(some_plustek_scanner.name)
     some scanner
-    >>> print some_plustek_scanner.variant
+    >>> print(some_plustek_scanner.variant)
     None
 
 Once we know that (bus, vendor ID, product ID) does not uniquely
@@ -802,15 +802,15 @@
     ...                                   vendor_id=hal_vendor_name,
     ...                                   product_id=hal_product_name,
     ...                                   product_name=hal_product_name)
-    >>> print tuffbook_2600.bus_vendor.bus.title
+    >>> print(tuffbook_2600.bus_vendor.bus.title)
     System
-    >>> print tuffbook_2600.bus_vendor.vendor_id_for_bus
-    Tonka
-    >>> print tuffbook_2600.bus_vendor.vendor_name.name
-    Tonka
-    >>> print tuffbook_2600.bus_product_id
+    >>> print(tuffbook_2600.bus_vendor.vendor_id_for_bus)
+    Tonka
+    >>> print(tuffbook_2600.bus_vendor.vendor_name.name)
+    Tonka
+    >>> print(tuffbook_2600.bus_product_id)
     Tuffbook 2600
-    >>> print tuffbook_2600.name
+    >>> print(tuffbook_2600.name)
     Tuffbook 2600
 
 The tuple (bus_vendor, bus_product_id, variant) must be unique.
@@ -848,50 +848,50 @@
 HWDeviceSet.getByDeviceID()
 
     >>> device = device_set.getByDeviceID(HWBus.USB, '0x07b3', '0x0017')
-    >>> print device.bus_vendor.bus.title
+    >>> print(device.bus_vendor.bus.title)
     USB
-    >>> print device.bus_vendor.vendor_id_for_bus
+    >>> print(device.bus_vendor.vendor_id_for_bus)
     0x07b3
-    >>> print device.bus_product_id
+    >>> print(device.bus_product_id)
     0x0017
-    >>> print device.name
+    >>> print(device.name)
     some scanner
 
 The call to HWDeviceSet.getByDeviceID() above did not specify a product
 variant. In such a case, the record having variant==None is returned
 
-    >>> print device.variant
+    >>> print(device.variant)
     None
 
 If a variant name is given, we get the HWDevice record of that variant.
 
     >>> device = device_set.getByDeviceID(HWBus.USB, '0x07b3', '0x0017',
     ...                                   'OpticPro UT16')
-    >>> print device.bus_vendor.bus.title
+    >>> print(device.bus_vendor.bus.title)
     USB
-    >>> print device.bus_vendor.vendor_id_for_bus
+    >>> print(device.bus_vendor.vendor_id_for_bus)
     0x07b3
-    >>> print device.bus_product_id
+    >>> print(device.bus_product_id)
     0x0017
-    >>> print device.name
+    >>> print(device.name)
     OpticPro UT16
-    >>> print device.variant
+    >>> print(device.variant)
     OpticPro UT16
 
 If the given parameters do not match any existing record, None is
 returned.
 
-    >>> print device_set.getByDeviceID(HWBus.PCI, '0x07b3', '0x0017',
-    ...                                'OpticPro UT16')
-    None
-    >>> print device_set.getByDeviceID(HWBus.USB, '0xffff', '0x0017',
-    ...                                'OpticPro UT16')
-    None
-    >>> print device_set.getByDeviceID(HWBus.PCI, '0x07b3', '0xffff',
-    ...                                'OpticPro UT16')
-    None
-    >>> print device_set.getByDeviceID(HWBus.PCI, '0x07b3', '0x0017',
-    ...                                'nonsense')
+    >>> print(device_set.getByDeviceID(HWBus.PCI, '0x07b3', '0x0017',
+    ...                                'OpticPro UT16'))
+    None
+    >>> print(device_set.getByDeviceID(HWBus.USB, '0xffff', '0x0017',
+    ...                                'OpticPro UT16'))
+    None
+    >>> print(device_set.getByDeviceID(HWBus.PCI, '0x07b3', '0xffff',
+    ...                                'OpticPro UT16'))
+    None
+    >>> print(device_set.getByDeviceID(HWBus.PCI, '0x07b3', '0x0017',
+    ...                                'nonsense'))
     None
 
 The parameters vendor_id and product_id must be valid IDs for the
@@ -900,12 +900,12 @@
     >>> device_set.getByDeviceID(HWBus.USB, '07b3', '0x0017')
     Traceback (most recent call last):
     ...
-    ParameterError: '07b3' is not a valid vendor ID for USB
+    ParameterError: u'07b3' is not a valid vendor ID for USB
 
     >>> device_set.getByDeviceID(HWBus.USB, '0x07b3', '0017')
     Traceback (most recent call last):
     ...
-    ParameterError: '0017' is not a valid product ID for USB
+    ParameterError: u'0017' is not a valid product ID for USB
 
 HWDeviceSet.getOrCreate() returns an existing record matching the given
 parameters or creates a new one, if no existing record matches.
@@ -915,79 +915,79 @@
     ...                                  product_id='0x0017',
     ...                                  product_name='OpticPro UT16',
     ...                                  variant='OpticPro UT16')
-    >>> print device2.bus_vendor.bus.title
+    >>> print(device2.bus_vendor.bus.title)
     USB
-    >>> print device2.bus_vendor.vendor_id_for_bus
+    >>> print(device2.bus_vendor.vendor_id_for_bus)
     0x07b3
-    >>> print device2.bus_product_id
+    >>> print(device2.bus_product_id)
     0x0017
-    >>> print device2.name
-    OpticPro UT16
-    >>> print device2.variant
-    OpticPro UT16
-    >>> print device2.id == device.id
+    >>> print(device2.name)
+    OpticPro UT16
+    >>> print(device2.variant)
+    OpticPro UT16
+    >>> print(device2.id == device.id)
     True
 
     >>> device3 = device_set.getByDeviceID(bus=HWBus.USB,
     ...                                    vendor_id='0x07b3',
     ...                                    product_id='0x0017',
     ...                                    variant='Some other scanner')
-    >>> print device3
+    >>> print(device3)
     None
     >>> device3 = device_set.getOrCreate(bus=HWBus.USB,
     ...                                  vendor_id='0x07b3',
     ...                                  product_id='0x0017',
     ...                                  product_name='Some other scanner',
     ...                                  variant='Some other scanner')
-    >>> print device3.bus_vendor.bus.title
+    >>> print(device3.bus_vendor.bus.title)
     USB
-    >>> print device3.bus_vendor.vendor_id_for_bus
+    >>> print(device3.bus_vendor.vendor_id_for_bus)
     0x07b3
-    >>> print device3.bus_product_id
+    >>> print(device3.bus_product_id)
     0x0017
-    >>> print device3.name
+    >>> print(device3.name)
     Some other scanner
-    >>> print device3.variant
+    >>> print(device3.variant)
     Some other scanner
 
     >>> device4 = device_set.getOrCreate(bus=HWBus.USB,
     ...                                  vendor_id='0x07b3',
     ...                                  product_id='0x0015',
     ...                                  product_name='OpticPro U24')
-    >>> print device4.bus_vendor.bus.title
+    >>> print(device4.bus_vendor.bus.title)
     USB
-    >>> print device4.bus_vendor.vendor_id_for_bus
+    >>> print(device4.bus_vendor.vendor_id_for_bus)
     0x07b3
-    >>> print device4.bus_product_id
+    >>> print(device4.bus_product_id)
     0x0015
-    >>> print device4.name
+    >>> print(device4.name)
     OpticPro U24
-    >>> print device4.variant
+    >>> print(device4.variant)
     None
 
 
 HWDeviceSet.getByID() returns a HWDevice record with the given database ID.
 
     >>> device = device_set.getByID(1)
-    >>> print device.id
+    >>> print(device.id)
     1
-    >>> print device.vendor_id
+    >>> print(device.vendor_id)
     MSI
-    >>> print device.bus_product_id
+    >>> print(device.bus_product_id)
     MS-7369
 
 HWDeviceSet.getByID() returns None if no record with the passed ID exists.
 
     >>> device = device_set.getByID(1000000)
-    >>> print device
+    >>> print(device)
     None
 
 HWDeviceSet.search() returns all devices with a given bus and vendor ID.
 
     >>> devices = device_set.search(bus=HWBus.USB, vendor_id='0x07b3')
     >>> for device in devices:
-    ...     print device.bus.title, device.vendor_id, device.bus_product_id,
-    ...     print device.variant
+    ...     print(device.bus.title, device.vendor_id, device.bus_product_id,
+    ...           device.variant)
     USB 0x07b3 0x0017 None
     USB 0x07b3 0x0017 OpticPro UT12
     USB 0x07b3 0x0017 OpticPro UT16
@@ -999,8 +999,8 @@
     >>> devices = device_set.search(
     ...     bus=HWBus.USB, vendor_id='0x07b3', product_id='0x0017')
     >>> for device in devices:
-    ...     print device.bus.title, device.vendor_id, device.bus_product_id,
-    ...     print device.variant
+    ...     print(device.bus.title, device.vendor_id, device.bus_product_id,
+    ...           device.variant)
     USB 0x07b3 0x0017 None
     USB 0x07b3 0x0017 OpticPro UT12
     USB 0x07b3 0x0017 OpticPro UT16
@@ -1013,13 +1013,13 @@
     ...     bus=HWBus.USB, vendor_id='invalid', product_id='0x0017')
     Traceback (most recent call last):
     ...
-    ParameterError: 'invalid' is not a valid vendor ID for USB
+    ParameterError: u'invalid' is not a valid vendor ID for USB
 
     >>> devices = device_set.search(
     ...     bus=HWBus.USB, vendor_id='0x07b3', product_id='nonsense')
     Traceback (most recent call last):
     ...
-    ParameterError: 'nonsense' is not a valid product ID for USB
+    ParameterError: u'nonsense' is not a valid product ID for USB
 
 HWDevice.getSubmissions() returns submissions which contain this device.
 
@@ -1036,7 +1036,7 @@
     >>> sata_controller = device_set.getByDeviceID(
     ...     bus=HWBus.PCI, vendor_id='0x10de', product_id='0x045d')
     >>> for submission in sata_controller.getSubmissions():
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
 We can limit the results to a specific driver. (See below for details about
@@ -1047,13 +1047,13 @@
     ...     'linux-image-2.6.24-19-generic', 'ahci')
     >>> for submission in sata_controller.getSubmissions(
     ...     driver=ahci_driver):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
     >>> usb_storage_driver = getUtility(IHWDriverSet).getByPackageAndName(
     ...     'linux-image-2.6.24-19-generic', 'usb-storage')
-    >>> print list(sata_controller.getSubmissions(
-    ...     driver=usb_storage_driver))
+    >>> print(list(sata_controller.getSubmissions(
+    ...     driver=usb_storage_driver)))
     []
 
 We can limit the results to a specific distribution.
@@ -1064,7 +1064,7 @@
     >>> ubuntu = distribution_set.getByName('ubuntu')
     >>> for submission in sata_controller.getSubmissions(
     ...     distribution=ubuntu):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
     >>> debian = distribution_set.getByName('debian')
@@ -1075,7 +1075,7 @@
 
     >>> for submission in sata_controller.getSubmissions(
     ...     architecture='i386'):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
     >>> sata_controller.getSubmissions(architecture='amd64').count()
@@ -1085,7 +1085,7 @@
 
     >>> for submission in sata_controller.getSubmissions(
     ...     distroseries=ubuntu['hoary']):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
     >>> sata_controller.getSubmissions(distroseries=ubuntu['warty']).count()
@@ -1095,7 +1095,7 @@
 
     >>> for submission in sata_controller.getSubmissions(
     ...     distroseries=ubuntu['hoary'], architecture='i386'):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
     >>> sata_controller.getSubmissions(
@@ -1107,7 +1107,7 @@
     >>> from lp.registry.interfaces.person import IPersonSet
     >>> owner = getUtility(IPersonSet).getByName('name12')
     >>> for submission in sata_controller.getSubmissions(owner=owner):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
     >>> not_owner = getUtility(IPersonSet).getByName('name20')
@@ -1122,7 +1122,7 @@
 HWDeviceDriverLink (see below) with this device.
 
     >>> for driver in sata_controller.drivers:
-    ...     print driver.package_name, driver.name
+    ...     print(driver.package_name, driver.name)
     linux-image-2.6.24-19-generic ahci
 
 
@@ -1143,17 +1143,17 @@
     >>> variant = device_name_variant_set.create(device=optic_pro_ut16,
     ...                                          vendor_name='Medion',
     ...                                          product_name='MD 1234')
-    >>> print variant.device.bus_vendor.vendor_name.name
+    >>> print(variant.device.bus_vendor.vendor_name.name)
     Plustek
-    >>> print variant.vendor_name.name
+    >>> print(variant.vendor_name.name)
     Medion
-    >>> print variant.product_name
+    >>> print(variant.product_name)
     MD 1234
 
 We count the number of submissions which told us an alternative device
 name.
 
-    >>> print variant.submissions
+    >>> print(variant.submissions)
     0
 
 The tuple (device, vendor_name, product_name) must be unique.
@@ -1191,11 +1191,11 @@
     >>> usb_driver = driver_set.create(package_name='linux-image-generic',
     ...                                name='usb',
     ...                                license=License.GNU_GPL_V2)
-    >>> print usb_driver.name
+    >>> print(usb_driver.name)
     usb
-    >>> print usb_driver.package_name
+    >>> print(usb_driver.package_name)
     linux-image-generic
-    >>> print usb_driver.license.title
+    >>> print(usb_driver.license.title)
     GNU GPL v2
 
 The submitted data does not need to contain package information for all
@@ -1206,21 +1206,21 @@
     >>> driver2 = driver_set.create(package_name=None,
     ...                             name='whatever',
     ...                             license=License.GNU_GPL_V2)
-    >>> print driver2.name
+    >>> print(driver2.name)
     whatever
-    >>> print repr(driver2.package_name)
+    >>> print(repr(driver2.package_name))
     u''
-    >>> print driver2.license.title
+    >>> print(driver2.license.title)
     GNU GPL v2
 
     >>> driver_blank_package_name = driver_set.create(package_name='',
     ...                                               name='bar',
     ...                             license=License.GNU_GPL_V3)
-    >>> print driver_blank_package_name.name
+    >>> print(driver_blank_package_name.name)
     bar
-    >>> print repr(driver_blank_package_name.package_name)
+    >>> print(repr(driver_blank_package_name.package_name))
     u''
-    >>> print driver_blank_package_name.license.title
+    >>> print(driver_blank_package_name.license.title)
     GNU GPL v3
 
 Since we also do not always know the license of a driver, the license
@@ -1229,11 +1229,11 @@
     >>> driver3 = driver_set.create(package_name='',
     ...                             name='something_else',
     ...                             license=None)
-    >>> print driver3.name
+    >>> print(driver3.name)
     something_else
-    >>> print repr(driver3.package_name)
+    >>> print(repr(driver3.package_name))
     u''
-    >>> print driver3.license
+    >>> print(driver3.license)
     None
 
 The tuple (driver name, package name) must be unique.
@@ -1263,18 +1263,18 @@
 IHWDriverSet.getByPackageAndName().
 
     >>> driver = driver_set.getByPackageAndName('linux-image-generic', 'usb')
-    >>> print driver.package_name
+    >>> print(driver.package_name)
     linux-image-generic
-    >>> print driver.name
+    >>> print(driver.name)
     usb
 
 If we want to search for a driver without a known package, we can
 pass None as well as the empty string.
 
     >>> driver = driver_set.getByPackageAndName('', 'whatever')
-    >>> print repr(driver.package_name)
+    >>> print(repr(driver.package_name))
     u''
-    >>> print driver.name
+    >>> print(driver.name)
     whatever
 
     >>> driver2 = driver_set.getByPackageAndName(None, 'whatever')
@@ -1285,34 +1285,34 @@
 IHWDriverSet.getByPackageAndName() call, None is returned.
 
     >>> driver = driver_set.getByPackageAndName('nonsense', 'more nonsense')
-    >>> print driver
+    >>> print(driver)
     None
 
 IHWDriverSet.getOrCreate() returns an existing record matching
 the given parameters or creates a new one, if no existing record matches.
 
     >>> driver = driver_set.getOrCreate('linux-image-generic', 'usb')
-    >>> print driver.package_name
+    >>> print(driver.package_name)
     linux-image-generic
-    >>> print driver.name
+    >>> print(driver.name)
     usb
 
     >>> driver = driver_set.getByPackageAndName('linux-image-generic', 'foo')
-    >>> print driver
+    >>> print(driver)
     None
     >>> driver = driver_set.getOrCreate('linux-image-generic', 'foo')
-    >>> print driver.name
+    >>> print(driver.name)
     foo
-    >>> print driver.package_name
+    >>> print(driver.package_name)
     linux-image-generic
 
 If we pass None as the value for package_name, we get records where
 package_name is None or the empty string.
 
     >>> driver = driver_set.getOrCreate(None, 'whatever')
-    >>> print repr(driver.package_name)
+    >>> print(repr(driver.package_name))
     u''
-    >>> print driver.name
+    >>> print(driver.name)
     whatever
 
 Older HWDriver records may store None as the package name. We can
@@ -1320,9 +1320,9 @@
 
     >>> from lp.hardwaredb.model.hwdb import HWDriver
     >>> old_driver = HWDriver(package_name=None, name=u'foo', license=None)
-    >>> print old_driver.name
+    >>> print(old_driver.name)
     foo
-    >>> print old_driver.package_name
+    >>> print(old_driver.package_name)
     None
 
     >>> driver = driver_set.getOrCreate(None, 'foo')
@@ -1340,20 +1340,20 @@
 
     >>> drivers = driver_set.search(package_name='linux-image-generic')
     >>> for driver in drivers:
-    ...    print driver.package_name, driver.name
+    ...    print(driver.package_name, driver.name)
     linux-image-generic usb
     linux-image-generic foo
 
     >>> drivers = driver_set.search(name='usb')
     >>> for driver in drivers:
-    ...    print driver.package_name, driver.name
+    ...    print(driver.package_name, driver.name)
     linux-image-2.6.24-19-generic usb
     linux-image-generic usb
 
     >>> drivers = driver_set.search(
     ...     package_name='linux-image-2.6.24-19-generic', name='ahci')
     >>> for driver in drivers:
-    ...    print driver.package_name, driver.name
+    ...    print(driver.package_name, driver.name)
     linux-image-2.6.24-19-generic ahci
 
 If package_name is an empty string, driver records are returned where
@@ -1363,7 +1363,7 @@
 
     >>> drivers = driver_set.search(package_name='')
     >>> for driver in drivers:
-    ...    print repr(driver.package_name), driver.name
+    ...    print(repr(driver.package_name), driver.name)
     u'' whatever
     u'' bar
     u'' something_else
@@ -1371,12 +1371,12 @@
 
     >>> drivers = driver_set.search(package_name='', name='whatever')
     >>> for driver in drivers:
-    ...    print repr(driver.package_name), driver.name
+    ...    print(repr(driver.package_name), driver.name)
     u'' whatever
 
     >>> drivers = driver_set.search(package_name='', name='foo')
     >>> for driver in drivers:
-    ...    print repr(driver.package_name), driver.name
+    ...    print(repr(driver.package_name), driver.name)
     None foo
 
 If no parameters are specified, IHWDriverSet.search() returns all driver
@@ -1384,7 +1384,7 @@
 
     >>> drivers = driver_set.search()
     >>> for driver in drivers:
-    ...    print repr(driver.package_name), driver.name
+    ...    print(repr(driver.package_name), driver.name)
     u'linux-image-2.6.24-19-generic' ehci_hcd
     u'linux-image-2.6.24-19-generic' usb
     u'linux-image-2.6.24-19-generic' usb-storage
@@ -1402,17 +1402,17 @@
 HWDriverSet.getByID() returns a HWDriver record with the given database ID.
 
     >>> driver = driver_set.getByID(1)
-    >>> print driver.id
+    >>> print(driver.id)
     1
-    >>> print driver.package_name
+    >>> print(driver.package_name)
     linux-image-2.6.24-19-generic
-    >>> print driver.name
+    >>> print(driver.name)
     ehci_hcd
 
 HWDriverSet.getByID() returns None if no record with the passed ID exists.
 
     >>> driver = driver_set.getByID(1000000)
-    >>> print driver
+    >>> print(driver)
     None
 
     >>> transaction.abort()
@@ -1422,23 +1422,23 @@
 
     >>> driver = driver_set.getByID(1)
     >>> for submission in driver.getSubmissions():
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
 We can limit our search to submissions for a particular distribution.
 
     >>> for submission in driver.getSubmissions(distribution=ubuntu):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
-    >>> print driver.getSubmissions(distribution=debian).count()
+    >>> print(driver.getSubmissions(distribution=debian).count())
     0
 
 We can limit the results to a specific distro series.
 
     >>> for submission in driver.getSubmissions(
     ...     distroseries=ubuntu['hoary']):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
     >>> driver.getSubmissions(distroseries=ubuntu['warty']).count()
@@ -1448,7 +1448,7 @@
 
     >>> for submission in driver.getSubmissions(
     ...     distroseries=ubuntu['hoary'], architecture='i386'):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
     >>> driver.getSubmissions(
@@ -1458,7 +1458,7 @@
 And We can search for submissions from a particular user.
 
     >>> for submission in driver.getSubmissions(owner=owner):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
     >>> driver.getSubmissions(owner=not_owner).count()
@@ -1477,7 +1477,7 @@
 
     >>> switch_dbuser('launchpad')
     >>> for driver_name in driver_set.all_driver_names():
-    ...     print driver_name.name
+    ...     print(driver_name.name)
     ahci
     bar
     ehci_hcd
@@ -1498,7 +1498,7 @@
     >>> store.add(HWDriver(name='foo', package_name=None))
     <HWDriver at...
     >>> for package_name in driver_set.all_package_names():
-    ...     print package_name.package_name
+    ...     print(package_name.package_name)
     <BLANKLINE>
     linux-image-2.6.24-19-generic
     linux-image-generic
@@ -1515,9 +1515,9 @@
     >>> device_driver_link_set = getUtility(IHWDeviceDriverLinkSet)
     >>> usb_controller_usb_link = device_driver_link_set.create(
     ...     device=usb_controller, driver=usb_driver)
-    >>> print usb_controller_usb_link.device.name
+    >>> print(usb_controller_usb_link.device.name)
     82801GBM/GHM (ICH7 Family) USB2 EHCI Controller
-    >>> print usb_controller_usb_link.driver.name
+    >>> print(usb_controller_usb_link.driver.name)
     usb
 
 A device may be linked to more than one driver. A USB2 host controller
@@ -1529,9 +1529,9 @@
     ...     license=License.GNU_GPL_V2)
     >>> usb_controller_ehci_hcd_link = device_driver_link_set.create(
     ...     device=usb_controller, driver=ehci_hcd_driver)
-    >>> print usb_controller_ehci_hcd_link.device.name
+    >>> print(usb_controller_ehci_hcd_link.device.name)
     82801GBM/GHM (ICH7 Family) USB2 EHCI Controller
-    >>> print usb_controller_ehci_hcd_link.driver.name
+    >>> print(usb_controller_ehci_hcd_link.driver.name)
     ehci_hcd
 
 A scanner can be linked to the kernel driver for the physical interface
@@ -1539,9 +1539,9 @@
 
     >>> scanner_usb_driver_link = device_driver_link_set.create(
     ...     device=optic_pro_ut12, driver=usb_driver)
-    >>> print scanner_usb_driver_link.device.name
+    >>> print(scanner_usb_driver_link.device.name)
     OpticPro UT12
-    >>> print scanner_usb_driver_link.driver.name
+    >>> print(scanner_usb_driver_link.driver.name)
     usb
 
     >>> sane_plustek_driver = driver_set.create(package_name='libsane',
@@ -1549,9 +1549,9 @@
     ...                                         license=License.GNU_GPL_V2)
     >>> scanner_sane_plustek_link = device_driver_link_set.create(
     ...     device=optic_pro_ut12, driver=sane_plustek_driver)
-    >>> print scanner_sane_plustek_link.device.name
+    >>> print(scanner_sane_plustek_link.device.name)
     OpticPro UT12
-    >>> print scanner_sane_plustek_link.driver.name
+    >>> print(scanner_sane_plustek_link.driver.name)
     plustek
 
 Devices can have alternative drivers. Let's assume that Plustek
@@ -1565,9 +1565,9 @@
 
     >>> link3 = device_driver_link_set.create(device=optic_pro_ut12,
     ...                                         driver=closed_driver)
-    >>> print link3.device.name
+    >>> print(link3.device.name)
     OpticPro UT12
-    >>> print link3.driver.name
+    >>> print(link3.driver.name)
     ut12
 
 We have two cases, where we do not (or can not) store driver information
@@ -1611,9 +1611,9 @@
 
     >>> link = device_driver_link_set.getByDeviceAndDriver(optic_pro_ut12,
     ...                                                    closed_driver)
-    >>> print link.device.name
+    >>> print(link.device.name)
     OpticPro UT12
-    >>> print link.driver.name
+    >>> print(link.driver.name)
     ut12
 
 If no record exists for the given tuple (device, driver),
@@ -1621,7 +1621,7 @@
 
     >>> link = device_driver_link_set.getByDeviceAndDriver(optic_pro_ut12,
     ...                                                    ehci_hcd_driver)
-    >>> print link
+    >>> print(link)
     None
 
 HWDeviceDriverLinkSet.getOrCreate() returns an existing record matching
@@ -1629,20 +1629,20 @@
 
     >>> link = device_driver_link_set.getOrCreate(optic_pro_ut12,
     ...                                           closed_driver)
-    >>> print link.device.name
+    >>> print(link.device.name)
     OpticPro UT12
-    >>> print link.driver.name
+    >>> print(link.driver.name)
     ut12
-    >>> print link.id == link3.id
+    >>> print(link.id == link3.id)
     True
     >>> link = device_driver_link_set.getByDeviceAndDriver(optic_pro_ut12,
     ...                                                    None)
-    >>> print link
+    >>> print(link)
     None
     >>> link = device_driver_link_set.getOrCreate(optic_pro_ut12, None)
-    >>> print link.device.name
+    >>> print(link.device.name)
     OpticPro UT12
-    >>> print link.driver
+    >>> print(link.driver)
     None
 
 
@@ -1684,17 +1684,17 @@
 
     >>> device_class_printer = optic_pro_ut12.getOrCreateDeviceClass(
     ...     main_class=0x07, sub_class=0x01)
-    >>> print device_class_printer.device.name
+    >>> print(device_class_printer.device.name)
     OpticPro UT12
-    >>> print device_class_printer.main_class
+    >>> print(device_class_printer.main_class)
     7
-    >>> print device_class_printer.sub_class
+    >>> print(device_class_printer.sub_class)
     1
 
 IHWDdevice.classes contains the set of classes defined for this device.
 
     >>> for device_class in optic_pro_ut12.classes:
-    ...     print device_class.main_class, device_class.sub_class
+    ...     print(device_class.main_class, device_class.sub_class)
     7 1
     16 0
 
@@ -1709,7 +1709,7 @@
     >>> switch_dbuser('launchpad')
     >>> optic_pro_ut12.removeDeviceClass(main_class=0x07, sub_class=0x01)
     >>> for device_class in optic_pro_ut12.classes:
-    ...     print device_class.main_class, device_class.sub_class
+    ...     print(device_class.main_class, device_class.sub_class)
     16 0
 
     >>> switch_dbuser('hwdb-submission-processor')
@@ -1739,17 +1739,17 @@
     >>> submitted_tuffbook_2600 = submission_device_set.create(
     ...     device_driver_link=tuffbook_2600_device_driver_link,
     ...     submission=sample_submission, parent=None, hal_device_id=1)
-    >>> print submitted_tuffbook_2600.device_driver_link.device.name
-    Tuffbook 2600
-    >>> print submitted_tuffbook_2600.device.name
-    Tuffbook 2600
-    >>> print submitted_tuffbook_2600.driver
+    >>> print(submitted_tuffbook_2600.device_driver_link.device.name)
+    Tuffbook 2600
+    >>> print(submitted_tuffbook_2600.device.name)
+    Tuffbook 2600
+    >>> print(submitted_tuffbook_2600.driver)
     None
-    >>> print submitted_tuffbook_2600.submission.submission_key
+    >>> print(submitted_tuffbook_2600.submission.submission_key)
     test_submission_id_1
-    >>> print submitted_tuffbook_2600.parent
+    >>> print(submitted_tuffbook_2600.parent)
     None
-    >>> print submitted_tuffbook_2600.hal_device_id
+    >>> print(submitted_tuffbook_2600.hal_device_id)
     1
 
 ...while ordinary device entries have the attribute parent set. The
@@ -1772,15 +1772,15 @@
     ...      submission=sample_submission,
     ...      parent=submitted_usb_ehci_hcd_controller,
     ...      hal_device_id=3)
-    >>> print submitted_usb_controller.device_driver_link.device.name
-    82801GBM/GHM (ICH7 Family) USB2 EHCI Controller
-    >>> print submitted_usb_controller.device_driver_link.driver.name
-    usb
-    >>> print submitted_usb_controller.device.name
-    82801GBM/GHM (ICH7 Family) USB2 EHCI Controller
-    >>> print submitted_usb_controller.driver.name
-    usb
-    >>> print submitted_usb_controller.hal_device_id
+    >>> print(submitted_usb_controller.device_driver_link.device.name)
+    82801GBM/GHM (ICH7 Family) USB2 EHCI Controller
+    >>> print(submitted_usb_controller.device_driver_link.driver.name)
+    usb
+    >>> print(submitted_usb_controller.device.name)
+    82801GBM/GHM (ICH7 Family) USB2 EHCI Controller
+    >>> print(submitted_usb_controller.driver.name)
+    usb
+    >>> print(submitted_usb_controller.hal_device_id)
     3
 
 The USB controller is connected to an (often internal) USB hub. We don't
@@ -1820,14 +1820,14 @@
     ...     submission=sample_submission)
     >>> def print_device(submission_device, indent=0):
     ...     if indent > 0:
-    ...         print '-' * indent + '>',
+    ...         print('-' * indent + '>', end=' ')
     ...     device = submission_device.device_driver_link.device
     ...     driver = submission_device.device_driver_link.driver
-    ...     print device.bus_vendor.vendor_name.name, device.name,
+    ...     print(device.bus_vendor.vendor_name.name, device.name, end=' ')
     ...     if driver is not None:
-    ...         print driver.name
+    ...         print(driver.name)
     ...     else:
-    ...         print '(no driver)'
+    ...         print('(no driver)')
     ...     for sub_device in submitted_devices:
     ...         if sub_device.parent == submission_device:
     ...             print_device(sub_device, indent+1)
@@ -1851,7 +1851,7 @@
 
 This method returns None if a nonexistent ID is passed.
 
-    >>> print submission_device_set.get(1000000)
+    >>> print(submission_device_set.get(1000000))
     None
 
 
@@ -1861,8 +1861,9 @@
 HWSubmissionDeviceSet.numDevicesInSubmissions() returns how often a
 device appears in HWDB submissions.
 
-    >>> print submission_device_set.numDevicesInSubmissions(
-    ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ')
+    >>> print(submission_device_set.numDevicesInSubmissions(
+    ...     bus=HWBus.IDE, vendor_id='SEAGATE',
+    ...     product_id='ST3250820NS     '))
     1
 
 If a device appears more than once in a submission, it is counted as often
@@ -1883,8 +1884,9 @@
 The number returned for the query "count the number of Seagate
 ST3250820NS" disks increased.
 
-    >>> print submission_device_set.numDevicesInSubmissions(
-    ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ')
+    >>> print(submission_device_set.numDevicesInSubmissions(
+    ...     bus=HWBus.IDE, vendor_id='SEAGATE',
+    ...     product_id='ST3250820NS     '))
     2
 
 Note that we did _not_ add a HWSubmissionDevice entry for the device
@@ -1892,9 +1894,9 @@
 disks driven by the sd driver, we'll get 1 as without the recently
 added device.
 
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='sd')
+    ...     driver_name='sd'))
     1
 
 Let's now create another HWDB submission, and let's add
@@ -1923,46 +1925,47 @@
 The number of all ST3250820NS disks and of those disks driven by
 the sd driver has now increased by 1.
 
-    >>> print submission_device_set.numDevicesInSubmissions(
-    ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ')
+    >>> print(submission_device_set.numDevicesInSubmissions(
+    ...     bus=HWBus.IDE, vendor_id='SEAGATE',
+    ...     product_id='ST3250820NS     '))
     3
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='sd')
+    ...     driver_name='sd'))
     2
 
 We can optionally specify a driver's package name too.
 
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='sd', package_name='linux-image-2.6.24-19-generic')
+    ...     driver_name='sd', package_name='linux-image-2.6.24-19-generic'))
     1
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='sd', package_name='nonsense')
+    ...     driver_name='sd', package_name='nonsense'))
     0
 
 And we can query for devices having any driver from a given package too.
 
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     package_name='linux-image-2.6.24-19-generic')
+    ...     package_name='linux-image-2.6.24-19-generic'))
     1
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     package_name='nonsense')
+    ...     package_name='nonsense'))
     0
 
 We can also get the number of all devices controlled by a given driver.
 
-    >>> print submission_device_set.numDevicesInSubmissions(
-    ...     driver_name='sd')
+    >>> print(submission_device_set.numDevicesInSubmissions(
+    ...     driver_name='sd'))
     6
 
 We can limit this count to a given package.
 
-    >>> print submission_device_set.numDevicesInSubmissions(
-    ...     driver_name='sd', package_name='linux-image-2.6.24-19-generic')
+    >>> print(submission_device_set.numDevicesInSubmissions(
+    ...     driver_name='sd', package_name='linux-image-2.6.24-19-generic'))
     5
 
 While the parameters for a device or a driver are optional, specifying
@@ -1979,62 +1982,62 @@
 distribution.
 
     >>> switch_dbuser('launchpad')
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu)
+    ...     distro_target=ubuntu))
     2
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=debian)
+    ...     distro_target=debian))
     0
 
 Similary, we can limit the count to devices mentioned in submissions
 made for a given distroseries.
 
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu['hoary'])
+    ...     distro_target=ubuntu['hoary']))
     2
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu['warty'])
+    ...     distro_target=ubuntu['warty']))
     0
 
 And we can also search for devices mentioned in submissions made on a
 given processor architecture.
 
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu['hoary']['i386'])
+    ...     distro_target=ubuntu['hoary']['i386']))
     2
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu['hoary']['hppa'])
+    ...     distro_target=ubuntu['hoary']['hppa']))
     0
 
 We can also query the number of devices controlled by a given driver
 for a distrotarget.
 
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='sd', distro_target=ubuntu['hoary']['i386'])
+    ...     driver_name='sd', distro_target=ubuntu['hoary']['i386']))
     1
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='nonsense', distro_target=ubuntu['hoary']['i386'])
+    ...     driver_name='nonsense', distro_target=ubuntu['hoary']['i386']))
     0
 
 And we can additionally specify a package name.
 
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     driver_name='sd', package_name='linux-image-2.6.24-19-generic',
-    ...     distro_target=ubuntu['hoary']['i386'])
+    ...     distro_target=ubuntu['hoary']['i386']))
     1
-    >>> print submission_device_set.numDevicesInSubmissions(
+    >>> print(submission_device_set.numDevicesInSubmissions(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     driver_name='sd', package_name='nonsense',
-    ...     distro_target=ubuntu['hoary']['i386'])
+    ...     distro_target=ubuntu['hoary']['i386']))
     0
 
 HWSubmissionSet.numSubmissionsWithDevice() returns all submissions
@@ -2050,106 +2053,107 @@
     >>> submission.status = HWSubmissionProcessingStatus.PROCESSED
 
     >>> submission_set = getUtility(IHWSubmissionSet)
-    >>> print submission_set.numSubmissionsWithDevice(
-    ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ')
+    >>> print(submission_set.numSubmissionsWithDevice(
+    ...     bus=HWBus.IDE, vendor_id='SEAGATE',
+    ...     product_id='ST3250820NS     '))
     (2L, 3L)
 
 We can limit the results to a given driver...
 
-    >>> print submission_set.numSubmissionsWithDevice(
+    >>> print(submission_set.numSubmissionsWithDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='sd')
+    ...     driver_name='sd'))
     (2L, 3L)
-    >>> print submission_set.numSubmissionsWithDevice(
+    >>> print(submission_set.numSubmissionsWithDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='usb')
+    ...     driver_name='usb'))
     (0L, 3L)
 
 ...or we can ask for all submissions containing any device controlled
 by a given driver.
 
-    >>> print submission_set.numSubmissionsWithDevice(
-    ...     driver_name='sd')
+    >>> print(submission_set.numSubmissionsWithDevice(
+    ...     driver_name='sd'))
     (2L, 3L)
 
 While the parameters for a device or a driver are optional, specifying
 neither of them leads to an error.
 
-    >>> print submission_set.numSubmissionsWithDevice()
+    >>> print(submission_set.numSubmissionsWithDevice())
     Traceback (most recent call last):
     ...
     ParameterError: Specify (bus, vendor_id, product_id) or driver_name.
 
 This count can be limited to a given package.
 
-    >>> print submission_set.numSubmissionsWithDevice(
-    ...     driver_name='sd', package_name='linux-image-2.6.24-19-generic')
+    >>> print(submission_set.numSubmissionsWithDevice(
+    ...     driver_name='sd', package_name='linux-image-2.6.24-19-generic'))
     (1L, 3L)
 
 We can also limit the count to a distibution...
 
-    >>> print submission_set.numSubmissionsWithDevice(
+    >>> print(submission_set.numSubmissionsWithDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu)
+    ...     distro_target=ubuntu))
     (1L, 2L)
-    >>> print submission_set.numSubmissionsWithDevice(
+    >>> print(submission_set.numSubmissionsWithDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=debian)
+    ...     distro_target=debian))
     (0L, 0L)
 
 ...to a distroseries...
 
-    >>> print submission_set.numSubmissionsWithDevice(
+    >>> print(submission_set.numSubmissionsWithDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu['hoary'])
+    ...     distro_target=ubuntu['hoary']))
     (1L, 2L)
-    >>> print submission_set.numSubmissionsWithDevice(
+    >>> print(submission_set.numSubmissionsWithDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu['warty'])
+    ...     distro_target=ubuntu['warty']))
     (0L, 0L)
 
 ...or to a distroarchseries.
 
-    >>> print submission_set.numSubmissionsWithDevice(
+    >>> print(submission_set.numSubmissionsWithDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu['hoary']['i386'])
+    ...     distro_target=ubuntu['hoary']['i386']))
     (1L, 2L)
-    >>> print submission_set.numSubmissionsWithDevice(
+    >>> print(submission_set.numSubmissionsWithDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu['hoary']['hppa'])
+    ...     distro_target=ubuntu['hoary']['hppa']))
     (0L, 0L)
 
 We can specify a distro target as well as a driver or package name.
 
-    >>> print submission_set.numSubmissionsWithDevice(
+    >>> print(submission_set.numSubmissionsWithDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='sd', distro_target=ubuntu['hoary']['i386'])
+    ...     driver_name='sd', distro_target=ubuntu['hoary']['i386']))
     (1L, 2L)
-    >>> print submission_set.numSubmissionsWithDevice(
+    >>> print(submission_set.numSubmissionsWithDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='nosense', distro_target=ubuntu['hoary']['i386'])
+    ...     driver_name='nosense', distro_target=ubuntu['hoary']['i386']))
     (0L, 2L)
 
-    >>> print submission_set.numSubmissionsWithDevice(
+    >>> print(submission_set.numSubmissionsWithDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     package_name='linux-image-2.6.24-19-generic',
-    ...     distro_target=ubuntu['hoary']['i386'])
+    ...     distro_target=ubuntu['hoary']['i386']))
     (1L, 2L)
-    >>> print submission_set.numSubmissionsWithDevice(
+    >>> print(submission_set.numSubmissionsWithDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     package_name='nonsense', distro_target=ubuntu['hoary']['i386'])
+    ...     package_name='nonsense', distro_target=ubuntu['hoary']['i386']))
     (0L, 2L)
 
-    >>> print submission_set.numSubmissionsWithDevice(
+    >>> print(submission_set.numSubmissionsWithDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     driver_name='sd', package_name='linux-image-2.6.24-19-generic',
-    ...     distro_target=ubuntu['hoary']['i386'])
+    ...     distro_target=ubuntu['hoary']['i386']))
     (1L, 2L)
-    >>> print submission_set.numSubmissionsWithDevice(
+    >>> print(submission_set.numSubmissionsWithDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     driver_name='nonsense',
     ...     package_name='linux-image-2.6.24-19-generic',
-    ...     distro_target=ubuntu['hoary']['i386'])
+    ...     distro_target=ubuntu['hoary']['i386']))
     (0L, 2L)
 
 HWSubmission.numDeviceOwners() returns the number of device owners.
@@ -2173,99 +2177,99 @@
 
 We can limit the results to a given driver.
 
-    >>> print submission_set.numOwnersOfDevice(
+    >>> print(submission_set.numOwnersOfDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='sd')
+    ...     driver_name='sd'))
     (2L, 3L)
-    >>> print submission_set.numOwnersOfDevice(
+    >>> print(submission_set.numOwnersOfDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='usb')
+    ...     driver_name='usb'))
     (0L, 3L)
 
 We can also ask for submitters who use a given driver with any device.
 
-    >>> print submission_set.numOwnersOfDevice(
-    ...     driver_name='sd')
+    >>> print(submission_set.numOwnersOfDevice(
+    ...     driver_name='sd'))
     (2L, 3L)
 
 This count can be limited to a given package.
 
-    >>> print submission_set.numOwnersOfDevice(
-    ...     driver_name='sd', package_name='linux-image-2.6.24-19-generic')
+    >>> print(submission_set.numOwnersOfDevice(
+    ...     driver_name='sd', package_name='linux-image-2.6.24-19-generic'))
     (1L, 3L)
 
 While the parameters for a device or a driver are optional, specifying
 neither of them leads to an error.
 
-    >>> print submission_set.numOwnersOfDevice()
+    >>> print(submission_set.numOwnersOfDevice())
     Traceback (most recent call last):
     ...
     ParameterError: Specify (bus, vendor_id, product_id) or driver_name.
 
 We can limit the count to a distibution...
 
-    >>> print submission_set.numOwnersOfDevice(
+    >>> print(submission_set.numOwnersOfDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu)
+    ...     distro_target=ubuntu))
     (1L, 2L)
-    >>> print submission_set.numOwnersOfDevice(
+    >>> print(submission_set.numOwnersOfDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=debian)
+    ...     distro_target=debian))
     (0L, 0L)
 
 ...to a distroseries...
 
-    >>> print submission_set.numOwnersOfDevice(
+    >>> print(submission_set.numOwnersOfDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu['hoary'])
+    ...     distro_target=ubuntu['hoary']))
     (1L, 2L)
-    >>> print submission_set.numOwnersOfDevice(
+    >>> print(submission_set.numOwnersOfDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu['warty'])
+    ...     distro_target=ubuntu['warty']))
     (0L, 0L)
 
 ...or to a distroarchseries.
 
-    >>> print submission_set.numOwnersOfDevice(
+    >>> print(submission_set.numOwnersOfDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu['hoary']['i386'])
+    ...     distro_target=ubuntu['hoary']['i386']))
     (1L, 2L)
-    >>> print submission_set.numOwnersOfDevice(
+    >>> print(submission_set.numOwnersOfDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distro_target=ubuntu['hoary']['hppa'])
+    ...     distro_target=ubuntu['hoary']['hppa']))
     (0L, 0L)
 
 We can specify a distro target as well as a driver or package name.
 
-    >>> print submission_set.numOwnersOfDevice(
+    >>> print(submission_set.numOwnersOfDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='sd', distro_target=ubuntu['hoary']['i386'])
+    ...     driver_name='sd', distro_target=ubuntu['hoary']['i386']))
     (1L, 2L)
-    >>> print submission_set.numOwnersOfDevice(
+    >>> print(submission_set.numOwnersOfDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='nosense', distro_target=ubuntu['hoary']['i386'])
+    ...     driver_name='nosense', distro_target=ubuntu['hoary']['i386']))
     (0L, 2L)
 
-    >>> print submission_set.numOwnersOfDevice(
+    >>> print(submission_set.numOwnersOfDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     package_name='linux-image-2.6.24-19-generic',
-    ...     distro_target=ubuntu['hoary']['i386'])
+    ...     distro_target=ubuntu['hoary']['i386']))
     (1L, 2L)
-    >>> print submission_set.numOwnersOfDevice(
+    >>> print(submission_set.numOwnersOfDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     package_name='nonsense', distro_target=ubuntu['hoary']['i386'])
+    ...     package_name='nonsense', distro_target=ubuntu['hoary']['i386']))
     (0L, 2L)
 
-    >>> print submission_set.numOwnersOfDevice(
+    >>> print(submission_set.numOwnersOfDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     driver_name='sd', package_name='linux-image-2.6.24-19-generic',
-    ...     distro_target=ubuntu['hoary']['i386'])
+    ...     distro_target=ubuntu['hoary']['i386']))
     (1L, 2L)
-    >>> print submission_set.numOwnersOfDevice(
+    >>> print(submission_set.numOwnersOfDevice(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     driver_name='nonsense',
     ...     package_name='linux-image-2.6.24-19-generic',
-    ...     distro_target=ubuntu['hoary']['i386'])
+    ...     distro_target=ubuntu['hoary']['i386']))
     (0L, 2L)
 
 
@@ -2283,12 +2287,12 @@
     >>> from lp.bugs.interfaces.bug import IBugSet
     >>> bug_set = getUtility(IBugSet)
     >>> bug_one = bug_set.get(1)
-    >>> print bug_one.owner.displayname
+    >>> print(bug_one.owner.displayname)
     Sample Person
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[1]):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Sample Person
 
 If Foo Bar says that they are affected by this bug, they will be listed
@@ -2300,7 +2304,7 @@
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[1], affected_by_bug=True):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Foo Bar
     Sample Person
 
@@ -2311,7 +2315,7 @@
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[1], affected_by_bug=True):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Sample Person
 
 By setting the parameter subscribed_to_bug to True, we can also look
@@ -2322,7 +2326,7 @@
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[1], subscribed_to_bug=True):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Foo Bar
     Sample Person
 
@@ -2330,7 +2334,7 @@
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[1], subscribed_to_bug=True):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Sample Person
 
 We can specify more than one bug ID. If we specify bugs 1 and 3,
@@ -2338,12 +2342,12 @@
 Foo Bar.
 
     >>> bug_three = bug_set.get(3)
-    >>> print bug_three.owner.displayname
+    >>> print(bug_three.owner.displayname)
     Foo Bar
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[1, 3]):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Foo Bar
     Sample Person
 
@@ -2359,25 +2363,25 @@
     ...     BugTaskSearchParams(user=foo_bar, tag=any('pebcak')))
     >>> owners = set(bugtask.bug.owner for bugtask in bugtasks)
     >>> for owner in owners:
-    ...     print owner.displayname
+    ...     print(owner.displayname)
     Sample Person
     >>> bugtasks = bugtask_set.search(
     ...     BugTaskSearchParams(user=foo_bar, tag=any('crash')))
     >>> owners = set(bugtask.bug.owner for bugtask in bugtasks)
     >>> for owner in owners:
-    ...     print owner.displayname
+    ...     print(owner.displayname)
     Foo Bar
 
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_tags=['pebcak']):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Sample Person
 
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_tags=['pebcak', 'crash']):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Foo Bar
     Sample Person
 
@@ -2392,13 +2396,13 @@
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     driver_name='sd', bug_tags=['pebcak', 'crash']):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Foo Bar
     Sample Person
 
-    >>> print submission_set.deviceDriverOwnersAffectedByBugs(
+    >>> print(submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='nonsense', bug_tags=['pebcak', 'crash']).count()
+    ...     driver_name='nonsense', bug_tags=['pebcak', 'crash']).count())
     0
 
 ...or a given package name by providing a package_name parameter.
@@ -2407,12 +2411,12 @@
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     package_name='linux-image-2.6.24-19-generic',
     ...     bug_tags=['pebcak', 'crash']):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Sample Person
 
-    >>> print submission_set.deviceDriverOwnersAffectedByBugs(
+    >>> print(submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     package_name='nonsense', bug_tags=['pebcak', 'crash']).count()
+    ...     package_name='nonsense', bug_tags=['pebcak', 'crash']).count())
     0
 
 Owners of private submissions are only included if the optional parameter
@@ -2430,14 +2434,14 @@
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[1], subscribed_to_bug=True, user=no_priv):
-    ...     print person.displayname
+    ...     print(person.displayname)
     No Privileges Person
     Sample Person
 
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[1], subscribed_to_bug=True, user=foo_bar):
-    ...     print person.displayname
+    ...     print(person.displayname)
     No Privileges Person
     Sample Person
 
@@ -2446,13 +2450,13 @@
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[1], subscribed_to_bug=True, user=sample_person):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Sample Person
 
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[1], subscribed_to_bug=True):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Sample Person
 
 
@@ -2464,7 +2468,7 @@
 
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     driver_name='sd', bug_ids=[1]):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Sample Person
 
 If Foo Bar says that they are affected by this bug, they will be listed
@@ -2473,7 +2477,7 @@
     >>> bug_one.markUserAffected(foo_bar)
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     driver_name='sd', bug_ids=[1], affected_by_bug=True):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Foo Bar
     Sample Person
 
@@ -2484,7 +2488,7 @@
     <lp.bugs.model.bugsubscription.BugSubscription ...>
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     driver_name='sd', bug_ids=[1], subscribed_to_bug=True):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Foo Bar
     Sample Person
 
@@ -2495,7 +2499,7 @@
     >>> bug_one.unsubscribe(foo_bar, unsubscribed_by=foo_bar)
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     driver_name='sd', bug_ids=[1, 3]):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Foo Bar
     Sample Person
 
@@ -2504,12 +2508,12 @@
 
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     driver_name='sd', bug_tags=['pebcak']):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Sample Person
 
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     driver_name='sd', bug_tags=['pebcak', 'crash']):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Foo Bar
     Sample Person
 
@@ -2521,14 +2525,14 @@
 
     >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
     ...     driver_name='sd', bug_ids=[2], bug_tags=['pebcak']):
-    ...     print person.displayname
+    ...     print(person.displayname)
     Sample Person
 
 Also, confirm that nothing is returned where there is no matching
 tag on a given bug id.
 
-    >>> print len(list(submission_set.deviceDriverOwnersAffectedByBugs(
-    ...     driver_name='sd', bug_ids=[3], bug_tags=['pebcak'])))
+    >>> print(len(list(submission_set.deviceDriverOwnersAffectedByBugs(
+    ...     driver_name='sd', bug_ids=[3], bug_tags=['pebcak']))))
     0
 
 If neither a device nor a driver name is specified,
@@ -2557,7 +2561,7 @@
 
     >>> for entry in submission_set.hwInfoByBugRelatedUsers(
     ...     bug_ids=[1]):
-    ...     print entry
+    ...     print(entry)
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
     (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
@@ -2574,7 +2578,7 @@
 
     >>> for entry in submission_set.hwInfoByBugRelatedUsers(
     ...     bug_ids=[1, 3]):
-    ...     print entry
+    ...     print(entry)
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
     (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
@@ -2592,7 +2596,7 @@
 
     >>> for entry in submission_set.hwInfoByBugRelatedUsers(
     ...     bug_tags=['pebcak']):
-    ...     print entry
+    ...     print(entry)
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
     (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
@@ -2607,7 +2611,7 @@
 
     >>> for entry in submission_set.hwInfoByBugRelatedUsers(
     ...     bug_tags=['pebcak', 'crash']):
-    ...     print entry
+    ...     print(entry)
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
     (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
@@ -2625,7 +2629,7 @@
 
     >>> for entry in submission_set.hwInfoByBugRelatedUsers(
     ...     bug_ids=[2], bug_tags=['pebcak']):
-    ...     print entry
+    ...     print(entry)
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
     (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
@@ -2641,8 +2645,8 @@
 Also, confirm that nothing is returned where there is no matching
 tag on a given bug id.
 
-    >>> print len(submission_set.hwInfoByBugRelatedUsers(
-    ...     bug_ids=[3], bug_tags=['pebcak']))
+    >>> print(len(submission_set.hwInfoByBugRelatedUsers(
+    ...     bug_ids=[3], bug_tags=['pebcak'])))
     0
 
 This method can also be used to list devices where the
@@ -2652,7 +2656,7 @@
 
     >>> for entry in submission_set.hwInfoByBugRelatedUsers(
     ...     bug_ids=[1], affected_by_bug=True):
-    ...     print entry
+    ...     print(entry)
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
     (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
@@ -2675,7 +2679,7 @@
 
     >>> for entry in submission_set.hwInfoByBugRelatedUsers(
     ...     bug_ids=[1], subscribed_to_bug=True):
-    ...     print entry
+    ...     print(entry)
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
     (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
@@ -2699,7 +2703,7 @@
 
     >>> for entry in submission_set.hwInfoByBugRelatedUsers(
     ...     bug_ids=[1], subscribed_to_bug=True, user=no_priv):
-    ...     print entry
+    ...     print(entry)
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
     (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
@@ -2717,7 +2721,7 @@
 
     >>> for entry in submission_set.hwInfoByBugRelatedUsers(
     ...     bug_ids=[1], subscribed_to_bug=True, user=foo_bar):
-    ...     print entry
+    ...     print(entry)
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
     (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
@@ -2736,7 +2740,7 @@
 
     >>> for entry in submission_set.hwInfoByBugRelatedUsers(
     ...     bug_ids=[1], subscribed_to_bug=True, user=sample_person):
-    ...     print entry
+    ...     print(entry)
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
     (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
     (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')

=== modified file 'lib/lp/hardwaredb/doc/hwdb-submission.txt'
--- lib/lp/hardwaredb/doc/hwdb-submission.txt	2012-11-22 00:15:23 +0000
+++ lib/lp/hardwaredb/doc/hwdb-submission.txt	2019-04-16 17:22:40 +0000
@@ -21,10 +21,10 @@
   * submission_data: An XML file containing the collected data. This file is
     simply stored as a Librarian file, and parsed later by a cron job.
 
+    >>> import io
     >>> from zope.component import getUtility
-    >>> from StringIO import StringIO
     >>> from lp.hardwaredb.interfaces.hwdb import IHWDBApplication
-    >>> data = StringIO('some data.')
+    >>> data = io.BytesIO(b'some data.')
     >>> data.filename = 'hardware-info'
     >>> form={'field.date_created':    u'2007-08-01',
     ...       'field.format':          u'VERSION_1',
@@ -80,7 +80,7 @@
 
     >>> submit_view = create_initialized_view(app, name='+submit', form=form)
     >>> for error in submit_view.errors:
-    ...     print error.doc()
+    ...     print(error.doc())
     Submission key already exists.
 
 If the field distribution contains a name which is not known in the
@@ -92,7 +92,7 @@
     >>> submit_view = create_initialized_view(
     ...     app, name='+submit', form=invalid_form)
     >>> submission = submission_set.getBySubmissionKey(u'unique-id-2')
-    >>> print submission.distroarchseries
+    >>> print(submission.distroarchseries)
     None
 
 If distribution is known, but distroseries or architecture are unknown
@@ -103,7 +103,7 @@
     >>> invalid_form['field.distroseries'] = 'no release'
     >>> submit_view = create_initialized_view(
     ...     app, name='+submit', form=invalid_form)
-    >>> print submission_set.getBySubmissionKey(u'unique-id-3')
+    >>> print(submission_set.getBySubmissionKey(u'unique-id-3'))
     None
 
     >>> form['field.submission_key'] = u'unique-id-4'
@@ -111,7 +111,7 @@
     >>> invalid_form['field.architecture'] = 'no architecture'
     >>> submit_view = create_initialized_view(
     ...     app, name='+submit', form=invalid_form)
-    >>> print submission_set.getBySubmissionKey(u'unique-id-4')
+    >>> print(submission_set.getBySubmissionKey(u'unique-id-4'))
     None
 
 The `date_created` field must contain a valid date.
@@ -122,7 +122,7 @@
     >>> submit_view = create_initialized_view(
     ...     app, name='+submit', form=invalid_form)
     >>> for error in submit_view.errors:
-    ...     print error.doc()
+    ...     print(error.doc())
     Invalid datetime data
 
 The `format` field must contain a value that matches the DBEnumeratedType
@@ -133,7 +133,7 @@
     >>> submit_view = create_initialized_view(
     ...     app, name='+submit', form=invalid_form)
     >>> for error in submit_view.errors:
-    ...     print error.doc()
+    ...     print(error.doc())
     Invalid value
 
 The field `submission_key` may contain only ASCII data.
@@ -143,7 +143,7 @@
     >>> submit_view = create_initialized_view(
     ...     app, name='+submit', form=invalid_form)
     >>> for error in submit_view.errors:
-    ...     print error.doc()
+    ...     print(error.doc())
     Invalid textual data
 
 The field `emailaddress` must contain a formally valid email address.
@@ -153,7 +153,7 @@
     >>> submit_view = create_initialized_view(
     ...     app, name='+submit', form=invalid_form)
     >>> for error in submit_view.errors:
-    ...     print error.doc()
+    ...     print(error.doc())
     Invalid email address
 
 All fields are required.  With normal form processing, it's impossible not to
@@ -171,10 +171,11 @@
     ...     invalid_form[field] = u''
     ...     submit_view = create_initialized_view(
     ...         app, name='+submit', form=invalid_form)
-    ...     print field
+    ...     print(field)
     ...     for error in submit_view.errors:
     ...         field_name = error.field_name
-    ...         print '   ', field_name, submit_view.getFieldError(field_name)
+    ...         print('   ', field_name,
+    ...               submit_view.getFieldError(field_name))
     field.date_created
         date_created Required input is missing.
     field.submission_key
@@ -203,7 +204,8 @@
     ...     config.root,
     ...     'lib/lp/hardwaredb/scripts/tests/'
     ...     'simple_valid_hwdb_submission.xml')
-    >>> valid_sample_data = StringIO(open(valid_sample_data_path).read())
+    >>> valid_sample_data = io.BytesIO(
+    ...     open(valid_sample_data_path, 'rb').read())
     >>> valid_sample_data.filename = 'simple_valid_hwdb_submission.xml'
     >>> team_form['field.submission_data'] = valid_sample_data
     >>> submit_view = create_initialized_view(
@@ -233,18 +235,18 @@
     >>> new_submissions = submission_set.getByStatus(
     ...     HWSubmissionProcessingStatus.SUBMITTED)
     >>> for submission in new_submissions:
-    ...     print submission.submission_key, submission.status.title
+    ...     print(submission.submission_key, submission.status.title)
     test_submission_id_1 Submitted
     unique-id-1 Submitted
     unique-id-68 Submitted
     >>> processed_submissions = submission_set.getByStatus(
     ...     HWSubmissionProcessingStatus.PROCESSED)
     >>> for submission in processed_submissions:
-    ...     print submission.submission_key, submission.status.title
+    ...     print(submission.submission_key, submission.status.title)
     sample-submission Processed
     >>> invalid_submissions = submission_set.getByStatus(
     ...     HWSubmissionProcessingStatus.INVALID)
-    >>> print invalid_submissions.count()
+    >>> print(invalid_submissions.count())
     0
 
 The script process-hwdb-submissions.py takes the optional parameter
@@ -269,14 +271,14 @@
     ...     'cronscripts/process-hwdb-submissions.py', ['-m1'])
     >>> returnvalue
     0
-    >>> print err
+    >>> print(err)
     INFO    Creating lockfile: /var/lock/launchpad-hwdbsubmissions.lock
     ERROR   Parsing submission test_submission_id_1: syntax error:
     line 1, column 0
     INFO    OOPS-...
     INFO    Processed 0 valid and 1 invalid HWDB submissions
     <BLANKLINE>
-    >>> print out
+    >>> print(out)
     <BLANKLINE>
 
 Submission "test_submission_id_1" has now the state INVALID; the other
@@ -285,18 +287,18 @@
     >>> new_submissions = submission_set.getByStatus(
     ...     HWSubmissionProcessingStatus.SUBMITTED)
     >>> for submission in new_submissions:
-    ...     print submission.submission_key, submission.status.title
+    ...     print(submission.submission_key, submission.status.title)
     unique-id-1 Submitted
     unique-id-68 Submitted
     >>> processed_submissions = submission_set.getByStatus(
     ...     HWSubmissionProcessingStatus.PROCESSED)
     >>> for submission in processed_submissions:
-    ...     print submission.submission_key, submission.status.title
+    ...     print(submission.submission_key, submission.status.title)
     sample-submission Processed
     >>> invalid_submissions = submission_set.getByStatus(
     ...     HWSubmissionProcessingStatus.INVALID)
     >>> for submission in invalid_submissions:
-    ...     print submission.submission_key, submission.status.title
+    ...     print(submission.submission_key, submission.status.title)
     test_submission_id_1 Invalid submission
 
 From the remaining two not yet processed submissions, one has invalid
@@ -306,13 +308,13 @@
     ...     'cronscripts/process-hwdb-submissions.py')
     >>> returnvalue
     0
-    >>> print err
+    >>> print(err)
     INFO    Creating lockfile: /var/lock/launchpad-hwdbsubmissions.lock
     ERROR   Parsing submission unique-id-1: syntax error: line 1, column 0
     INFO    OOPS-...
     INFO    Processed 1 valid and 1 invalid HWDB submissions
     <BLANKLINE>
-    >>> print out
+    >>> print(out)
     <BLANKLINE>
 
 Now we have one valid, two invalid and no unprocessed submissions.
@@ -322,19 +324,19 @@
     >>> transaction.commit()
     >>> new_submissions = submission_set.getByStatus(
     ...     HWSubmissionProcessingStatus.SUBMITTED)
-    >>> print new_submissions.count()
+    >>> print(new_submissions.count())
     0
     >>> processed_submissions = submission_set.getByStatus(
     ...     HWSubmissionProcessingStatus.PROCESSED)
     >>> for submission in processed_submissions:
-    ...     print submission.submission_key, submission.status.title
+    ...     print(submission.submission_key, submission.status.title)
     sample-submission Processed
     unique-id-68 Processed
 
     >>> invalid_submissions = submission_set.getByStatus(
     ...     HWSubmissionProcessingStatus.INVALID)
     >>> for submission in invalid_submissions:
-    ...     print submission.submission_key, submission.status.title
+    ...     print(submission.submission_key, submission.status.title)
     test_submission_id_1 Invalid submission
     unique-id-1 Invalid submission
 
@@ -350,14 +352,14 @@
 Now we have 80 new submissions and three submissions that were processed
 in previous tests.
 
-    >>> print submission_set.getByStatus(
-    ...     HWSubmissionProcessingStatus.SUBMITTED).count()
+    >>> print(submission_set.getByStatus(
+    ...     HWSubmissionProcessingStatus.SUBMITTED).count())
     80
-    >>> print submission_set.getByStatus(
-    ...     HWSubmissionProcessingStatus.PROCESSED).count()
+    >>> print(submission_set.getByStatus(
+    ...     HWSubmissionProcessingStatus.PROCESSED).count())
     2
-    >>> print submission_set.getByStatus(
-    ...     HWSubmissionProcessingStatus.INVALID).count()
+    >>> print(submission_set.getByStatus(
+    ...     HWSubmissionProcessingStatus.INVALID).count())
     2
     >>> transaction.commit()
 
@@ -368,19 +370,19 @@
     ...     'cronscripts/process-hwdb-submissions.py', ['-m60'])
     >>> returnvalue
     0
-    >>> print err
+    >>> print(err)
     INFO    Creating lockfile: /var/lock/launchpad-hwdbsubmissions.lock
     INFO    Processed 60 valid and 0 invalid HWDB submissions
-    >>> print out
+    >>> print(out)
     <BLANKLINE>
-    >>> print submission_set.getByStatus(
-    ...     HWSubmissionProcessingStatus.SUBMITTED).count()
+    >>> print(submission_set.getByStatus(
+    ...     HWSubmissionProcessingStatus.SUBMITTED).count())
     20
-    >>> print submission_set.getByStatus(
-    ...     HWSubmissionProcessingStatus.PROCESSED).count()
+    >>> print(submission_set.getByStatus(
+    ...     HWSubmissionProcessingStatus.PROCESSED).count())
     62
-    >>> print submission_set.getByStatus(
-    ...     HWSubmissionProcessingStatus.INVALID).count()
+    >>> print(submission_set.getByStatus(
+    ...     HWSubmissionProcessingStatus.INVALID).count())
     2
 
 Let's add more subscription so that we have more than max_chunk_size
@@ -391,31 +393,31 @@
     ...     submit_view = create_initialized_view(
     ...         app, name='+submit', form=form)
 
-    >>> print submission_set.getByStatus(
-    ...     HWSubmissionProcessingStatus.SUBMITTED).count()
+    >>> print(submission_set.getByStatus(
+    ...     HWSubmissionProcessingStatus.SUBMITTED).count())
     100
-    >>> print submission_set.getByStatus(
-    ...     HWSubmissionProcessingStatus.PROCESSED).count()
+    >>> print(submission_set.getByStatus(
+    ...     HWSubmissionProcessingStatus.PROCESSED).count())
     62
-    >>> print submission_set.getByStatus(
-    ...     HWSubmissionProcessingStatus.INVALID).count()
+    >>> print(submission_set.getByStatus(
+    ...     HWSubmissionProcessingStatus.INVALID).count())
     2
     >>> transaction.commit()
     >>> returnvalue, out, err = run_script(
     ...     'cronscripts/process-hwdb-submissions.py')
     >>> returnvalue
     0
-    >>> print err
+    >>> print(err)
     INFO    Creating lockfile: /var/lock/launchpad-hwdbsubmissions.lock
     INFO    Processed 100 valid and 0 invalid HWDB submissions
-    >>> print out
+    >>> print(out)
     <BLANKLINE>
-    >>> print submission_set.getByStatus(
-    ...     HWSubmissionProcessingStatus.SUBMITTED).count()
+    >>> print(submission_set.getByStatus(
+    ...     HWSubmissionProcessingStatus.SUBMITTED).count())
     0
-    >>> print submission_set.getByStatus(
-    ...     HWSubmissionProcessingStatus.PROCESSED).count()
+    >>> print(submission_set.getByStatus(
+    ...     HWSubmissionProcessingStatus.PROCESSED).count())
     162
-    >>> print submission_set.getByStatus(
-    ...     HWSubmissionProcessingStatus.INVALID).count()
+    >>> print(submission_set.getByStatus(
+    ...     HWSubmissionProcessingStatus.INVALID).count())
     2

=== modified file 'lib/lp/hardwaredb/doc/hwdb.txt'
--- lib/lp/hardwaredb/doc/hwdb.txt	2016-02-05 16:51:12 +0000
+++ lib/lp/hardwaredb/doc/hwdb.txt	2019-04-16 17:22:40 +0000
@@ -14,7 +14,7 @@
 
   * reference to the librarian file.
 
-    >>> print sample_submission.raw_submission
+    >>> print(sample_submission.raw_submission)
      <...LibraryFileAlias instance at ...>
 
   * date_created: Date and time of the submission (generated by the client).
@@ -24,52 +24,52 @@
     * Some machines have a broken CMOS battery and the user does not set
       date and time after every boot.
 
-    >>> print sample_submission.date_created
+    >>> print(sample_submission.date_created)
     2008-09-26 17:19:18+00:00
 
   * date_submitted: Date and time of the submission (generated by the server).
 
-    >>> print sample_submission.date_submitted
+    >>> print(sample_submission.date_submitted)
     2008-09-30 08:19:00.222131+00:00
 
   * format: The format version of the submitted data, as given by the HWDB
     client. See HWSubmissionFormat for valid values.
 
-    >>> print sample_submission.format.name
+    >>> print(sample_submission.format.name)
     VERSION_1
 
   * status: The status of the submission. See HWSubmissionProcessingStatus for
     valid values.
 
-    >>> print sample_submission.status.name
+    >>> print(sample_submission.status.name)
     PROCESSED
 
   * private: If True, the submitter allows public access to the data. If
     false, the data may be used only for statistical purposes.
 
-    >>> print sample_submission.private
+    >>> print(sample_submission.private)
     False
 
   * contactable: If True, the submitter agrees to be contacted by upstream
     developers and package maintainers for tests etc.
 
-    >>> print sample_submission.contactable
+    >>> print(sample_submission.contactable)
     False
 
   * submission_key: A unique submission ID.
 
-    >>> print sample_submission.submission_key
+    >>> print(sample_submission.submission_key)
     sample-submission
 
   * raw_emailaddress: The email address of the submitter.
 
-    >>> print sample_submission.raw_emailaddress
+    >>> print(sample_submission.raw_emailaddress)
     test@xxxxxxxxxxxxx
 
   * owner: A reference to the Person table. This value is null, if the email
     address does not belong (yet) to an entry in Person table.
 
-    >>> print sample_submission.owner.displayname
+    >>> print(sample_submission.owner.displayname)
     Sample Person
 
   * distroarchseries: A reference to the distroarchseries of the submission.
@@ -77,20 +77,21 @@
     distroseries and architecture do not match an existing entry in the
     Distroarchrelease table.
 
-    >>> print sample_submission.distroarchseries.architecturetag
+    >>> print(sample_submission.distroarchseries.architecturetag)
     i386
 
-    >>> print sample_submission.distroarchseries.distroseries.name
+    >>> print(sample_submission.distroarchseries.distroseries.name)
     hoary
 
-    >>> print sample_submission.distroarchseries.distroseries.distribution.name
+    >>> print(
+    ...     sample_submission.distroarchseries.distroseries.distribution.name)
     ubuntu
 
   * system_fingerprint: A reference to an entry of the HWSystemFingerprint
     table. This table stores the system name as returned by HAL
     (system.vendor, system.product).
 
-    >>> print sample_submission.system_fingerprint.fingerprint
+    >>> print(sample_submission.system_fingerprint.fingerprint)
     MSI MS-7369
 
   * devices: The set set of HWSubmissionDevice records which belong to
@@ -101,7 +102,7 @@
 
     >>> login('foo.bar@xxxxxxxxxxxxx')
     >>> for submission_device in sample_submission.devices[:2]:
-    ...     print submission_device.device.name
+    ...     print(submission_device.device.name)
     MCP65 USB Controller
     MCP65 SATA Controller
     >>> login(ANONYMOUS)
@@ -146,7 +147,7 @@
 
 ...or None, if no entry exists.
 
-    >>> print hw_fingerprint_set.getByName(u'DEC PDP11')
+    >>> print(hw_fingerprint_set.getByName(u'DEC PDP11'))
     None
 
 IHWSubmissionSet.createSubmission creates a new entry in the
@@ -207,7 +208,7 @@
     >>> from lp.registry.interfaces.person import IPersonSet
     >>> beeblebrox = getUtility(IPersonSet).getByEmail(
     ...     'beeblebrox@xxxxxxxxxxx')
-    >>> print beeblebrox
+    >>> print(beeblebrox)
     None
 
     >>> submission = hw_submission_set.createSubmission(
@@ -222,7 +223,7 @@
     ...     filename=u'hwinfo.txt',
     ...     filesize=len(submission_data),
     ...     system_fingerprint=u'Acer 6789')
-    >>> print submission.owner
+    >>> print(submission.owner)
     None
 
 The submitted data can be retrieved via IHWSubmissionSet.getBySubmissionKey.
@@ -247,7 +248,7 @@
     ...     filename=u'hwinfo.txt',
     ...     filesize=len(submission_data),
     ...     system_fingerprint=u'Dell Inspiron 1234')
-    >>> print hw_submission_set.getBySubmissionKey(u'private-submission')
+    >>> print(hw_submission_set.getBySubmissionKey(u'private-submission'))
     None
     >>> sample_person = getUtility(IPersonSet).getByEmail('test@xxxxxxxxxxxxx')
     >>> sample_person.displayname
@@ -286,15 +287,15 @@
     >>> no_priv = getUtility(IPersonSet).getByEmail('no-priv@xxxxxxxxxxxxx')
     >>> no_priv.displayname
     u'No Privileges Person'
-    >>> print hw_submission_set.getBySubmissionKey(u'private-submission',
-    ...     no_priv)
+    >>> print(hw_submission_set.getBySubmissionKey(u'private-submission',
+    ...     no_priv))
     None
 
     >>> login(ANONYMOUS)
 
 If no submission exists for a given ID, None is returned.
 
-    >>> print hw_submission_set.getBySubmissionKey(u'unknown-ID')
+    >>> print(hw_submission_set.getBySubmissionKey(u'unknown-ID'))
     None
 
 IHWSubmissionSet.getByFingerprintName returns all submissions for a
@@ -381,7 +382,7 @@
     >>> from lp.services.log.logger import DevNullLogger
     >>> HWSubmissionEmailLinker(log=DevNullLogger()).run()
     >>> submission = hw_submission_set.getBySubmissionKey(u'unique-id-2')
-    >>> print submission.owner.displayname
+    >>> print(submission.owner.displayname)
     Beeblebrox
 
 If somebody has a Launchpad account, but submits HWDB test data using
@@ -401,7 +402,7 @@
     ...     filesize=len(submission_data),
     ...     system_fingerprint=u'Acer 6789')
     >>> Store.of(submission).flush()
-    >>> print submission.owner
+    >>> print(submission.owner)
     None
 
 When they add this email address to their list of addresses in Launchpad,
@@ -415,7 +416,7 @@
     >>> transaction.commit()
     >>> HWSubmissionEmailLinker(log=DevNullLogger()).run()
     >>> submission = hw_submission_set.getBySubmissionKey(u'unique-id-2')
-    >>> print submission.owner.displayname
+    >>> print(submission.owner.displayname)
     Beeblebrox
 
 === Submission Records without an email address ===
@@ -436,9 +437,9 @@
     ...     filesize=len(submission_data),
     ...     system_fingerprint=u'Dell Inspiron 1234')
     >>> Store.of(submission_no_owner).flush()
-    >>> print submission_no_owner.raw_emailaddress
+    >>> print(submission_no_owner.raw_emailaddress)
     None
-    >>> print submission_no_owner.owner
+    >>> print(submission_no_owner.owner)
     None
 
 == Retrieving Submissions by Status ==
@@ -451,12 +452,12 @@
     ...     HWSubmissionProcessingStatus)
     >>> def print_submissions(submissions):
     ...     for submission in submissions:
-    ...         print submission.submission_key, submission.private,
+    ...         print(submission.submission_key, submission.private, end=' ')
     ...         if submission.owner is not None:
-    ...             print submission.owner.displayname,
+    ...             print(submission.owner.displayname, end=' ')
     ...         else:
-    ...             print '(no owner)',
-    ...         print submission.status.name
+    ...             print('(no owner)', end=' ')
+    ...         print(submission.status.name)
     >>> new_submissions = hw_submission_set.getByStatus(
     ...     HWSubmissionProcessingStatus.SUBMITTED)
     >>> print_submissions(new_submissions)
@@ -546,7 +547,7 @@
     >>> submission_bug = submission_bug_set.create(
     ...     submission_no_owner, bug_one)
     >>> transaction.commit()
-    >>> print submission_bug.submission.submission_key
+    >>> print(submission_bug.submission.submission_key)
     unique-id-5
     >>> submission_bug.bug.id
     1
@@ -563,7 +564,7 @@
 a given bug.
 
     >>> for submission in submission_bug_set.submissionsForBug(bug_one):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     unique-id-5
 
 Private submissions are only returned if the current user is an admin
@@ -575,13 +576,13 @@
     <HWSubmissionBug at...
     >>> for submission in submission_bug_set.submissionsForBug(
     ...     bug_one, user=sample_person):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     private-submission
     unique-id-5
 
     >>> for submission in submission_bug_set.submissionsForBug(
     ...     bug_one, user=foobar):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     private-submission
     unique-id-5
 
@@ -589,14 +590,14 @@
 
     >>> for submission in submission_bug_set.submissionsForBug(
     ...     bug_one, user=no_priv):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     unique-id-5
 
 ...as well as anonymous users.
 
     >>> for submission in submission_bug_set.submissionsForBug(
     ...     bug_one):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     unique-id-5
 
 Existing links can also be removed.
@@ -607,7 +608,7 @@
 
     >>> for submission in submission_bug_set.submissionsForBug(
     ...     bug_one, user=foobar):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     private-submission
 
 
@@ -621,7 +622,7 @@
 submissions are returned.
 
     >>> for submission in hw_submission_set.search():
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     test_submission_id_1
     sample-submission
     unique-id-1
@@ -633,7 +634,7 @@
 are returned too.
 
     >>> for submission in hw_submission_set.search(user=sample_person):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     test_submission_id_1
     sample-submission
     unique-id-1
@@ -645,7 +646,7 @@
 Admins have access to all submissions.
 
     >>> for submission in hw_submission_set.search(user=foobar):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     test_submission_id_1
     sample-submission
     unique-id-1
@@ -662,21 +663,21 @@
     >>> distribution_set = getUtility(IDistributionSet)
     >>> ubuntu = distribution_set.getByName('ubuntu')
     >>> for submission in hw_submission_set.search(distribution=ubuntu):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
     >>> debian = distribution_set.getByName('debian')
-    >>> print hw_submission_set.search(distribution=debian).count()
+    >>> print(hw_submission_set.search(distribution=debian).count())
     0
 
 If an architecture is specified, only those submissions that were made
 for that architecture are returned.
 
     >>> for submission in hw_submission_set.search(architecture='i386'):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
-    >>> print hw_submission_set.search(architecture='amd64').count()
+    >>> print(hw_submission_set.search(architecture='amd64').count())
     0
 
 
@@ -688,7 +689,7 @@
     >>> msi_mainboard = device_set.getByDeviceID(
     ...     HWBus.SYSTEM, 'MSI', 'MS-7369')
     >>> for submission in hw_submission_set.search(device=msi_mainboard):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
 If a driver is specified, only those submissions for that driver
@@ -699,7 +700,7 @@
     >>> ehci_driver = driver_set.getByPackageAndName(
     ...     'linux-image-2.6.24-19-generic', 'ehci_hcd')
     >>> for submission in hw_submission_set.search(driver=ehci_driver):
-    ...     print submission.submission_key
+    ...     print(submission.submission_key)
     sample-submission
 
 If a distroseries is specified, only submissions for that distroseries
@@ -712,7 +713,7 @@
     >>> warty_arch_series = factory.makeDistroArchSeries(distroseries=warty)
     >>> submission = factory.makeHWSubmission(distroarchseries=warty_arch_series)
     >>> for submission in hw_submission_set.search(distroseries=warty):
-    ...     print submission.distroarchseries.distroseries.name
+    ...     print(submission.distroarchseries.distroseries.name)
     warty
 
 It is also possible to search for a distroseries and architecture.
@@ -724,9 +725,9 @@
     ...     processor=amd64)
     >>> submission = factory.makeHWSubmission(distroarchseries=warty_amd64)
     >>> for submission in hw_submission_set.search(distroseries=warty, architecture='amd64'):
-    ...     print '%s %s ' % (
+    ...     print('%s %s ' % (
     ...         submission.distroarchseries.distroseries.name,
-    ...         submission.distroarchseries.architecturetag)
+    ...         submission.distroarchseries.architecturetag))
     warty amd64
 
 And we can also search for submissions from a particular user.

=== modified file 'lib/lp/hardwaredb/scripts/hwdbsubmissions.py'
--- lib/lp/hardwaredb/scripts/hwdbsubmissions.py	2018-02-02 10:06:24 +0000
+++ lib/lp/hardwaredb/scripts/hwdbsubmissions.py	2019-04-16 17:22:40 +0000
@@ -16,11 +16,11 @@
           ]
 
 import bz2
-from cStringIO import StringIO
 from datetime import (
     datetime,
     timedelta,
     )
+import io
 from logging import getLogger
 import os
 import re
@@ -73,14 +73,15 @@
     """,
     re.VERBOSE)
 
-_broken_comment_nodes_re = re.compile('(<comment>.*?</comment>)', re.DOTALL)
+_broken_comment_nodes_re = re.compile(br'(<comment>.*?</comment>)', re.DOTALL)
 _missing_udev_node_data = re.compile(
-    '<info command="udevadm info --export-db">(.*?)</info>', re.DOTALL)
+    br'<info command="udevadm info --export-db">(.*?)</info>', re.DOTALL)
 _missing_dmi_node_data = re.compile(
-    r'<info command="grep -r \. /sys/class/dmi/id/ 2&gt;/dev/null">(.*?)'
-    '</info>', re.DOTALL)
-_udev_node_exists = re.compile('<hardware>.*?<udev>.*?</hardware>', re.DOTALL)
-_dmi_node_exists = re.compile('<hardware>.*?<dmi>.*?</hardware>', re.DOTALL)
+    br'<info command="grep -r \. /sys/class/dmi/id/ 2&gt;/dev/null">(.*?)'
+    br'</info>', re.DOTALL)
+_udev_node_exists = re.compile(
+    br'<hardware>.*?<udev>.*?</hardware>', re.DOTALL)
+_dmi_node_exists = re.compile(br'<hardware>.*?<dmi>.*?</hardware>', re.DOTALL)
 
 ROOT_UDI = '/org/freedesktop/Hal/devices/computer'
 UDEV_ROOT_PATH = '/devices/LNXSYSTM:00'
@@ -176,7 +177,7 @@
         # A considerable number of reports for Lucid has ESC characters
         # in comment nodes. We don't need the comment nodes at all, so
         # we can simply empty them.
-        submission = _broken_comment_nodes_re.sub('<comment/>', submission)
+        submission = _broken_comment_nodes_re.sub(b'<comment/>', submission)
 
         # Submissions from Natty don't have the nodes <dmi> and <udev>
         # as children of the <hardware> node. Fortunately, they provide
@@ -197,14 +198,14 @@
             mo = _missing_udev_node_data.search(submission)
             if mo is not None:
                 missing_data = mo.group(1)
-                missing_data = '<udev>%s</udev>\n</hardware>' % missing_data
-                submission = submission.replace('</hardware>', missing_data)
+                missing_data = b'<udev>%s</udev>\n</hardware>' % missing_data
+                submission = submission.replace(b'</hardware>', missing_data)
         if _dmi_node_exists.search(submission) is None:
             mo = _missing_dmi_node_data.search(submission)
             if mo is not None:
                 missing_data = mo.group(1)
-                missing_data = '<dmi>%s</dmi>\n</hardware>' % missing_data
-                submission = submission.replace('</hardware>', missing_data)
+                missing_data = b'<dmi>%s</dmi>\n</hardware>' % missing_data
+                submission = submission.replace(b'</hardware>', missing_data)
         return submission
 
     def _getValidatedEtree(self, submission, submission_key):
@@ -215,7 +216,7 @@
         """
         submission = self.fixFrequentErrors(submission)
         try:
-            tree = etree.parse(StringIO(submission), parser=self.doc_parser)
+            tree = etree.parse(io.BytesIO(submission), parser=self.doc_parser)
         except SyntaxError as error_value:
             self._logError(error_value, submission_key)
             return None

=== modified file 'lib/lp/hardwaredb/scripts/tests/test_hwdb_submission_parser.py'
--- lib/lp/hardwaredb/scripts/tests/test_hwdb_submission_parser.py	2012-01-01 02:58:52 +0000
+++ lib/lp/hardwaredb/scripts/tests/test_hwdb_submission_parser.py	2019-04-16 17:22:40 +0000
@@ -3,8 +3,10 @@
 
 """Tests of the HWDB submissions parser."""
 
-from cStringIO import StringIO
+from __future__ import absolute_import, print_function, unicode_literals
+
 from datetime import datetime
+import io
 import logging
 import os
 from textwrap import dedent
@@ -343,18 +345,18 @@
 
     def testStringPropertyEncoding(self):
         """Different encodings are properly handled."""
-        xml_template = '''<?xml version="1.0" encoding="%s"?>
-                          <property type="str" name="foo">%s</property>'''
+        xml_template = u'''<?xml version="1.0" encoding="%s"?>
+                           <property type="str" name="foo">%s</property>'''
         umlaut = u'\xe4'
         parser = SubmissionParser()
         for encoding in ('utf-8', 'iso-8859-1'):
-            xml = xml_template % (encoding, umlaut.encode(encoding))
-            tree = etree.parse(StringIO(xml))
+            xml = (xml_template % (encoding, umlaut)).encode(encoding)
+            tree = etree.parse(io.BytesIO(xml))
             node = tree.getroot()
             result = parser._parseProperty(node)
             self.assertEqual(result, ('foo', (umlaut, 'str')),
                 'Invalid parsing result for string encoding %s, '
-                'expected am umlaut (\xe4), got %s'
+                'expected an umlaut (\xe4), got %s'
                     % (encoding, repr(result)))
 
     def testIntegerPropertyTypes(self):
@@ -1431,7 +1433,7 @@
         sample_data_path = os.path.join(
             config.root, 'lib', 'lp', 'hardwaredb', 'scripts',
             'tests', 'hardwaretest.xml')
-        sample_data = open(sample_data_path).read()
+        sample_data = open(sample_data_path, 'rb').read()
         parser = SubmissionParser()
         result = parser.parseSubmission(sample_data, 'parser test 1')
         self.assertNotEqual(result, None,
@@ -1441,7 +1443,7 @@
         # parseSubmission returns None, if the submitted data is not
         # well-formed XML...
         result = parser.parseSubmission(
-            sample_data.replace('<summary', '<inconsitent_opening_tag'),
+            sample_data.replace(b'<summary', b'<inconsitent_opening_tag'),
             'parser test 2')
         self.assertEqual(result, None,
                          'Not-well-formed XML data accepted by '
@@ -1449,7 +1451,7 @@
 
         # ...or if RelaxNG validation fails...
         result = parser.parseSubmission(
-            sample_data.replace('<summary', '<summary foo="bar"'),
+            sample_data.replace(b'<summary', b'<summary foo="bar"'),
             'parser test 3')
         self.assertEqual(result, None,
                          'XML data that does pass the Relax NG validation '
@@ -1459,8 +1461,8 @@
         # property set containing two properties with the same name.
         result = parser.parseSubmission(
             sample_data.replace(
-                '<property name="info.parent"',
-                """<property name="info.parent" type="dbus.String">
+                b'<property name="info.parent"',
+                b"""<property name="info.parent" type="dbus.String">
                        foo
                    </property>
                    <property name="info.parent"
@@ -1980,8 +1982,8 @@
             [self.udev_root_device, self.udev_pci_device]))
         self.assertErrorMessage(
             parser.submission_key,
-            "Non-PCI udev device with PCI properties: set(['PCI_SLOT_NAME']) "
-            "'/devices/LNXSYSTM:00'")
+            "Non-PCI udev device with PCI properties: set([u'PCI_SLOT_NAME']) "
+            "u'/devices/LNXSYSTM:00'")
 
     def testCheckUdevPciPropertiesPciDeviceWithoutRequiredProperties(self):
         """Test of SubmissionParser.checkUdevPciProperties().
@@ -1997,7 +1999,7 @@
         self.assertErrorMessage(
             parser.submission_key,
             "PCI udev device without required PCI properties: "
-            "set(['PCI_CLASS']) '/devices/pci0000:00/0000:00:1f.2'")
+            "set(['PCI_CLASS']) u'/devices/pci0000:00/0000:00:1f.2'")
 
     def testCheckUdevPciPropertiesPciDeviceWithNonIntegerPciClass(self):
         """Test of SubmissionParser.checkUdevPciProperties().
@@ -2012,8 +2014,8 @@
             [self.udev_root_device, self.udev_pci_device]))
         self.assertErrorMessage(
             parser.submission_key,
-            "Invalid udev PCI class: 'not-an-integer' "
-            "'/devices/pci0000:00/0000:00:1f.2'")
+            "Invalid udev PCI class: u'not-an-integer' "
+            "u'/devices/pci0000:00/0000:00:1f.2'")
 
     def testCheckUdevPciPropertiesPciDeviceWithInvalidPciClassValue(self):
         """Test of SubmissionParser.checkUdevPciProperties().
@@ -2028,8 +2030,8 @@
             [self.udev_root_device, self.udev_pci_device]))
         self.assertErrorMessage(
             parser.submission_key,
-            "Invalid udev PCI class: '1234567' "
-            "'/devices/pci0000:00/0000:00:1f.2'")
+            "Invalid udev PCI class: u'1234567' "
+            "u'/devices/pci0000:00/0000:00:1f.2'")
 
     def testCheckUdevPciPropertiesPciDeviceWithInvalidDeviceID(self):
         """Test of SubmissionParser.checkUdevPciProperties().
@@ -2044,8 +2046,8 @@
             [self.udev_root_device, self.udev_pci_device]))
         self.assertErrorMessage(
             parser.submission_key,
-            "Invalid udev PCI device ID: 'not-an-id' "
-            "'/devices/pci0000:00/0000:00:1f.2'")
+            "Invalid udev PCI device ID: u'not-an-id' "
+            "u'/devices/pci0000:00/0000:00:1f.2'")
 
     def testCheckUdevPciPropertiesPciDeviceWithInvalidSubsystemID(self):
         """Test of SubmissionParser.checkUdevPciProperties().
@@ -2060,8 +2062,8 @@
             [self.udev_root_device, self.udev_pci_device]))
         self.assertErrorMessage(
             parser.submission_key,
-            "Invalid udev PCI device ID: 'not-a-subsystem-id' "
-            "'/devices/pci0000:00/0000:00:1f.2'")
+            "Invalid udev PCI device ID: u'not-a-subsystem-id' "
+            "u'/devices/pci0000:00/0000:00:1f.2'")
 
     def testCheckUdevUsbProperties(self):
         """Test of SubmissionParser.checkUdevUsbProperties().
@@ -2096,7 +2098,7 @@
             self.assertErrorMessage(
                 parser.submission_key,
                 "USB udev device found without required properties: "
-                "set(['%s']) '/devices/pci0000:00/0000:00:1d.1/usb3/3-2'"
+                "set(['%s']) u'/devices/pci0000:00/0000:00:1d.1/usb3/3-2'"
                 % property_name)
             self.udev_usb_device['E'][property_name] = saved_property
 
@@ -2114,8 +2116,8 @@
         self.assertErrorMessage(
             parser.submission_key,
             "USB udev device found with invalid product ID: "
-            "'not-a-valid-usb-product-id' "
-            "'/devices/pci0000:00/0000:00:1d.1/usb3/3-2'")
+            "u'not-a-valid-usb-product-id' "
+            "u'/devices/pci0000:00/0000:00:1d.1/usb3/3-2'")
 
     def testCheckUdevUsbProperties_with_invalid_type_data(self):
         """Test of SubmmissionParser.checkUdevUsbProperties().
@@ -2129,8 +2131,8 @@
             [self.udev_root_device, self.udev_usb_device]))
         self.assertErrorMessage(
             parser.submission_key,
-            "USB udev device found with invalid type data: 'no-type' "
-            "'/devices/pci0000:00/0000:00:1d.1/usb3/3-2'")
+            "USB udev device found with invalid type data: u'no-type' "
+            "u'/devices/pci0000:00/0000:00:1d.1/usb3/3-2'")
 
     def testCheckUdevUsbProperties_with_invalid_devtype(self):
         """Test of SubmmissionParser.checkUdevUsbProperties().
@@ -2145,8 +2147,8 @@
             [self.udev_root_device, self.udev_usb_device]))
         self.assertErrorMessage(
             parser.submission_key,
-            "USB udev device found with invalid udev type data: 'nonsense' "
-            "'/devices/pci0000:00/0000:00:1d.1/usb3/3-2'")
+            "USB udev device found with invalid udev type data: u'nonsense' "
+            "u'/devices/pci0000:00/0000:00:1d.1/usb3/3-2'")
 
     def testCheckUdevUsbProperties_interface_without_interface_property(self):
         """Test of SubmmissionParser.checkUdevUsbProperties().
@@ -2161,7 +2163,7 @@
         self.assertErrorMessage(
             parser.submission_key,
             "USB interface udev device found without INTERFACE property: "
-            "'/devices/pci0000:00/0000:00:1d.1/usb3/3-2/3-2:1.1'")
+            "u'/devices/pci0000:00/0000:00:1d.1/usb3/3-2/3-2:1.1'")
 
     def testCheckUdevUsbProperties_interface_invalid_interface_property(self):
         """Test of SubmmissionParser.checkUdevUsbProperties().
@@ -2177,8 +2179,8 @@
         self.assertErrorMessage(
             parser.submission_key,
             "USB Interface udev device found with invalid INTERFACE "
-            "property: 'nonsense' "
-            "'/devices/pci0000:00/0000:00:1d.1/usb3/3-2/3-2:1.1'")
+            "property: u'nonsense' "
+            "u'/devices/pci0000:00/0000:00:1d.1/usb3/3-2/3-2:1.1'")
 
     def testCheckUdevScsiProperties(self):
         """Test of SubmissionParser.checkUdevScsiProperties()."""
@@ -2218,7 +2220,7 @@
         self.assertErrorMessage(
             parser.submission_key,
             "SCSI udev node found without DEVTYPE property: "
-            "'/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0'")
+            "u'/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0'")
 
     def testCheckUdevScsiProperties_no_sysfs_data(self):
         """Test of SubmissionParser.checkUdevScsiProperties().
@@ -2234,7 +2236,7 @@
         self.assertErrorMessage(
             parser.submission_key,
             "SCSI udev device node found without related sysfs record: "
-            "'/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0'")
+            "u'/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0'")
 
     def testCheckUdevScsiProperties_missing_sysfs_attributes(self):
         """Test of SubmissionParser.checkUdevScsiProperties().
@@ -2255,7 +2257,7 @@
             parser.submission_key,
             "SCSI udev device found without required sysfs attributes: "
             "set(['model']) "
-            "'/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0'")
+            "u'/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0'")
 
     class UdevTestSubmissionParser(SubmissionParser):
         """A variant of SubmissionParser that shortcuts udev related tests.
@@ -2612,4 +2614,4 @@
         self.assertErrorMessage(
             'Consistency check detects circular parent-child relationships',
             "Found HAL devices with circular parent/child "
-                "relationship: ['/foo', '/bar']")
+                "relationship: [u'/foo', u'/bar']")

=== modified file 'lib/lp/hardwaredb/scripts/tests/test_hwdb_submission_processing.py'
--- lib/lp/hardwaredb/scripts/tests/test_hwdb_submission_processing.py	2018-01-02 15:23:24 +0000
+++ lib/lp/hardwaredb/scripts/tests/test_hwdb_submission_processing.py	2019-04-16 17:22:40 +0000
@@ -3,10 +3,12 @@
 
 """Tests of the HWDB submissions parser."""
 
+from __future__ import absolute_import, print_function, unicode_literals
+
 import bz2
 from copy import deepcopy
-from cStringIO import StringIO
 from datetime import datetime
+import io
 import logging
 import os
 
@@ -397,7 +399,7 @@
         parser.submission_key = 'udev device with invalid path'
         self.assertFalse(parser.buildUdevDeviceList(parsed_data))
         self.assertErrorMessage(
-            parser.submission_key, "Invalid device path name: '/nonsense'")
+            parser.submission_key, "Invalid device path name: u'/nonsense'")
 
     def test_buildUdevDeviceList_missing_root_device(self):
         """Test the creation of UdevDevice instances for a submission.
@@ -1565,7 +1567,7 @@
                          % found_bus)
         self.assertWarningMessage(
             parser.submission_key,
-            "Unknown bus 'nonsense' for device " + self.UDI_PCCARD_DEVICE)
+            "Unknown bus u'nonsense' for device " + self.UDI_PCCARD_DEVICE)
 
     def test_HALDevice_is_root_device_for_root_device(self):
         """Test of HALDevice.is_root_device for the root device."""
@@ -2147,13 +2149,13 @@
             ('pci.vendor_id',
              "A HALDevice that is supposed to be a real device does not "
              "provide bus, vendor ID, product ID or product name: <DBItem "
-             "HWBus.PCI, (1) PCI> None 28980 'Intel PCCard bridge 1234' "
+             "HWBus.PCI, (1) PCI> None 28980 u'Intel PCCard bridge 1234' "
              "/org/freedesktop/Hal/devices/pci_8086_27c5"
              ),
             ('pci.product_id',
              "A HALDevice that is supposed to be a real device does not "
              "provide bus, vendor ID, product ID or product name: "
-             "<DBItem HWBus.PCI, (1) PCI> 32902 None 'Intel PCCard bridge "
+             "<DBItem HWBus.PCI, (1) PCI> 32902 None u'Intel PCCard bridge "
              "1234' /org/freedesktop/Hal/devices/pci_8086_27c5"
              ),
             ('info.product',
@@ -4212,7 +4214,7 @@
         # which a USB is not. Hence we get a warning.
         self.assertWarningMessage(
             parser.submission_key,
-            "Unknown bus 'usb_interface' for device "
+            "Unknown bus u'usb_interface' for device "
             "/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0")
 
     def test_real_bus_pci(self):
@@ -4370,8 +4372,8 @@
             parser.submission_key,
             "A UdevDevice that is supposed to be a real device does not "
             "provide bus, vendor ID, product ID or product name: "
-            "<DBItem HWBus.SYSTEM, (0) System> None 'LIFEBOOK E8210' "
-            "'LIFEBOOK E8210' /devices/LNXSYSTM:00")
+            "<DBItem HWBus.SYSTEM, (0) System> None u'LIFEBOOK E8210' "
+            "u'LIFEBOOK E8210' /devices/LNXSYSTM:00")
 
     def test_has_reliable_data_system_no_product_name(self):
         """Test of UdevDevice.has_reliable_data for a system.
@@ -4390,7 +4392,7 @@
             parser.submission_key,
             "A UdevDevice that is supposed to be a real device does not "
             "provide bus, vendor ID, product ID or product name: "
-            "<DBItem HWBus.SYSTEM, (0) System> 'FUJITSU SIEMENS' None None "
+            "<DBItem HWBus.SYSTEM, (0) System> u'FUJITSU SIEMENS' None None "
             "/devices/LNXSYSTM:00")
 
     def test_has_reliable_data_acpi_device(self):
@@ -5078,6 +5080,8 @@
     def createSubmissionData(self, data, compress, submission_key,
                              private=False):
         """Create a submission."""
+        if not isinstance(data, bytes):
+            data = data.encode('UTF-8')
         if compress:
             data = bz2.compress(data)
         switch_dbuser('launchpad')
@@ -5089,7 +5093,7 @@
             submission_key=submission_key,
             emailaddress=u'test@xxxxxxxxxxxxx',
             distroarchseries=None,
-            raw_submission=StringIO(data),
+            raw_submission=io.BytesIO(data),
             filename='hwinfo.xml',
             filesize=len(data),
             system_fingerprint='A Machine Name')

=== modified file 'lib/lp/hardwaredb/scripts/tests/test_hwdbsubmissions.py'
--- lib/lp/hardwaredb/scripts/tests/test_hwdbsubmissions.py	2012-04-23 11:52:39 +0000
+++ lib/lp/hardwaredb/scripts/tests/test_hwdbsubmissions.py	2019-04-16 17:22:40 +0000
@@ -3,6 +3,8 @@
 
 """Tests for hwdbsubmissions script."""
 
+from __future__ import absolute_import, print_function, unicode_literals
+
 __metaclass__ = type
 
 from tempfile import mktemp

=== modified file 'lib/lp/hardwaredb/stories/hwdb/xx-hwdb.txt'
--- lib/lp/hardwaredb/stories/hwdb/xx-hwdb.txt	2016-01-26 15:47:37 +0000
+++ lib/lp/hardwaredb/stories/hwdb/xx-hwdb.txt	2019-04-16 17:22:40 +0000
@@ -42,7 +42,7 @@
 For easy error checks by the HWDB client, an extra header is added, if the
 data has successfully been uploaded.
 
-    >>> print browser.headers
+    >>> print(browser.headers)
     Status: 200 Ok
     Content-Length: ...
     Content-Type: text/html;charset=utf-8
@@ -56,7 +56,7 @@
 
     >>> for tag in find_tags_by_class(
     ...     browser.contents, 'informational message'):
-    ...     print tag
+    ...     print(tag)
     <div class="informational message">Thank you for your submission.</div>
 
 If fields are not set, the response contains a header explaining this
@@ -74,8 +74,8 @@
     ...         browser, wrong_data, submit_data_checkboxes, submit_file,
     ...         'test.txt')
     ...     browser.getControl('Upload').click()
-    ...     print "--- missing field", field
-    ...     print browser.headers
+    ...     print("--- missing field", field)
+    ...     print(browser.headers)
     --- missing field Date Created:
     Status: 200 Ok
     ...
@@ -118,7 +118,7 @@
     >>> fill_form(
     ...     browser, wrong_data, submit_data_checkboxes, None, 'test.txt')
     >>> browser.getControl('Upload').click()
-    >>> print browser.headers
+    >>> print(browser.headers)
     Status: 200 Ok
     ...
     X-Launchpad-Hwdb-Submission: Error in field 'submission_data' - Required input is missing.
@@ -134,7 +134,7 @@
     ...     browser, wrong_data, submit_data_checkboxes, submit_file,
     ...     'test.txt')
     >>> browser.getControl('Upload').click()
-    >>> print browser.headers
+    >>> print(browser.headers)
     Status: 200 Ok
     ...
     X-Launchpad-Hwdb-Submission: Error in field 'submission_key' - Submission key already exists.
@@ -149,7 +149,7 @@
     ...     browser, wrong_data, submit_data_checkboxes, submit_file,
     ...     'test.txt')
     >>> browser.getControl('Upload').click()
-    >>> print browser.headers
+    >>> print(browser.headers)
     Status: 200 Ok
     ...
     X-Launchpad-Hwdb-Submission: Error in field 'date_created' - Invalid datetime data
@@ -164,7 +164,7 @@
     ...     browser, wrong_data, submit_data_checkboxes, submit_file,
     ...     'test.txt')
     >>> browser.getControl('Upload').click()
-    >>> print browser.headers
+    >>> print(browser.headers)
     Status: 200 Ok
     ...
     X-Launchpad-Hwdb-Submission: Error in field 'submission_key' - Invalid textual data
@@ -179,7 +179,7 @@
     ...     browser, wrong_data, submit_data_checkboxes, submit_file,
     ...     'test.txt')
     >>> browser.getControl('Upload').click()
-    >>> print browser.headers
+    >>> print(browser.headers)
     Status: 200 Ok
     ...
     X-Launchpad-Hwdb-Submission: Error in field 'emailaddress' - Invalid email address
@@ -212,7 +212,7 @@
     ... }
     >>> browser.open('http://launchpad.dev/+hwdb/+submit',
     ...     data=urlencode(form_data))
-    >>> print browser.headers
+    >>> print(browser.headers)
     Status: 200 Ok
     ...
     X-Launchpad-Hwdb-Submission: Error: Required fields not contained in
@@ -230,7 +230,7 @@
 
     >>> anon_browser.open('http://launchpad.dev/~name12/+hwdb-submissions')
     >>> [content_table] = find_tags_by_class(anon_browser.contents, 'listing')
-    >>> print extract_text(content_table)
+    >>> print(extract_text(content_table))
     System        Date submitted  Download          Raw
     Fujitsu_CY26  ...             test.txt          ...
     TONKA TUFFBOOK2600 ...        hwsubmission1.xml ...
@@ -297,7 +297,7 @@
     >>> browser.getControl('Upload').click()
     >>> anon_browser.open('http://launchpad.dev/~name12/+hwdb-submissions')
     >>> [content_table] = find_tags_by_class(anon_browser.contents, 'listing')
-    >>> print extract_text(content_table)
+    >>> print(extract_text(content_table))
     System        Date submitted  Download          Raw
     Fujitsu_CY26  ...             test.txt          ...
     TONKA TUFFBOOK2600 ...        hwsubmission1.xml ...
@@ -312,7 +312,7 @@
     >>> browser = setupBrowser(auth='Basic test@xxxxxxxxxxxxx:test')
     >>> browser.open('http://launchpad.dev/~name12/+hwdb-submissions')
     >>> [content_table] = find_tags_by_class(browser.contents, 'listing')
-    >>> print extract_text(content_table)
+    >>> print(extract_text(content_table))
     System        Date submitted  Download          Private     Raw
     Fujitsu_CY26  ...             test2.txt           yes       ...
     Fujitsu_CY26  ...             test.txt             no       ...
@@ -322,7 +322,7 @@
 displayed.
 
     >>> anon_browser.open('http://launchpad.dev/~name16/+hwdb-submissions')
-    >>> print extract_text(find_main_content(anon_browser.contents))
+    >>> print(extract_text(find_main_content(anon_browser.contents)))
     Hardware submissions for Foo Bar...
     Foo Bar has posted no submissions.
 
@@ -351,14 +351,14 @@
     >>> browser.getControl('Upload').click()
     >>> anon_browser.open(
     ...     'http://launchpad.dev/~ubuntu-team/+hwdb-submissions')
-    >>> print extract_text(find_main_content(anon_browser.contents))
+    >>> print(extract_text(find_main_content(anon_browser.contents)))
     Hardware submissions for ...Ubuntu Team...
     Ubuntu Team has posted no submissions.
 
     >>> browser = setupBrowser(auth='Basic celso.providelo@xxxxxxxxxxxxx:test')
     >>> browser.open('http://launchpad.dev/~ubuntu-team/+hwdb-submissions')
     >>> [content_table] = find_tags_by_class(browser.contents, 'listing')
-    >>> print extract_text(content_table)
+    >>> print(extract_text(content_table))
     System        Date submitted  Download          Raw
     Black Box 42  ...             teamtest.txt      ...
 
@@ -371,7 +371,7 @@
 
     >>> browser.open(
     ...     'http://launchpad.dev/+hwdb/+submission/unique-id-1/+text')
-    >>> print browser.contents
+    >>> print(browser.contents)
     Date-Created: 2007-01-01 00:00:00+00:00
     Date-Submitted: ...
     Format: VERSION_1
@@ -394,7 +394,7 @@
     >>> browser = setupBrowser(auth='Basic celso.providelo@xxxxxxxxxxxxx:test')
     >>> browser.open(
     ...     'http://launchpad.dev/+hwdb/+submission/unique-id-3a/+text')
-    >>> print browser.contents
+    >>> print(browser.contents)
     Date-Created: 2007-01-01 00:00:00+00:00
     Date-Submitted: ...
     Format: VERSION_1
@@ -413,7 +413,7 @@
     >>> anon_browser.open(
     ...     'http://launchpad.dev/+hwdb/+fingerprint/Fujitsu_CY26')
     >>> [content_table] = find_tags_by_class(anon_browser.contents, 'listing')
-    >>> print extract_text(content_table)
+    >>> print(extract_text(content_table))
     Date submitted     Submitted by    Download     Raw
     ...                     n/a        test.txt     ...
 
@@ -432,7 +432,7 @@
     >>> anon_browser.open(
     ...     'http://launchpad.dev/+hwdb/+fingerprint/Fujitsu_CY26')
     >>> [content_table] = find_tags_by_class(anon_browser.contents, 'listing')
-    >>> print extract_text(content_table)
+    >>> print(extract_text(content_table))
     Date submitted     Submitted by            Download     Raw
     ...                Sample Person (name12)  test3.txt    ...
     ...                    n/a                 test.txt     ...
@@ -443,7 +443,7 @@
     >>> browser.open(
     ...     'http://launchpad.dev/+hwdb/+fingerprint/Fujitsu_CY26')
     >>> [content_table] = find_tags_by_class(browser.contents, 'listing')
-    >>> print extract_text(content_table)
+    >>> print(extract_text(content_table))
     Date submitted     Submitted by              Download        Raw
     ...                Sample Person (name12)    test3.txt       ...
     ...                Sample Person (name12)    test2.txt       ...
@@ -453,7 +453,7 @@
 
     >>> anon_browser.open(
     ...     'http://launchpad.dev/+hwdb/+fingerprint/unknownfingerprint')
-    >>> print extract_text(find_main_content(anon_browser.contents))
+    >>> print(extract_text(find_main_content(anon_browser.contents)))
     Hardware Database submissions for a fingerprint
     Submissions for system: unknownfingerprint
     There are no submissions for this system.

=== modified file 'lib/lp/hardwaredb/stories/webservice/xx-hwdb.txt'
--- lib/lp/hardwaredb/stories/webservice/xx-hwdb.txt	2015-10-06 06:48:01 +0000
+++ lib/lp/hardwaredb/stories/webservice/xx-hwdb.txt	2019-04-16 17:22:40 +0000
@@ -49,8 +49,8 @@
 
 The query parameter `bus` must be a bus name as enumerated by HWBus.
 
-    >>> print webservice.get(
-    ...     '/+hwdb?ws.op=devices&bus=NoSuchBus&vendor_id=MSI')
+    >>> print(webservice.get(
+    ...     '/+hwdb?ws.op=devices&bus=NoSuchBus&vendor_id=MSI'))
     HTTP/1.1 400 Bad Request
     ...
     bus: Invalid value "NoSuchBus". Acceptable values are: System, PCI,
@@ -58,14 +58,14 @@
 
 Omitting the query parameters `bus` or `vendor_id` leads to an error.
 
-    >>> print webservice.get(
-    ...     '/+hwdb?ws.op=devices&bus=System')
+    >>> print(webservice.get(
+    ...     '/+hwdb?ws.op=devices&bus=System'))
     HTTP/1.1 400 Bad Request
     ...
     vendor_id: Required input is missing.
 
-    >>> print webservice.get(
-    ...     '/+hwdb?ws.op=devices&vendor_id=MSI')
+    >>> print(webservice.get(
+    ...     '/+hwdb?ws.op=devices&vendor_id=MSI'))
     HTTP/1.1 400 Bad Request
     ...
     bus: Required input is missing.
@@ -91,7 +91,7 @@
 
     >>> devices = webservice.get(
     ...     '/+hwdb?ws.op=devices&bus=System&vendor_id=MSI&product_id=nothing')
-    >>> print devices.jsonBody()['entries']
+    >>> print(devices.jsonBody()['entries'])
     []
 
 Some buses have constraints for the values of vendor and product IDs.
@@ -99,14 +99,14 @@
 an overview of these constraints, see doc/hwdb-device-tables.txt.)
 Queries with invalid parameter values return a 400 error.
 
-    >>> print webservice.get(
-    ...     '/+hwdb?ws.op=devices&bus=PCI&vendor_id=WRONG')
+    >>> print(webservice.get(
+    ...     '/+hwdb?ws.op=devices&bus=PCI&vendor_id=WRONG'))
     HTTP/1.1 400 Bad Request
     ...
     u'WRONG' is not a valid vendor ID for PCI
 
-    >>> print webservice.get(
-    ...     '/+hwdb?ws.op=devices&bus=PCI&vendor_id=0x1234&product_id=BAD')
+    >>> print(webservice.get(
+    ...     '/+hwdb?ws.op=devices&bus=PCI&vendor_id=0x1234&product_id=BAD'))
     HTTP/1.1 400 Bad Request
     ...
     u'BAD' is not a valid product ID for PCI
@@ -129,7 +129,7 @@
 
 A 404 error is returned, when a non-existent ID is passed in the URL...
 
-    >>> print webservice.get('/+hwdb/+device/1000000')
+    >>> print(webservice.get('/+hwdb/+device/1000000'))
     HTTP/1.1 404 Not Found
     ...
     Object: <lp.systemhomes.HWDBApplication
@@ -137,7 +137,7 @@
 
 ...and when an otherwise invalid ID is passed.
 
-    >>> print webservice.get('/+hwdb/+device/nonsense')
+    >>> print(webservice.get('/+hwdb/+device/nonsense'))
     HTTP/1.1 404 Not Found
     ...
     Object: <lp.systemhomes.HWDBApplication
@@ -187,7 +187,7 @@
     >>> class_info = webservice.named_post(
     ...     '/+hwdb/+device/2', 'getOrCreateDeviceClass', {}, main_class=12,
     ...     sub_class=3).jsonBody()
-    >>> print class_info['self_link']
+    >>> print(class_info['self_link'])
     http://api.launchpad.dev/beta/+hwdb/+deviceclass/...
 
 The property device.classes returns the collection of all classes
@@ -203,12 +203,12 @@
 
 We can delete existing class data by calling deviceclass.delete().
 
-    >>> print webservice.delete(class_info['entries'][0]['self_link'])
+    >>> print(webservice.delete(class_info['entries'][0]['self_link']))
     HTTP/1.1 200 Ok
     ...
 
     >>> class_info = webservice.get('/+hwdb/+device/2/classes').jsonBody()
-    >>> print class_info['total_size']
+    >>> print(class_info['total_size'])
     0
 
 
@@ -389,7 +389,7 @@
 
 A 404 error is returned, when a non-existent ID is passed in the URL...
 
-    >>> print webservice.get('/+hwdb/+driver/1000000')
+    >>> print(webservice.get('/+hwdb/+driver/1000000'))
     HTTP/1.1 404 Not Found
     ...
     Object: <lp.systemhomes.HWDBApplication
@@ -397,7 +397,7 @@
 
 ...and when an otherwise invalid ID is passed.
 
-    >>> print webservice.get('/+hwdb/+driver/nonsense')
+    >>> print(webservice.get('/+hwdb/+driver/nonsense'))
     HTTP/1.1 404 Not Found
     ...
     Object: <lp.systemhomes.HWDBApplication
@@ -408,7 +408,7 @@
     >>> submissions = webservice.named_get(
     ...     '/+hwdb/+driver/1', 'getSubmissions').jsonBody()
     >>> for submission in submissions['entries']:
-    ...     print submission['submission_key']
+    ...     print(submission['submission_key'])
     sample-submission
 
 We can filter the list of drivers by distribution.
@@ -417,13 +417,13 @@
     ...     '/+hwdb/+driver/1', 'getSubmissions',
     ...     distribution=webservice.getAbsoluteUrl('/ubuntu')).jsonBody()
     >>> for submission in submissions['entries']:
-    ...     print submission['submission_key']
+    ...     print(submission['submission_key'])
     sample-submission
 
     >>> submissions = webservice.named_get(
     ...     '/+hwdb/+driver/1', 'getSubmissions',
     ...     distribution=webservice.getAbsoluteUrl('/debian')).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     0
 
 We can filter the list of drivers by distribution series.
@@ -432,13 +432,13 @@
     ...     '/+hwdb/+driver/1', 'getSubmissions',
     ...     distroseries=webservice.getAbsoluteUrl('/ubuntu/hoary')).jsonBody()
     >>> for submission in submissions['entries']:
-    ...     print submission['submission_key']
+    ...     print(submission['submission_key'])
     sample-submission
 
     >>> submissions = webservice.named_get(
     ...     '/+hwdb/+driver/1', 'getSubmissions',
     ...     distroseries=webservice.getAbsoluteUrl('/ubuntu/warty')).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     0
 
 We can filter the list of drivers by processor architecture.
@@ -447,13 +447,13 @@
     ...     '/+hwdb/+driver/1', 'getSubmissions',
     ...     architecture='i386').jsonBody()
     >>> for submission in submissions['entries']:
-    ...     print submission['submission_key']
+    ...     print(submission['submission_key'])
     sample-submission
 
     >>> submissions = webservice.named_get(
     ...     '/+hwdb/+driver/1', 'getSubmissions',
     ...     architecture='powerpc').jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     0
 
 We can filter by distribution series and processor architecture.
@@ -463,7 +463,7 @@
     ...     distroseries=webservice.getAbsoluteUrl('/ubuntu/hoary'),
     ...     architecture='i386').jsonBody()
     >>> for submission in submissions['entries']:
-    ...     print submission['submission_key']
+    ...     print(submission['submission_key'])
     sample-submission
 
 
@@ -536,7 +536,7 @@
 
 Accessing the raw submission data yields a redirect to a Librarian URL.
 
-    >>> print webservice.get(submission['raw_submission_link'])
+    >>> print(webservice.get(submission['raw_submission_link']))
     HTTP/1.1 303 See Other...
     Content-Length: 0
     Content-Type: text/plain
@@ -546,7 +546,7 @@
 A 404 error is returned when a client tries to access a non-existent
 submission.
 
-    >>> print webservice.get('/+hwdb/+submission/nonsense')
+    >>> print(webservice.get('/+hwdb/+submission/nonsense'))
     HTTP/1.1 404 Not Found
     ...
     Object: <...systemhomes.HWDBApplication object at ...>, name: u'nonsense'
@@ -557,7 +557,7 @@
     >>> submissions = webservice.get(
     ...     '/+hwdb/+device/2?ws.op=getSubmissions').jsonBody()
     >>> for submission in submissions['entries']:
-    ...     print submission['submission_key']
+    ...     print(submission['submission_key'])
     sample-submission
 
 We can limit the result set to submissions where the device is accessed
@@ -572,7 +572,7 @@
     >>> submissions = webservice.get(
     ...     '/+hwdb/+device/2?' + urlencode(parameters)).jsonBody()
     >>> for submission in submissions['entries']:
-    ...     print submission['submission_key']
+    ...     print(submission['submission_key'])
     sample-submission
 
 ...but when we set it to nv_xorg_driver, we get an empty result set.
@@ -583,7 +583,7 @@
     ...     }
     >>> submissions = webservice.get(
     ...     '/+hwdb/+device/2?' + urlencode(parameters)).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     0
 
 We can also limit the result set to submissions made for a specific
@@ -604,7 +604,7 @@
     >>> submissions = webservice.get(
     ...     '/+hwdb/+device/2?' + urlencode(parameters)).jsonBody()
     >>> for submission in submissions['entries']:
-    ...     print submission['submission_key']
+    ...     print(submission['submission_key'])
     sample-submission
 
     >>> parameters = {
@@ -613,7 +613,7 @@
     ...     }
     >>> submissions = webservice.get(
     ...     '/+hwdb/+device/2?' + urlencode(parameters)).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     0
 
 ...for a specific processor architecture...
@@ -625,7 +625,7 @@
     >>> submissions = webservice.get(
     ...     '/+hwdb/+device/2?' + urlencode(parameters)).jsonBody()
     >>> for submission in submissions['entries']:
-    ...     print submission['submission_key']
+    ...     print(submission['submission_key'])
     sample-submission
 
     >>> parameters = {
@@ -634,7 +634,7 @@
     ...     }
     >>> submissions = webservice.get(
     ...     '/+hwdb/+device/2?' + urlencode(parameters)).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     0
 
 ...for a specific distro series...
@@ -643,13 +643,13 @@
     ...     '/+hwdb/+device/2', 'getSubmissions',
     ...     distroseries=webservice.getAbsoluteUrl('/ubuntu/hoary')).jsonBody()
     >>> for submission in submissions['entries']:
-    ...     print submission['submission_key']
+    ...     print(submission['submission_key'])
     sample-submission
 
     >>> submissions = webservice.named_get(
     ...     '/+hwdb/+device/2', 'getSubmissions',
     ...     distroseries=webservice.getAbsoluteUrl('/ubuntu/warty')).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     0
 
 ...and the combination of a distro series and processor architecture.
@@ -659,22 +659,22 @@
     ...     distroseries=webservice.getAbsoluteUrl('/ubuntu/hoary'),
     ...     architecture='i386').jsonBody()
     >>> for submission in submissions['entries']:
-    ...     print submission['submission_key']
+    ...     print(submission['submission_key'])
     sample-submission
 
     >>> submissions = webservice.named_get(
     ...     '/+hwdb/+device/2', 'getSubmissions',
     ...     distroseries=webservice.getAbsoluteUrl('/ubuntu/hoary'),
     ...     architecture='powerpc').jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     0
 
 But we can't supply both distribution and distroseries.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb/+device/2', 'getSubmissions',
     ...     distribution=webservice.getAbsoluteUrl('/ubuntu'),
-    ...     distroseries=webservice.getAbsoluteUrl('/ubuntu/hoary'))
+    ...     distroseries=webservice.getAbsoluteUrl('/ubuntu/hoary')))
     HTTP/1.1 400 Bad Request
     ...
     Only one of `distribution` or `distroseries` can be present.
@@ -685,13 +685,13 @@
     ...     '/+hwdb/+device/2', 'getSubmissions',
     ...     owner=webservice.getAbsoluteUrl('/~name12')).jsonBody()
     >>> for submission in submissions['entries']:
-    ...     print submission['submission_key']
+    ...     print(submission['submission_key'])
     sample-submission
 
     >>> submissions = webservice.named_get(
     ...     '/+hwdb/+device/2', 'getSubmissions',
     ...     owner=webservice.getAbsoluteUrl('/~name20')).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     0
 
 === Getting all submissions for a user ===
@@ -718,13 +718,13 @@
     >>> owner = webservice.getAbsoluteUrl('/~name12')
     >>> submissions = webservice.get(
     ...     '/+hwdb?ws.op=search&owner=%s' % owner).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     2
 
     >>> owner = webservice.getAbsoluteUrl('/~name20')
     >>> submissions = webservice.get(
     ...     '/+hwdb?ws.op=search&owner=%s' % owner).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     0
 
 ...and by device:
@@ -732,7 +732,7 @@
     >>> device = webservice.getAbsoluteUrl('/+hwdb/+device/1')
     >>> submissions = webservice.named_get(
     ...     '/+hwdb', 'search', device=device).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     1
 
 ...and by driver:
@@ -740,7 +740,7 @@
     >>> driver = webservice.getAbsoluteUrl('/+hwdb/+driver/1')
     >>> submissions = webservice.named_get(
     ...     '/+hwdb', 'search', driver=driver).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     1
 
 ...and by distribution:
@@ -748,12 +748,12 @@
     >>> ubuntu_url = webservice.getAbsoluteUrl('/ubuntu')
     >>> submissions = webservice.named_get(
     ...     '/+hwdb', 'search', distribution=ubuntu_url).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     1
     >>> debian_url = webservice.getAbsoluteUrl('/debian')
     >>> submissions = webservice.named_get(
     ...     '/+hwdb', 'search', distribution=debian_url).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     0
 
 ...and by distroseries:
@@ -761,23 +761,23 @@
     >>> hoary_url = webservice.getAbsoluteUrl('/ubuntu/hoary')
     >>> submissions = webservice.named_get(
     ...     '/+hwdb', 'search', distroseries=hoary_url).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     1
     >>> warty_url = webservice.getAbsoluteUrl('/ubuntu/warty')
     >>> submissions = webservice.named_get(
     ...     '/+hwdb', 'search', distroseries=warty_url).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     0
 
 ...and by architecture:
 
     >>> submissions = webservice.named_get(
     ...     '/+hwdb', 'search', architecture='i386').jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     1
     >>> submissions = webservice.named_get(
     ...     '/+hwdb', 'search', architecture='powerpc').jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     0
 
 ...and by date created:
@@ -785,11 +785,11 @@
     >>> date_created = u'2007-09-11T00:00:00+00:00'
     >>> submissions = webservice.named_get(
     ...     '/+hwdb', 'search', created_before=date_created).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     1
     >>> submissions = webservice.named_get(
     ...     '/+hwdb', 'search', created_after=date_created).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     1
 
 ...and by date submitted:
@@ -797,11 +797,11 @@
     >>> date_submitted = u'2007-09-11T15:23:45.653316+00:00'
     >>> submissions = webservice.named_get(
     ...     '/+hwdb', 'search', submitted_before=date_submitted).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     1
     >>> submissions = webservice.named_get(
     ...     '/+hwdb', 'search', submitted_after=date_submitted).jsonBody()
-    >>> print submissions['total_size']
+    >>> print(submissions['total_size'])
     1
 
 
@@ -867,7 +867,7 @@
 
 A 404 error is returned, when a non-existent ID is passed in the URL...
 
-    >>> print webservice.get('/+hwdb/+hwvendorid/1000000')
+    >>> print(webservice.get('/+hwdb/+hwvendorid/1000000'))
     HTTP/1.1 404 Not Found
     ...
     Object: <lp.systemhomes.HWDBApplication
@@ -875,7 +875,7 @@
 
 ...and when an otherwise invalid ID is passed.
 
-    >>> print webservice.get('/+hwdb/+hwvendorid/nonsense')
+    >>> print(webservice.get('/+hwdb/+hwvendorid/nonsense'))
     HTTP/1.1 404 Not Found
     ...
     Object: <lp.systemhomes.HWDBApplication
@@ -905,52 +905,52 @@
 We can query how often a given device or a given driver appears in
 HWDB submissions.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     '
-    ...     ).jsonBody()
+    ...     ).jsonBody())
     1
 
-    >>> print webservice.named_get(
-    ...     '/+hwdb', 'numDevicesInSubmissions', driver_name='sd').jsonBody()
+    >>> print(webservice.named_get(
+    ...     '/+hwdb', 'numDevicesInSubmissions', driver_name='sd').jsonBody())
     5
 
 We can ask how many given devices controlled by a given driver appear
 in HWDB submissions.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='sd').jsonBody()
+    ...     driver_name='sd').jsonBody())
     1
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='nonsense').jsonBody()
+    ...     driver_name='nonsense').jsonBody())
     0
 
 This count can be limited to a package_name.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     package_name='linux-image-2.6.24-19-generic').jsonBody()
+    ...     package_name='linux-image-2.6.24-19-generic').jsonBody())
     1
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     package_name='nonsense').jsonBody()
+    ...     package_name='nonsense').jsonBody())
     0
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions', driver_name='sd',
-    ...     package_name='linux-image-2.6.24-19-generic').jsonBody()
+    ...     package_name='linux-image-2.6.24-19-generic').jsonBody())
     5
 
 While the parameters for a device and for a driver are optional,
 specifying neither leads to an error.
 
-    >>> print webservice.named_get('/+hwdb', 'numDevicesInSubmissions')
+    >>> print(webservice.named_get('/+hwdb', 'numDevicesInSubmissions'))
     HTTP/1.1 400 Bad Request
     ...
     Specify (bus, vendor_id, product_id) or driver_name.
@@ -958,77 +958,76 @@
 We can additionally pass a reference to a distribution...
 
     >>> ubuntu_url = webservice.getAbsoluteUrl('/ubuntu')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distribution=ubuntu_url).jsonBody()
+    ...     distribution=ubuntu_url).jsonBody())
     1
     >>> debian_url = webservice.getAbsoluteUrl('/debian')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distribution=debian_url).jsonBody()
+    ...     distribution=debian_url).jsonBody())
     0
 
 ...a reference to a distroseries...
 
     >>> hoary_url = webservice.getAbsoluteUrl('/ubuntu/hoary')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroseries=hoary_url).jsonBody()
+    ...     distroseries=hoary_url).jsonBody())
     1
     >>> warty_url = webservice.getAbsoluteUrl('/ubuntu/warty')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroseries=warty_url).jsonBody()
+    ...     distroseries=warty_url).jsonBody())
     0
 
 ...or a reference to a distroarchseries.
 
     >>> hoary_i386_url = webservice.getAbsoluteUrl('/ubuntu/hoary/i386')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroarchseries=hoary_i386_url).jsonBody()
+    ...     distroarchseries=hoary_i386_url).jsonBody())
     1
     >>> hoary_hppa_url = webservice.getAbsoluteUrl('/ubuntu/hoary/hppa')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroarchseries=hoary_hppa_url).jsonBody()
+    ...     distroarchseries=hoary_hppa_url).jsonBody())
     0
 
 But at most one of the parameters distribution, distroseries,
 distroarchseries may be specified.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distribution=ubuntu_url, distroseries=hoary_url)
+    ...     distribution=ubuntu_url, distroseries=hoary_url))
     ...
     HTTP/1.1 400 Bad Request
     ...
     Only one of `distribution`, `distroseries` or `distroarchseries` can
     be present.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     distribution=ubuntu_url,
-    ...     distroarchseries=hoary_i386_url)
+    ...     distroarchseries=hoary_i386_url))
     ...
     HTTP/1.1 400 Bad Request
     ...
     Only one of `distribution`, `distroseries` or `distroarchseries` can
     be present.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numDevicesInSubmissions',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroseries=hoary_url, distroarchseries=hoary_i386_url
-    ...     )
+    ...     distroseries=hoary_url, distroarchseries=hoary_i386_url))
     HTTP/1.1 400 Bad Request
     ...
     Only one of `distribution`, `distroseries` or `distroarchseries` can
@@ -1040,46 +1039,47 @@
 distroseries or distroarchseries, if one of these parameters is
 specified.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numSubmissionsWithDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     '
-    ...     ).jsonBody()
+    ...     ).jsonBody())
     {u'submissions_with_device': 1, u'all_submissions': 1}
 
-    >>> print webservice.named_get(
-    ...     '/+hwdb', 'numSubmissionsWithDevice', driver_name='sd').jsonBody()
+    >>> print(webservice.named_get(
+    ...     '/+hwdb', 'numSubmissionsWithDevice',
+    ...     driver_name='sd').jsonBody())
     {u'submissions_with_device': 1, u'all_submissions': 1}
 
 The parameters for a device and a driver can be combined.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numSubmissionsWithDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='sd').jsonBody()
+    ...     driver_name='sd').jsonBody())
     {u'submissions_with_device': 1, u'all_submissions': 1}
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numSubmissionsWithDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='nonsense').jsonBody()
+    ...     driver_name='nonsense').jsonBody())
     {u'submissions_with_device': 0, u'all_submissions': 1}
 
 Additionally, a package_name can be passed.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numSubmissionsWithDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     package_name='linux-image-2.6.24-19-generic').jsonBody()
+    ...     package_name='linux-image-2.6.24-19-generic').jsonBody())
     {u'submissions_with_device': 1, u'all_submissions': 1}
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numSubmissionsWithDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     package_name='nonsense').jsonBody()
+    ...     package_name='nonsense').jsonBody())
     {u'submissions_with_device': 0, u'all_submissions': 1}
 
 If neither a device nor a driver is specified, an error is returned.
 
-    >>> print webservice.named_get(
-    ...     '/+hwdb', 'numSubmissionsWithDevice')
+    >>> print(webservice.named_get(
+    ...     '/+hwdb', 'numSubmissionsWithDevice'))
     HTTP/1.1 400 Bad Request
     ...
     Specify (bus, vendor_id, product_id) or driver_name.
@@ -1087,77 +1087,76 @@
 The count can be limited to a distribution...
 
     >>> ubuntu_url = webservice.getAbsoluteUrl('/ubuntu')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numSubmissionsWithDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distribution=ubuntu_url).jsonBody()
+    ...     distribution=ubuntu_url).jsonBody())
     {u'submissions_with_device': 1, u'all_submissions': 1}
     >>> debian_url = webservice.getAbsoluteUrl('/debian')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numSubmissionsWithDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distribution=debian_url).jsonBody()
+    ...     distribution=debian_url).jsonBody())
     {u'submissions_with_device': 0, u'all_submissions': 0}
 
 ...or a distroseries...
 
     >>> hoary_url = webservice.getAbsoluteUrl('/ubuntu/hoary')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numSubmissionsWithDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroseries=hoary_url).jsonBody()
+    ...     distroseries=hoary_url).jsonBody())
     {u'submissions_with_device': 1, u'all_submissions': 1}
     >>> warty_url = webservice.getAbsoluteUrl('/ubuntu/warty')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numSubmissionsWithDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroseries=warty_url).jsonBody()
+    ...     distroseries=warty_url).jsonBody())
     {u'submissions_with_device': 0, u'all_submissions': 0}
 
 ...or a distroarchseries.
 
     >>> hoary_i386_url = webservice.getAbsoluteUrl('/ubuntu/hoary/i386')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numSubmissionsWithDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroarchseries=hoary_i386_url).jsonBody()
+    ...     distroarchseries=hoary_i386_url).jsonBody())
     {u'submissions_with_device': 1, u'all_submissions': 1}
     >>> hoary_hppa_url = webservice.getAbsoluteUrl('/ubuntu/hoary/hppa')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numSubmissionsWithDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroarchseries=hoary_hppa_url).jsonBody()
+    ...     distroarchseries=hoary_hppa_url).jsonBody())
     {u'submissions_with_device': 0, u'all_submissions': 0}
 
 But at most one of the parameters distribution, distroseries,
 distroarchseries may be specified.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numSubmissionsWithDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distribution=ubuntu_url, distroseries=hoary_url)
+    ...     distribution=ubuntu_url, distroseries=hoary_url))
     ...
     HTTP/1.1 400 Bad Request
     ...
     Only one of `distribution`, `distroseries` or `distroarchseries` can
     be present.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numSubmissionsWithDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     distribution=ubuntu_url,
-    ...     distroarchseries=hoary_i386_url)
+    ...     distroarchseries=hoary_i386_url))
     ...
     HTTP/1.1 400 Bad Request
     ...
     Only one of `distribution`, `distroseries` or `distroarchseries` can
     be present.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numSubmissionsWithDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroseries=hoary_url, distroarchseries=hoary_i386_url
-    ...     )
+    ...     distroseries=hoary_url, distroarchseries=hoary_i386_url))
     HTTP/1.1 400 Bad Request
     ...
     Only one of `distribution`, `distroseries` or `distroarchseries` can
@@ -1170,123 +1169,122 @@
 the given distribution, distroseries or distroarchseries, if one
 of these parameters is specified.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numOwnersOfDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     '
-    ...     ).jsonBody()
+    ...     ).jsonBody())
     {u'owners': 1, u'all_submitters': 1}
 
-    >>> print webservice.named_get(
-    ...     '/+hwdb', 'numOwnersOfDevice', driver_name='sd').jsonBody()
+    >>> print(webservice.named_get(
+    ...     '/+hwdb', 'numOwnersOfDevice', driver_name='sd').jsonBody())
     {u'owners': 1, u'all_submitters': 1}
 
 A device and a driver can be specified simultaneously.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numOwnersOfDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='sd').jsonBody()
+    ...     driver_name='sd').jsonBody())
     {u'owners': 1, u'all_submitters': 1}
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numOwnersOfDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     driver_name='nonsense').jsonBody()
+    ...     driver_name='nonsense').jsonBody())
     {u'owners': 0, u'all_submitters': 1}
 
 Specifying neiher a device nor a driver leads to an error.
 
-    >>> print webservice.named_get('/+hwdb', 'numOwnersOfDevice')
+    >>> print(webservice.named_get('/+hwdb', 'numOwnersOfDevice'))
     HTTP/1.1 400 Bad Request
     ...
     Specify (bus, vendor_id, product_id) or driver_name.
 
 Additionally, a package_name can be passed...
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numOwnersOfDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     package_name='linux-image-2.6.24-19-generic').jsonBody()
+    ...     package_name='linux-image-2.6.24-19-generic').jsonBody())
     {u'owners': 1, u'all_submitters': 1}
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numOwnersOfDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     package_name='nonsense').jsonBody()
+    ...     package_name='nonsense').jsonBody())
     {u'owners': 0, u'all_submitters': 1}
 
 ...a reference to a distribution...
 
     >>> ubuntu_url = webservice.getAbsoluteUrl('/ubuntu')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numOwnersOfDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distribution=ubuntu_url).jsonBody()
+    ...     distribution=ubuntu_url).jsonBody())
     {u'owners': 1, u'all_submitters': 1}
     >>> debian_url = webservice.getAbsoluteUrl('/debian')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numOwnersOfDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distribution=debian_url).jsonBody()
+    ...     distribution=debian_url).jsonBody())
     {u'owners': 0, u'all_submitters': 0}
 
 ...a reference to a distroseries...
 
     >>> hoary_url = webservice.getAbsoluteUrl('/ubuntu/hoary')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numOwnersOfDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroseries=hoary_url).jsonBody()
+    ...     distroseries=hoary_url).jsonBody())
     {u'owners': 1, u'all_submitters': 1}
     >>> warty_url = webservice.getAbsoluteUrl('/ubuntu/warty')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numOwnersOfDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroseries=warty_url).jsonBody()
+    ...     distroseries=warty_url).jsonBody())
     {u'owners': 0, u'all_submitters': 0}
 
 ...or a reference to a distroarchseries.
 
     >>> hoary_i386_url = webservice.getAbsoluteUrl('/ubuntu/hoary/i386')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numOwnersOfDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroarchseries=hoary_i386_url).jsonBody()
+    ...     distroarchseries=hoary_i386_url).jsonBody())
     {u'owners': 1, u'all_submitters': 1}
     >>> hoary_hppa_url = webservice.getAbsoluteUrl('/ubuntu/hoary/hppa')
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numOwnersOfDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroarchseries=hoary_hppa_url).jsonBody()
+    ...     distroarchseries=hoary_hppa_url).jsonBody())
     {u'owners': 0, u'all_submitters': 0}
 
 But at most one of the parameters distribution, distroseries,
 distroarchseries may be specified.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numOwnersOfDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distribution=ubuntu_url, distroseries=hoary_url)
+    ...     distribution=ubuntu_url, distroseries=hoary_url))
     ...
     HTTP/1.1 400 Bad Request
     ...
     Only one of `distribution`, `distroseries` or `distroarchseries` can
     be present.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numOwnersOfDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     distribution=ubuntu_url,
-    ...     distroarchseries=hoary_i386_url)
+    ...     distroarchseries=hoary_i386_url))
     ...
     HTTP/1.1 400 Bad Request
     ...
     Only one of `distribution`, `distroseries` or `distroarchseries` can
     be present.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'numOwnersOfDevice',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
-    ...     distroseries=hoary_url, distroarchseries=hoary_i386_url
-    ...     )
+    ...     distroseries=hoary_url, distroarchseries=hoary_i386_url))
     HTTP/1.1 400 Bad Request
     ...
     Only one of `distribution`, `distroseries` or `distroarchseries` can
@@ -1305,7 +1303,7 @@
     ...     '/+hwdb', 'deviceDriverOwnersAffectedByBugs',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[1]).jsonBody()['entries']:
-    ...     print person['display_name']
+    ...     print(person['display_name'])
     Sample Person
 
 We can additionally ask for bugsubscribers...
@@ -1314,7 +1312,7 @@
     ...     '/+hwdb', 'deviceDriverOwnersAffectedByBugs',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[9], subscribed_to_bug=True).jsonBody()['entries']:
-    ...     print person['display_name']
+    ...     print(person['display_name'])
     Sample Person
 
 or users affected by a bug.
@@ -1335,7 +1333,7 @@
     ...     '/+hwdb', 'deviceDriverOwnersAffectedByBugs',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[15], affected_by_bug=True).jsonBody()['entries']:
-    ...     print person['display_name']
+    ...     print(person['display_name'])
     Sample Person
 
 We can limit the search to a driver...
@@ -1344,14 +1342,14 @@
     ...     '/+hwdb', 'deviceDriverOwnersAffectedByBugs',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[1], driver_name='sd').jsonBody()['entries']:
-    ...     print person['display_name']
+    ...     print(person['display_name'])
     Sample Person
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'deviceDriverOwnersAffectedByBugs',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[9], driver_name='nonsense', subscribed_to_bug=True
-    ...     ).jsonBody()['total_size']
+    ...     ).jsonBody()['total_size'])
     0
 
 ...or a package name.
@@ -1361,14 +1359,14 @@
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[1], package_name='linux-image-2.6.24-19-generic'
     ...     ).jsonBody()['entries']:
-    ...     print person['display_name']
+    ...     print(person['display_name'])
     Sample Person
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'deviceDriverOwnersAffectedByBugs',
     ...     bus='IDE', vendor_id='SEAGATE', product_id='ST3250820NS     ',
     ...     bug_ids=[9], package_name='nonsense', subscribed_to_bug=True
-    ...     ).jsonBody()['total_size']
+    ...     ).jsonBody()['total_size'])
     0
 
 And we can search for people using a given driver and being affected by
@@ -1377,18 +1375,18 @@
     >>> for person in webservice.named_get(
     ...     '/+hwdb', 'deviceDriverOwnersAffectedByBugs',
     ...     driver_name='sd', bug_ids=[1]).jsonBody()['entries']:
-    ...     print person['display_name']
+    ...     print(person['display_name'])
     Sample Person
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'deviceDriverOwnersAffectedByBugs',
-    ...     driver_name='nonsense', bug_ids=[1]).jsonBody()['total_size']
+    ...     driver_name='nonsense', bug_ids=[1]).jsonBody()['total_size'])
     0
 
 A 400 error is returned, if neither a device nor a driver name is specified.
 
-    >>> print webservice.named_get(
-    ...     '/+hwdb', 'deviceDriverOwnersAffectedByBugs', bug_ids=[1])
+    >>> print(webservice.named_get(
+    ...     '/+hwdb', 'deviceDriverOwnersAffectedByBugs', bug_ids=[1]))
     HTTP/1.1 400 Bad Request
     ...
     Specify (bus, vendor_id, product_id) or driver_name.
@@ -1396,9 +1394,9 @@
 If one of the parameters bus, vendor_id, product_id is specified, all of
 them have to be specified.
 
-    >>> print webservice.named_get(
+    >>> print(webservice.named_get(
     ...     '/+hwdb', 'deviceDriverOwnersAffectedByBugs',
-    ...     bus='IDE', bug_ids=[1])
+    ...     bus='IDE', bug_ids=[1]))
     HTTP/1.1 400 Bad Request
     ...
     Either specify bus, vendor_id and product_id or none of them.
@@ -1409,7 +1407,7 @@
     >>> for entry in webservice.named_get(
     ...     '/+hwdb', 'hwInfoByBugRelatedUsers',
     ...     bug_ids=[1]).jsonBody():
-    ...     print entry
+    ...     print(entry)
     [u'name12', u'IDE', u'Optiarc', u'DVD RW AD-7170S ']
     [u'name12', u'IDE', u'SEAGATE', u'ST3250820NS     ']
     [u'name12', u'PCI', u'0x10de', u'0x0455']
@@ -1424,7 +1422,7 @@
     >>> for entry in webservice.named_get(
     ...     '/+hwdb', 'hwInfoByBugRelatedUsers',
     ...     bug_ids=[9], subscribed_to_bug=True).jsonBody():
-    ...     print entry
+    ...     print(entry)
     [u'name12', u'IDE', u'Optiarc', u'DVD RW AD-7170S ']
     [u'name12', u'IDE', u'SEAGATE', u'ST3250820NS     ']
     [u'name12', u'PCI', u'0x10de', u'0x0455']
@@ -1438,7 +1436,7 @@
     >>> for entry in webservice.named_get(
     ...     '/+hwdb', 'hwInfoByBugRelatedUsers',
     ...     bug_ids=[15], affected_by_bug=True).jsonBody():
-    ...     print entry
+    ...     print(entry)
     [u'name12', u'IDE', u'Optiarc', u'DVD RW AD-7170S ']
     [u'name12', u'IDE', u'SEAGATE', u'ST3250820NS     ']
     [u'name12', u'PCI', u'0x10de', u'0x0455']

=== modified file 'lib/lp/hardwaredb/tests/test_doc.py'
--- lib/lp/hardwaredb/tests/test_doc.py	2012-01-20 15:42:44 +0000
+++ lib/lp/hardwaredb/tests/test_doc.py	2019-04-16 17:22:40 +0000
@@ -5,6 +5,8 @@
 Run the doctests and pagetests.
 """
 
+from __future__ import absolute_import, print_function, unicode_literals
+
 import os
 
 from lp.services.testing import build_test_suite
@@ -13,6 +15,7 @@
     LaunchpadFunctionalLayer,
     LaunchpadZopelessLayer,
     )
+from lp.testing.pages import setUpGlobs
 from lp.testing.systemdocs import (
     LayeredDocFileSuite,
     setUp,
@@ -24,7 +27,7 @@
 
 
 def hwdbDeviceTablesSetup(test):
-    setUp(test)
+    setUp(test, future=True)
     switch_dbuser('hwdb-submission-processor')
 
 
@@ -38,4 +41,7 @@
 
 
 def test_suite():
-    return build_test_suite(here, special, layer=LaunchpadFunctionalLayer)
+    return build_test_suite(
+        here, special, layer=LaunchpadFunctionalLayer,
+        setUp=lambda test: setUp(test, future=True),
+        pageTestsSetUp=lambda test: setUpGlobs(test, future=True))

=== modified file 'lib/lp/hardwaredb/tests/test_hwdb_submission_validation.py'
--- lib/lp/hardwaredb/tests/test_hwdb_submission_validation.py	2012-01-01 02:58:52 +0000
+++ lib/lp/hardwaredb/tests/test_hwdb_submission_validation.py	2019-04-16 17:22:40 +0000
@@ -3,6 +3,8 @@
 
 """Tests of the HWDB submissions parser."""
 
+from __future__ import absolute_import, print_function, unicode_literals
+
 from datetime import datetime
 import logging
 import os
@@ -36,6 +38,8 @@
             config.root, 'lib', 'lp', 'hardwaredb', 'scripts',
             'tests', 'hardwaretest.xml')
         self.sample_data = open(sample_data_path).read()
+        if isinstance(self.sample_data, bytes):
+            self.sample_data = self.sample_data.decode('UTF-8')
 
     def runValidator(self, sample_data):
         """Run the Relax NG validator.
@@ -44,6 +48,8 @@
         expected in a test is indeed created by this test.
         """
         self.submission_count += 1
+        if not isinstance(sample_data, bytes):
+            sample_data = sample_data.encode('UTF-8')
         submission_id = 'submission_%i' % self.submission_count
         result = SubmissionParser(self.log)._getValidatedEtree(sample_data,
                                                                submission_id)
@@ -165,7 +171,7 @@
             data=self.sample_data,
             replace_text='<?xml version="1.0" encoding="%s"?>' % encoding,
             from_text='<?xml',
-            to_text='?>')
+            to_text='?>').encode(encoding)
 
     def testAsciiEncoding(self):
         """Validation of ASCII encoded XML data.
@@ -182,8 +188,8 @@
         sample_data = self.replaceSampledata(
             data=sample_data_ascii_encoded,
             replace_text=tag_with_umlaut,
-            from_text='<architecture',
-            to_text='/>')
+            from_text=b'<architecture',
+            to_text=b'/>')
         result, submission_id = self.runValidator(sample_data)
         self.assertEqual(result, None,
                          'Invalid submission with ASCII encoding accepted')
@@ -196,12 +202,12 @@
     def testISO8859_1_Encoding(self):
         """XML data with ISO-8859-1 may have bytes with bit 7 set."""
         sample_data_iso_8859_1_encoded = self._setEncoding('ISO-8859-1')
-        tag_with_umlaut = '<architecture value="\xc4"/>'
+        tag_with_umlaut = b'<architecture value="\xc4"/>'
         sample_data = self.replaceSampledata(
             data=sample_data_iso_8859_1_encoded,
             replace_text=tag_with_umlaut,
-            from_text='<architecture',
-            to_text='/>')
+            from_text=b'<architecture',
+            to_text=b'/>')
         result, submission_id = self.runValidator(sample_data)
         self.assertNotEqual(result, None,
                             'Valid submission with ISO-8859-1 encoding '
@@ -211,24 +217,24 @@
         """UTF-8 encoded data is properly detected and parsed."""
         sample_data_utf8_encoded = self._setEncoding('UTF-8')
         umlaut = u'\xc4'.encode('utf8')
-        tag = '<architecture value="%s"/>'
+        tag = b'<architecture value="%s"/>'
         tag_with_valid_utf8 = tag % umlaut
         sample_data = self.replaceSampledata(
             data=sample_data_utf8_encoded,
             replace_text=tag_with_valid_utf8,
-            from_text='<architecture',
-            to_text='/>')
+            from_text=b'<architecture',
+            to_text=b'/>')
         result, submission_id = self.runValidator(sample_data)
         self.assertNotEqual(result, None,
                             'Valid submission with UTF-8 encoding rejected')
 
         # Broken UTF8 encoding is detected.
-        tag_with_broken_utf8 = tag % umlaut[0]
+        tag_with_broken_utf8 = tag % umlaut[:1]
         sample_data = self.replaceSampledata(
             data=tag_with_broken_utf8,
             replace_text=tag_with_broken_utf8,
-            from_text='<architecture',
-            to_text='/>')
+            from_text=b'<architecture',
+            to_text=b'/>')
         result, submission_id = self.runValidator(sample_data)
         self.assertEqual(result, None,
                          'Invalid submissison with UTF-8 encoding accepted')


Follow ups