← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:py3-services-print-function into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:py3-services-print-function into launchpad:master.

Commit message:
Convert the rest of lp.services to print_function

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/398840
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:py3-services-print-function into launchpad:master.
diff --git a/lib/lp/services/doc/collection.txt b/lib/lp/services/doc/collection.txt
index 87bf99f..5d2408c 100644
--- a/lib/lp/services/doc/collection.txt
+++ b/lib/lp/services/doc/collection.txt
@@ -42,12 +42,12 @@ yet until you invoke the "select" method, which returns a Storm result
 set.
 
     >>> collection = KumquatCollection()
-    >>> print list(collection.select().order_by(Kumquat.id))
+    >>> print(list(collection.select().order_by(Kumquat.id)))
     [Kumquat-1, Kumquat-2]
 
 Actually, select() is just shorthand for select(Kumquat).
 
-    >>> print list(collection.select(Kumquat).order_by(Kumquat.id))
+    >>> print(list(collection.select(Kumquat).order_by(Kumquat.id)))
     [Kumquat-1, Kumquat-2]
 
 You can also query individual columns.
diff --git a/lib/lp/services/doc/limitedlist.txt b/lib/lp/services/doc/limitedlist.txt
index 10f1fed..e8bdf08 100644
--- a/lib/lp/services/doc/limitedlist.txt
+++ b/lib/lp/services/doc/limitedlist.txt
@@ -22,7 +22,7 @@ We can optionally specify the initial content of the sequence. Note that
 only the last N elements of the second parameter are stored, where N is
 the given maximum size of the LimitedList.
 
-    >>> LimitedList(3, (0, 'one', 2, 3))
+    >>> LimitedList(3, (0, six.ensure_str('one'), 2, 3))
     <LimitedList(3, ['one', 2, 3])>
 
 If the initial content has more elements than the given maximum length,
diff --git a/lib/lp/services/doc/looptuner.txt b/lib/lp/services/doc/looptuner.txt
index 8c83471..56bb62b 100644
--- a/lib/lp/services/doc/looptuner.txt
+++ b/lib/lp/services/doc/looptuner.txt
@@ -52,7 +52,7 @@ architectures, compilers used for the Python interpreter, etc.
     >>> goal_seconds = 10.0
     >>> def print_change(last_chunk_size, new_chunk_size):
     ...     if last_chunk_size is None:
-    ...         print "start"
+    ...         print("start")
     ...         return
     ...     change = "same"
     ...     if new_chunk_size > last_chunk_size:
@@ -61,7 +61,7 @@ architectures, compilers used for the Python interpreter, etc.
     ...         change = "decreased"
     ...     ratio = new_chunk_size / last_chunk_size
     ...     order_of_magnitude = math.log10(ratio)
-    ...     print "%s (%.1f)" % (change, order_of_magnitude)
+    ...     print("%s (%.1f)" % (change, order_of_magnitude))
 
     >>> @implementer(ITunableLoop)
     ... class PlannedLoop:
@@ -74,7 +74,7 @@ architectures, compilers used for the Python interpreter, etc.
     ...     def isDone(self):
     ...         done = self.iteration >= len(self.timings)
     ...         if done:
-    ...             print "done"
+    ...             print("done")
     ...         return done
     ...
     ...     def __call__(self, chunk_size):
@@ -197,7 +197,7 @@ This variant of the LoopTuner simulates an overridable cost function:
     ...     def isDone(self):
     ...         done = (self.iteration >= self.counter)
     ...         if done:
-    ...             print "done"
+    ...             print("done")
     ...         return done
     ...
     ...     def __call__(self, chunk_size):
@@ -379,9 +379,9 @@ but still print out what would happen.
     >>> class CooldownTuner(LoopTuner):
     ...     def _coolDown(self, bedtime):
     ...         if self.cooldown_time is None or self.cooldown_time <= 0.0:
-    ...             print "No cooldown"
+    ...             print("No cooldown")
     ...         else:
-    ...             print "Cooldown for %.1f seconds." % self.cooldown_time
+    ...             print("Cooldown for %.1f seconds." % self.cooldown_time)
     ...         return bedtime
 
 SimpleLoop is a loop that does a constant number of iterations, regardless
@@ -397,11 +397,11 @@ of the actual run-time.
     ...     def isDone(self):
     ...         done = (self.iteration >= self.total_iterations)
     ...         if done:
-    ...             print "done"
+    ...             print("done")
     ...         return done
     ...
     ...     def __call__(self, chunk_size):
-    ...         print "Processing %d items." % (chunk_size)
+    ...         print("Processing %d items." % (chunk_size))
     ...         self.iteration += 1
 
 Aim for a low goal_seconds (to reduce test runtime), and only 3 iterations.
@@ -427,7 +427,7 @@ returns time after sleep is done.
     >>> cooldown_loop = LoopTuner(body, goal_seconds, cooldown_time=0.2)
     >>> old_time = time.time()
     >>> new_time = cooldown_loop._coolDown(old_time)
-    >>> print new_time > old_time
+    >>> print(new_time > old_time)
     True
 
 If no cooldown_time is specified, there's no sleep, and exactly the same
@@ -436,7 +436,7 @@ time is returned.
     >>> no_cooldown_loop = LoopTuner(body, goal_seconds, cooldown_time=None)
     >>> old_time = time.time()
     >>> new_time = no_cooldown_loop._coolDown(old_time)
-    >>> print new_time == old_time
+    >>> print(new_time == old_time)
     True
 
 == Abort Timeout ==
@@ -454,7 +454,7 @@ than this timeout, it is aborted and a INFO logged.
     start
     same (0.0)
     same (0.0)
-    >>> print logger.getLogBufferAndClear()
+    >>> print(logger.getLogBufferAndClear())
     INFO Task aborted after 20 seconds.
 
 
@@ -466,7 +466,7 @@ the isDone() method, and __del__ is fragile and can never be relied on.
 
     >>> class PlannedLoopWithCleanup(PlannedLoop):
     ...     def cleanUp(self):
-    ...         print 'clean up'
+    ...         print('clean up')
 
     >>> body = PlannedLoopWithCleanup([])
     >>> loop = TestTuner(body, goal_seconds, 100)
@@ -481,6 +481,6 @@ the isDone() method, and __del__ is fragile and can never be relied on.
     same (0.0)
     same (0.0)
     clean up
-    >>> print logger.getLogBufferAndClear()
+    >>> print(logger.getLogBufferAndClear())
     INFO Task aborted after 20 seconds.
 
diff --git a/lib/lp/services/doc/orderingcheck.txt b/lib/lp/services/doc/orderingcheck.txt
index fe9294f..209b6e0 100644
--- a/lib/lp/services/doc/orderingcheck.txt
+++ b/lib/lp/services/doc/orderingcheck.txt
@@ -75,7 +75,7 @@ ordering, override the "fail" method.
 
     >>> def alternative_fail(item):
     ...     """Don't raise an error, just print a message."""
-    ...     print "Item %s was out of sequence." % item
+    ...     print("Item %s was out of sequence." % item)
 
     >>> checker = OrderingCheck(key=sort_key)
     >>> checker.fail = alternative_fail
diff --git a/lib/lp/services/doc/pidfile.txt b/lib/lp/services/doc/pidfile.txt
index d0a1728..672d68c 100644
--- a/lib/lp/services/doc/pidfile.txt
+++ b/lib/lp/services/doc/pidfile.txt
@@ -32,8 +32,8 @@ You can pass in your own config instance to use.
     ...     class canonical:
     ...         pid_dir = '/var/tmp'
     ...     instance_name = 'blah'
-    >>> pidfile_path('beans', MyConfig)
-    '/var/tmp/blah-beans.pid'
+    >>> print(pidfile_path('beans', MyConfig))
+    /var/tmp/blah-beans.pid
 
 This basic mechanism supports the other three functions.
 
@@ -93,24 +93,24 @@ we'll need them again later.
     ...                 return real_pid
     ...         time.sleep(0.1)
     ...     else:
-    ...         print 'Error: pid file was not created'
+    ...         print('Error: pid file was not created')
     ...
     >>> def stop(pid, sig):
     ...     os.kill(pid, sig)
     ...     os.waitpid(pid, 0)
     ...     if not os.path.exists(pidfile_path('nuts')):
-    ...         print 'Stopped successfully'
+    ...         print('Stopped successfully')
     ...     else:
     ...         try:
     ...             # Is it still here at all?
     ...             os.kill(pid, 0)
     ...         except OSError as e:
     ...             if e.errno == errno.ESRCH:
-    ...                 print 'Error: pid file was not removed'
+    ...                 print('Error: pid file was not removed')
     ...             else:
     ...                 raise
     ...         else:
-    ...             print 'Error: process did not exit'
+    ...             print('Error: process did not exit')
     ...
 
 Here's our example.  We start, and then stop with SIGINT.
@@ -165,7 +165,7 @@ continuing as normal.
     True
     >>> stop(new_pid, signal.SIGTERM)
     Stopped successfully
-    >>> print get_pid('nuts')
+    >>> print(get_pid('nuts'))
     None
 
 
@@ -197,11 +197,11 @@ You can also pass in your own config instance.
     ...         pid_dir = '/var/tmp'
     ...     instance_name = 'blah'
     >>> path = pidfile_path('beans', MyConfig)
-    >>> path
-    '/var/tmp/blah-beans.pid'
+    >>> print(path)
+    /var/tmp/blah-beans.pid
     >>> file = open(path, 'w')
     >>> try:
-    ...     print >> file, 72
+    ...     print(72, file=file)
     ... finally:
     ...     file.close()
     >>> get_pid('beans', MyConfig)
@@ -218,7 +218,7 @@ if you are overriding the default SIGTERM signal handler.
     >>> path = pidfile_path('legumes')
     >>> file = open(path, 'w')
     >>> try:
-    ...     print >> file, os.getpid()
+    ...     print(os.getpid(), file=file)
     ... finally:
     ...     file.close()
     >>> remove_pidfile('legumes')
@@ -240,7 +240,7 @@ need to match the current process's pid.
 
     >>> file = open(path, 'w')
     >>> try:
-    ...     print >> file, os.getpid() + 1
+    ...     print(os.getpid() + 1, file=file)
     ... finally:
     ...     file.close()
     >>> remove_pidfile('pits', MyConfig)
diff --git a/lib/lp/services/doc/propertycache.txt b/lib/lp/services/doc/propertycache.txt
index 4930b01..d8af5ff 100644
--- a/lib/lp/services/doc/propertycache.txt
+++ b/lib/lp/services/doc/propertycache.txt
@@ -140,8 +140,8 @@ as "a_in_cache" in the cache.
 
     >>> isinstance(Foo.a, CachedProperty)
     True
-    >>> Foo.a.name
-    'a_in_cache'
+    >>> print(Foo.a.name)
+    a_in_cache
     >>> Foo.a.populate
     <function ...a at 0x...>
 
diff --git a/lib/lp/services/doc/sprites.txt b/lib/lp/services/doc/sprites.txt
index ccdfcea..8c8d692 100644
--- a/lib/lp/services/doc/sprites.txt
+++ b/lib/lp/services/doc/sprites.txt
@@ -75,7 +75,7 @@ is currently zero.
     >>> sprite_util.combineImages(icing)
     >>> sprite_util.savePNG(new_png_file.name)
     >>> image = Image.open(new_png_file.name)
-    >>> print image.size
+    >>> print(image.size)
     (14, 55)
 
 The height will increase when the margin is increased.
@@ -84,7 +84,7 @@ The height will increase when the margin is increased.
     >>> sprite_util.combineImages(icing)
     >>> sprite_util.savePNG(new_png_file.name)
     >>> image = Image.open(new_png_file.name)
-    >>> print image.size
+    >>> print(image.size)
     (14, 455)
 
 
@@ -96,7 +96,7 @@ image file. This allows the css file to be regenerated when the template
 changes without requiring the combined image file to be recreated.
 
     >>> sprite_util.savePositioning(new_positioning_file.name)
-    >>> print new_positioning_file.read()
+    >>> print(new_positioning_file.read())
     /*...
     {
         "../images/add.png": [
@@ -115,13 +115,13 @@ changes without requiring the combined image file to be recreated.
 
 The positions attribute can be cleared and loaded from the file.
 
-    >>> print pretty(sprite_util.positions)
+    >>> print(pretty(sprite_util.positions))
     {'../images/add.png': (0, -114),
      '../images/blue-bar.png': (0, -342),
      '../images/edit.png': (0, -228)}
     >>> sprite_util.positions = None
     >>> sprite_util.loadPositioning(new_positioning_file.name)
-    >>> print pretty(sprite_util.positions)
+    >>> print(pretty(sprite_util.positions))
     {'../images/add.png': [0, -114],
      '../images/blue-bar.png': [0, -342],
      '../images/edit.png': [0, -228]}
@@ -138,7 +138,7 @@ referenced /@@/add.png, which was only added once to the combined file.
 is not group1.png, since its sprite-ref is "group2".
 
     >>> sprite_util.saveConvertedCSS(new_css_file.name, 'group1.png')
-    >>> print new_css_file.read()
+    >>> print(new_css_file.read())
     /*...
     .add {
         background-image: url(group1.png);
diff --git a/lib/lp/services/doc/tarfile_helpers.txt b/lib/lp/services/doc/tarfile_helpers.txt
index 9748d38..59b809f 100644
--- a/lib/lp/services/doc/tarfile_helpers.txt
+++ b/lib/lp/services/doc/tarfile_helpers.txt
@@ -23,15 +23,15 @@ output we will get.
     ...             file = tar.extractfile(member)
     ...
     ...             if file is not None:
-    ...                 print format % (
-    ...                     member.name, six.ensure_text(file.read()))
+    ...                 print(format % (
+    ...                     member.name, six.ensure_text(file.read())))
     ...             else:
-    ...                 print format % (member.name, '')
+    ...                 print(format % (member.name, ''))
     ...         elif member.type == tarfile.SYMTYPE:
-    ...             print format % (
-    ...                 member.name, "<link to %s>" % member.linkname)
+    ...             print(format % (
+    ...                 member.name, "<link to %s>" % member.linkname))
     ...         elif member.type == tarfile.DIRTYPE:
-    ...             print format % (member.name, "<directory>")
+    ...             print(format % (member.name, "<directory>"))
 
     # Start off by creating a blank archive.
     # We'll need a filehandle to store it in.
diff --git a/lib/lp/services/features/__init__.py b/lib/lp/services/features/__init__.py
index 6604472..7ee4895 100644
--- a/lib/lp/services/features/__init__.py
+++ b/lib/lp/services/features/__init__.py
@@ -123,7 +123,7 @@ and if you want to use the value ::
 
      value = features.getFeatureFlag('example_flag.enabled')
      if value:
-        print value
+        print(value)
 
 Checking flags without access to the database
 =============================================
diff --git a/lib/lp/services/fields/doc/uri-field.txt b/lib/lp/services/fields/doc/uri-field.txt
index f4c9c00..bd8ff8c 100644
--- a/lib/lp/services/fields/doc/uri-field.txt
+++ b/lib/lp/services/fields/doc/uri-field.txt
@@ -170,7 +170,7 @@ URIs with an authority but a blank path get canonicalised to a path of
 None is an acceptable value for a URI field.
 
   >>> field = URIField(__name__='foo', title=u'Foo')
-  >>> print field.normalize(None)
+  >>> print(field.normalize(None))
   None
 
 
@@ -196,7 +196,7 @@ This widget is registered as an input widget:
   >>> field = IURIFieldTest['field'].bind(context)
   >>> request = LaunchpadTestRequest()
   >>> widget = getMultiAdapter((field, request), IInputWidget)
-  >>> print widget
+  >>> print(widget)
   <lp.app.widgets.textwidgets.URIWidget object at ...>
 
 Multiple values will cause an UnexpectedFormData exception:
diff --git a/lib/lp/services/job/celeryconfig.py b/lib/lp/services/job/celeryconfig.py
index b830826..dcc931e 100644
--- a/lib/lp/services/job/celeryconfig.py
+++ b/lib/lp/services/job/celeryconfig.py
@@ -1,6 +1,8 @@
 # Copyright 2012-2019 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
+from __future__ import absolute_import, print_function
+
 from datetime import timedelta
 import sys
 
@@ -118,5 +120,5 @@ def configure(argv):
 try:
     globals().update(configure(getattr(sys, 'argv', [''])))
 except ConfigurationError as error:
-    print >>sys.stderr, error
+    print(error, file=sys.stderr)
     sys.exit(1)
diff --git a/lib/lp/services/librarianserver/tests/test_doc.py b/lib/lp/services/librarianserver/tests/test_doc.py
index 6a9ed9c..613acf3 100644
--- a/lib/lp/services/librarianserver/tests/test_doc.py
+++ b/lib/lp/services/librarianserver/tests/test_doc.py
@@ -150,4 +150,5 @@ special = {
 
 
 def test_suite():
-    return build_test_suite(here, special)
+    return build_test_suite(
+        here, special, setUp=lambda test: setUp(future=True))
diff --git a/lib/lp/services/sitesearch/tests/data/blog.launchpad.net-feed.xml b/lib/lp/services/sitesearch/tests/data/blog.launchpad.net-feed.xml
index 562dd87..93dd442 100644
--- a/lib/lp/services/sitesearch/tests/data/blog.launchpad.net-feed.xml
+++ b/lib/lp/services/sitesearch/tests/data/blog.launchpad.net-feed.xml
@@ -65,13 +65,13 @@
 <p>Don&#8217;t do this:</p>
 <pre>
     if bug.person is not None:
-        print bug.person.name
+        print(bug.person.name)
 </pre>
 <p>instead</p>
 <pre>
     p = bug.person
     if p is not None:
-        print p.name
+        print(p.name)
 </pre>
 <p>In the first case, the client may fetch the Person object twice.  (We may fix this in future.)</p>
 ]]></content:encoded>
diff --git a/lib/lp/services/spriteutils.py b/lib/lp/services/spriteutils.py
index 21ccddb..826e36a 100644
--- a/lib/lp/services/spriteutils.py
+++ b/lib/lp/services/spriteutils.py
@@ -6,6 +6,8 @@
 
 """Library to create sprites."""
 
+from __future__ import absolute_import, print_function
+
 __metaclass__ = type
 
 __all__ = [
@@ -160,8 +162,10 @@ class SpriteUtil:
             try:
                 sprite_images[sprite['filename']] = Image.open(abs_filename)
             except IOError:
-                print >> sys.stderr, "Error opening '%s' for %s css rule" % (
-                    abs_filename, sprite['rule'].selectorText)
+                print(
+                    "Error opening '%s' for %s css rule" % (
+                        abs_filename, sprite['rule'].selectorText),
+                    file=sys.stderr)
                 raise
             width, height = sprite_images[sprite['filename']].size
             max_sprite_width = max(width, max_sprite_width)
@@ -194,8 +198,9 @@ class SpriteUtil:
                         position[0] = x_position
                         combined_image.paste(sprite_image, tuple(position))
             except:
-                print >> sys.stderr, (
-                    "Error with image file %s" % sprite['filename'])
+                print(
+                    "Error with image file %s" % sprite['filename'],
+                    file=sys.stderr)
                 raise
             # This is the position of the combined image on an HTML
             # element. Therefore, it subtracts the position of the
diff --git a/lib/lp/services/tests/test_doc.py b/lib/lp/services/tests/test_doc.py
index 5a4a7a1..d15b126 100644
--- a/lib/lp/services/tests/test_doc.py
+++ b/lib/lp/services/tests/test_doc.py
@@ -9,7 +9,11 @@ import os
 
 from lp.services.testing import build_test_suite
 from lp.testing.layers import BaseLayer
-from lp.testing.systemdocs import LayeredDocFileSuite
+from lp.testing.systemdocs import (
+    LayeredDocFileSuite,
+    setGlobs,
+    setUp,
+    )
 
 
 here = os.path.dirname(os.path.realpath(__file__))
@@ -18,12 +22,15 @@ here = os.path.dirname(os.path.realpath(__file__))
 special = {
     'limitedlist.txt': LayeredDocFileSuite(
         '../doc/limitedlist.txt',
+        setUp=lambda test: setGlobs(test, future=True),
         layer=BaseLayer),
     'propertycache.txt': LayeredDocFileSuite(
         '../doc/propertycache.txt',
+        setUp=lambda test: setGlobs(test, future=True),
         layer=BaseLayer),
     }
 
 
 def test_suite():
-    return build_test_suite(here, special)
+    return build_test_suite(
+        here, special, setUp=lambda test: setUp(test, future=True))
diff --git a/lib/lp/services/tests/test_helpers.py b/lib/lp/services/tests/test_helpers.py
index 4a1aa84..b0383dc 100644
--- a/lib/lp/services/tests/test_helpers.py
+++ b/lib/lp/services/tests/test_helpers.py
@@ -1,6 +1,8 @@
 # Copyright 2009-2018 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
+from __future__ import absolute_import, print_function
+
 from doctest import DocTestSuite
 from textwrap import dedent
 import unittest
diff --git a/lib/lp/services/webservice/tests/test_wadllib.py b/lib/lp/services/webservice/tests/test_wadllib.py
index 10a7238..07134b4 100644
--- a/lib/lp/services/webservice/tests/test_wadllib.py
+++ b/lib/lp/services/webservice/tests/test_wadllib.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import, print_function
 __metaclass__ = type
 __all__ = ['test_suite']
 
-
+import __future__
 import os
 import unittest
 
@@ -23,7 +23,7 @@ topdir = os.path.dirname(wadllib.__file__)
 
 def setUp(test):
     for future_item in 'absolute_import', 'print_function':
-        test.globs[future_item] = getattr(globals(), future_item)
+        test.globs[future_item] = getattr(__future__, future_item)
 
 
 def test_suite():
diff --git a/utilities/lsconf.py b/utilities/lsconf.py
index c6306d7..8eab198 100755
--- a/utilities/lsconf.py
+++ b/utilities/lsconf.py
@@ -82,7 +82,7 @@ class Configuration:
                 continue
             if count > 0:
                 # Separate sections by a blank line, or two when verbose.
-                print
+                print()
             print('[%s]' % section.name)
             if verbose and section.optional:
                 print('# This section is optional.\n')