← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:services-webservice-future-imports into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:services-webservice-future-imports into launchpad:master.

Commit message:
Convert lp.services.webservice to preferred __future__ imports

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/391159
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:services-webservice-future-imports into launchpad:master.
diff --git a/lib/lp/services/webservice/doc/webservice-marshallers.txt b/lib/lp/services/webservice/doc/webservice-marshallers.txt
index 765bf45..17cfa94 100644
--- a/lib/lp/services/webservice/doc/webservice-marshallers.txt
+++ b/lib/lp/services/webservice/doc/webservice-marshallers.txt
@@ -84,8 +84,8 @@ This marshaller also appends '_link' to the representation name of
 this field, so that clients can know this is a link to another
 resource and not a random string.
 
-    >>> marshaller.representation_name
-    'some_person_link'
+    >>> print(marshaller.representation_name)
+    some_person_link
 
 If you export a Choice that uses an SQLObjectVocabularyBase then you
 get an error, as you should be using a ReferenceChoice instead to
diff --git a/lib/lp/services/webservice/stories/apidoc.txt b/lib/lp/services/webservice/stories/apidoc.txt
index 176071c..f6b62da 100644
--- a/lib/lp/services/webservice/stories/apidoc.txt
+++ b/lib/lp/services/webservice/stories/apidoc.txt
@@ -5,7 +5,7 @@ http://launchpad.test/+apidoc. It contains summaries of the different
 web service versions, and links to version-specific documents.
 
     >>> browser.open('http://launchpad.test/+apidoc')
-    >>> print extract_text(browser.contents)
+    >>> print(extract_text(browser.contents))
     Launchpad Web Service API
     ...
     Launchpad web service API documentation
@@ -19,6 +19,6 @@ The documentation for a specific version is located at
 http://launchpad.test/+apidoc/{version}.html.
 
     >>> browser.open('http://launchpad.test/+apidoc/devel.html')
-    >>> print browser.title
+    >>> print(browser.title)
     About this service
 
diff --git a/lib/lp/services/webservice/stories/conditional-write.txt b/lib/lp/services/webservice/stories/conditional-write.txt
index 8b25b26..44502fd 100644
--- a/lib/lp/services/webservice/stories/conditional-write.txt
+++ b/lib/lp/services/webservice/stories/conditional-write.txt
@@ -17,8 +17,8 @@ Here's a bug: it has an ETag and values for fields like
 When we add a message to a bug, 'date_last_message' is changed as a
 side effect.
 
-  >>> print webservice.named_post(
-  ...     url, 'newMessage', subject="subject", content="content")
+  >>> print(webservice.named_post(
+  ...     url, 'newMessage', subject="subject", content="content"))
   HTTP/1.1 201 Created
   ...
 
@@ -37,7 +37,7 @@ changed:
 A conditional GET request using the old ETag will fail, and the client
 will hear about the new value for 'date_last_message'.
 
-  >>> print webservice.get(url, headers={'If-None-Match' : old_etag})
+  >>> print(webservice.get(url, headers={'If-None-Match' : old_etag}))
   HTTP/1.1 200 Ok
   ...
 
@@ -70,7 +70,7 @@ conditional write will succeed.
   >>> import simplejson
   >>> data = simplejson.dumps({'title' : 'New title'})
   >>> headers = {'If-Match': old_etag}
-  >>> print webservice.patch(url, 'application/json', data, headers=headers)
+  >>> print(webservice.patch(url, 'application/json', data, headers=headers))
   HTTP/1.1 209 Content Returned
   ...
 
@@ -93,7 +93,7 @@ A conditional write will fail when the write portion of the submitted
 ETag doesn't match, even if the read portion matches.
 
   >>> headers = {'If-Match': new_etag}
-  >>> print webservice.patch(url, 'application/json', data, headers=headers)
+  >>> print(webservice.patch(url, 'application/json', data, headers=headers))
   HTTP/1.1 412 Precondition Failed
   ...
 
@@ -114,7 +114,7 @@ modified by mod_compress as though it were the original ETag.
   >>> etag = webservice.get(url).jsonBody()['http_etag']
 
   >>> headers = {'If-None-Match': etag}
-  >>> print webservice.get(url, headers=headers)
+  >>> print(webservice.get(url, headers=headers))
   HTTP/1.1 304 Not Modified
   ...
 
@@ -122,18 +122,18 @@ Some versions of mod_compress turn '"foo"' into '"foo"-gzip', and some
 versions turn it into '"foo-gzip"'. We treat all three forms the same.
 
   >>> headers = {'If-None-Match': etag + "-gzip"}
-  >>> print webservice.get(url, headers=headers)
+  >>> print(webservice.get(url, headers=headers))
   HTTP/1.1 304 Not Modified
   ...
 
   >>> headers = {'If-None-Match': etag[:-1] + "-gzip" + etag[-1]}
-  >>> print webservice.get(url, headers=headers)
+  >>> print(webservice.get(url, headers=headers))
   HTTP/1.1 304 Not Modified
   ...
 
 Any other modification to the ETag is treated as a distinct ETag.
 
   >>> headers = {'If-None-Match': etag + "-not-gzip"}
-  >>> print webservice.get(url, headers=headers)
+  >>> print(webservice.get(url, headers=headers))
   HTTP/1.1 200 Ok
   ...
diff --git a/lib/lp/services/webservice/stories/datamodel.txt b/lib/lp/services/webservice/stories/datamodel.txt
index 796c545..f47d6c3 100644
--- a/lib/lp/services/webservice/stories/datamodel.txt
+++ b/lib/lp/services/webservice/stories/datamodel.txt
@@ -19,9 +19,9 @@ Normally, the total size of a collection is not served along with the
 collection; it's available by following the total_size_link.
 
   >>> collection = get_collection()
-  >>> print sorted(collection.keys())
+  >>> print(sorted(collection.keys()))
   [u'entries', u'next_collection_link', u'start', u'total_size_link']
-  >>> print webservice.get(collection['total_size_link']).jsonBody()
+  >>> print(webservice.get(collection['total_size_link']).jsonBody())
   9
 
 If an entire collection fits on one page (making the size of the
@@ -29,9 +29,9 @@ collection obvious), 'total_size' is served instead of
 'total_size_link'.
 
   >>> collection = get_collection(size=100)
-  >>> print sorted(collection.keys())
+  >>> print(sorted(collection.keys()))
   [u'entries', u'start', u'total_size']
-  >>> print collection['total_size']
+  >>> print(collection['total_size'])
   9
 
 If the last page of the collection is fetched (making the total size
@@ -39,7 +39,7 @@ of the collection semi-obvious), 'total_size' is served instead of
 'total_size_link'.
 
   >>> collection = get_collection(start=8)
-  >>> print sorted(collection.keys())
+  >>> print(sorted(collection.keys()))
   [u'entries', u'prev_collection_link', u'start', u'total_size']
-  >>> print collection['total_size']
+  >>> print(collection['total_size'])
   9
diff --git a/lib/lp/services/webservice/stories/launchpadlib.txt b/lib/lp/services/webservice/stories/launchpadlib.txt
index 50c25b4..5a79f52 100644
--- a/lib/lp/services/webservice/stories/launchpadlib.txt
+++ b/lib/lp/services/webservice/stories/launchpadlib.txt
@@ -20,7 +20,7 @@ Launchpad object for a given user with a single call.
 
     >>> launchpad = launchpadlib_for(
     ...     u'launchpadlib test', 'salgado', 'WRITE_PUBLIC')
-    >>> print launchpad.me.name
+    >>> print(launchpad.me.name)
     salgado
 
     # XXX leonardr 2010-03-31 bug=552732
@@ -35,7 +35,7 @@ Launchpad object for a given user with a single call.
     #>>> launchpad = launchpadlib_for(
     #...     u'launchpadlib test', 'no-priv', 'READ_PRIVATE', 'firefox',
     #...     version="devel")
-    #>>> print launchpad.projects['firefox'].name
+    #>>> print(launchpad.projects['firefox'].name)
     #firefox
 
 With launchpadlib_credentials_for() you can get a launchpadlib
@@ -47,9 +47,9 @@ Credentials object.
     >>> credentials
     <launchpadlib.credentials.Credentials object ...>
 
-    >>> print credentials.consumer.key
+    >>> print(credentials.consumer.key)
     launchpadlib test
-    >>> print credentials.access_token
+    >>> print(credentials.access_token)
     oauth_token_secret=...&oauth_token=...
 
 This can be used to create your own Launchpad object.  Note you cannot
@@ -59,7 +59,7 @@ scheme which does not work in the test environment.
     >>> from launchpadlib.launchpad import Launchpad
     >>> launchpad = Launchpad(
     ...     credentials, None, None, 'http://api.launchpad.test/')
-    >>> print launchpad.me.name
+    >>> print(launchpad.me.name)
     no-priv
 
 Anonymous access
@@ -72,13 +72,13 @@ The Launchpad object for the anonymous user can be used to access
 public information.
 
     >>> apache_results = lp_anon.project_groups.search(text="Apache")
-    >>> print apache_results[0].name
+    >>> print(apache_results[0].name)
     apache
 
 But trying to access information that requires a logged in user
 results in an error.
 
-    >>> print lp_anon.me.name
+    >>> print(lp_anon.me.name)
     Traceback (most recent call last):
       ...
     Unauthorized: HTTP Error 401: Unauthorized...
diff --git a/lib/lp/services/webservice/stories/multiversion.txt b/lib/lp/services/webservice/stories/multiversion.txt
index 7f90181..bc4f855 100644
--- a/lib/lp/services/webservice/stories/multiversion.txt
+++ b/lib/lp/services/webservice/stories/multiversion.txt
@@ -17,18 +17,18 @@ total size of the collection.
   ...     return collection.jsonBody()
 
   >>> collection = get_collection("devel")
-  >>> print sorted(collection.keys())
+  >>> print(sorted(collection.keys()))
   [u'entries', u'next_collection_link', u'start', u'total_size_link']
-  >>> print webservice.get(collection['total_size_link']).jsonBody()
+  >>> print(webservice.get(collection['total_size_link']).jsonBody())
   9
 
 In previous versions, the same named operations will return a
 'total_size' containing the actual size of the collection.
 
   >>> collection = get_collection("1.0")
-  >>> print sorted(collection.keys())
+  >>> print(sorted(collection.keys()))
   [u'entries', u'next_collection_link', u'start', u'total_size']
-  >>> print collection['total_size']
+  >>> print(collection['total_size'])
   9
 
 Mutator operations
@@ -49,17 +49,17 @@ subsequent versions, those named operations are not published.
 Here's the 'beta' version, where the named operation works.
 
   >>> url = get_bugtask_path('beta')
-  >>> print webservice.named_post(
+  >>> print(webservice.named_post(
   ...     url, 'transitionToImportance', importance='Low',
-  ...     api_version='beta')
+  ...     api_version='beta'))
   HTTP/1.1 200 Ok
   ...
 
 Now let's try the same thing in the '1.0' version, where it fails.
 
   >>> url = get_bugtask_path('1.0')
-  >>> print webservice.named_post(
+  >>> print(webservice.named_post(
   ...     url, 'transitionToImportance', importance='Low',
-  ...     api_version='devel')
+  ...     api_version='devel'))
   HTTP/1.1 405 Method Not Allowed
   ...
diff --git a/lib/lp/services/webservice/stories/root.txt b/lib/lp/services/webservice/stories/root.txt
index 7ba36bc..aebe90f 100644
--- a/lib/lp/services/webservice/stories/root.txt
+++ b/lib/lp/services/webservice/stories/root.txt
@@ -5,7 +5,7 @@ special entry: the user account of the authenticated user. To avoid
 confusion when one program runs as different users, this is
 implemented as a redirect to that person's canonical URL.
 
-  >>> print webservice.get('/people/+me')
+  >>> print(webservice.get('/people/+me'))
   HTTP/1.1 303 See Other
   ...
   Location: http://.../~salgado
diff --git a/lib/lp/services/webservice/stories/security.txt b/lib/lp/services/webservice/stories/security.txt
index fa31fe2..77c09ea 100644
--- a/lib/lp/services/webservice/stories/security.txt
+++ b/lib/lp/services/webservice/stories/security.txt
@@ -21,7 +21,7 @@ Jokosher project.
 
 But the 'no-priv' user can't see bug number 14, which is private.
 
-  >>> print user_webservice.get("/bugs/14")
+  >>> print(user_webservice.get("/bugs/14"))
   HTTP/1.1 404 Not Found
   ...
 
@@ -35,7 +35,7 @@ Things are a little different for a user who has permission to see
 private data, but is using an OAuth key that restricts the client to
 operating on public data.
 
-  >>> print public_webservice.get("/bugs/14")
+  >>> print(public_webservice.get("/bugs/14"))
   HTTP/1.1 404 Not Found
   ...
 
diff --git a/lib/lp/services/webservice/stories/xx-hostedfile.txt b/lib/lp/services/webservice/stories/xx-hostedfile.txt
index e792c62..bda79d6 100644
--- a/lib/lp/services/webservice/stories/xx-hostedfile.txt
+++ b/lib/lp/services/webservice/stories/xx-hostedfile.txt
@@ -19,13 +19,13 @@ Firefox starts out with a link to branding images, but no actual images.
     >>> project['brand_link']
     u'http://.../firefox/brand'
 
-    >>> print webservice.get(project['icon_link'])
+    >>> print(webservice.get(project['icon_link']))
     HTTP/1.1 404 Not Found
     ...
-    >>> print webservice.get(project['logo_link'])
+    >>> print(webservice.get(project['logo_link']))
     HTTP/1.1 404 Not Found
     ...
-    >>> print webservice.get(project['brand_link'])
+    >>> print(webservice.get(project['brand_link']))
     HTTP/1.1 404 Not Found
     ...
 
@@ -39,16 +39,16 @@ We can upload branding images with PUT.
     ...         'images', filename)
     ...     return open(image_file).read()
 
-    >>> print webservice.put(project['icon_link'], 'image/png',
-    ...                      load_image('team.png'))
+    >>> print(webservice.put(project['icon_link'], 'image/png',
+    ...                      load_image('team.png')))
     HTTP/1.1 200 Ok
     ...
-    >>> print webservice.put(project['logo_link'], 'image/png',
-    ...                      load_image('team-logo.png'))
+    >>> print(webservice.put(project['logo_link'], 'image/png',
+    ...                      load_image('team-logo.png')))
     HTTP/1.1 200 Ok
     ...
-    >>> print webservice.put(project['brand_link'], 'image/png',
-    ...                      load_image('team-mugshot.png'))
+    >>> print(webservice.put(project['brand_link'], 'image/png',
+    ...                      load_image('team-mugshot.png')))
     HTTP/1.1 200 Ok
     ...
 
@@ -56,21 +56,21 @@ The project's branding links now redirects you to files maintained
 by the librarian.
 
     >>> result = webservice.get(project['icon_link'])
-    >>> print result
+    >>> print(result)
     HTTP/1.1 303 See Other
     ...
     Location: http://.../icon
     ...
 
     >>> result = webservice.get(project['logo_link'])
-    >>> print result
+    >>> print(result)
     HTTP/1.1 303 See Other
     ...
     Location: http://.../logo
     ...
 
     >>> result = webservice.get(project['brand_link'])
-    >>> print result
+    >>> print(result)
     HTTP/1.1 303 See Other
     ...
     Location: http://.../brand
@@ -83,8 +83,8 @@ Error handling
 Launchpad's ImageUpload classes enforce restrictions on uploaded
 images. You can't upload an image that's the wrong type.
 
-    >>> print webservice.put(
-    ...     project['brand_link'], 'image/png', 'Not an image')
+    >>> print(webservice.put(
+    ...     project['brand_link'], 'image/png', 'Not an image'))
     HTTP/1.1 400 Bad Request
     ...
     The file uploaded was not recognized as an image; please check it
@@ -92,8 +92,8 @@ images. You can't upload an image that's the wrong type.
 
 You also can't upload an image that's the wrong size.
 
-    >>> print webservice.put(project['brand_link'], 'image/png',
-    ...                      load_image('team-logo.png'))
+    >>> print(webservice.put(project['brand_link'], 'image/png',
+    ...                      load_image('team-logo.png')))
     HTTP/1.1 400 Bad Request
     ...
     This image is not exactly 192x192 pixels in size.
diff --git a/lib/lp/services/webservice/stories/xx-service.txt b/lib/lp/services/webservice/stories/xx-service.txt
index 24c7931..92e31f5 100644
--- a/lib/lp/services/webservice/stories/xx-service.txt
+++ b/lib/lp/services/webservice/stories/xx-service.txt
@@ -13,7 +13,7 @@ The Launchpad web service defines three versions: 'beta', '1.0', and
 
     >>> def me_link_for_version(version):
     ...     response = webservice.get("/", api_version=version)
-    ...     print response.jsonBody()['me_link']
+    ...     print(response.jsonBody()['me_link'])
 
     >>> me_link_for_version('beta')
     http://api.launchpad.test/beta/people/+me
@@ -26,7 +26,7 @@ The Launchpad web service defines three versions: 'beta', '1.0', and
 
 No other versions are available.
 
-    >>> print webservice.get("/", api_version="nosuchversion")
+    >>> print(webservice.get("/", api_version="nosuchversion"))
     HTTP/1.1 404 Not Found
     ...
 
@@ -39,9 +39,9 @@ is treated as an anonymous request.
 
     >>> root = 'http://api.launchpad.test/beta'
     >>> body = anon_webservice.get(root).jsonBody()
-    >>> print body['projects_collection_link']
+    >>> print(body['projects_collection_link'])
     http://api.launchpad.test/beta/projects
-    >>> print body['me_link']
+    >>> print(body['me_link'])
     http://api.launchpad.test/beta/people/+me
 
 Normally, Launchpad will reject any call made with an unrecognized
@@ -56,7 +56,7 @@ consumer keys.
     >>> response = caller.get(root)
     >>> response.status
     401
-    >>> print response.body
+    >>> print(response.body)
     Unknown consumer (new-consumer).
 
 But with anonymous access there is no registration step. The first
@@ -67,7 +67,7 @@ doesn't recognize the client.
     >>> login(ANONYMOUS)
     >>> from zope.component import getUtility
     >>> consumer_set = getUtility(IOAuthConsumerSet)
-    >>> print consumer_set.getByKey(u'another-new-consumer')
+    >>> print(consumer_set.getByKey(u'another-new-consumer'))
     None
     >>> logout()
 
@@ -81,7 +81,7 @@ Anonymous requests can't access certain data.
     >>> response = anon_webservice.get(body['me_link'])
     >>> response.status
     401
-    >>> print response.body
+    >>> print(response.body)
     You need to be logged in to view this URL.
 
 Anonymous requests can't change the dataset.
@@ -92,7 +92,7 @@ Anonymous requests can't change the dataset.
     ...     'application/json', data)
     >>> response.status
     401
-    >>> print response.body
+    >>> print(response.body)
     (<Person at...>, 'display_name', 'launchpad.Edit')
 
 A completely unsigned web service request is treated as an anonymous
@@ -100,7 +100,7 @@ request, with the OAuth consumer name being equal to the User-Agent.
 
     >>> agent = u"unsigned-user-agent"
     >>> login(ANONYMOUS)
-    >>> print consumer_set.getByKey(agent)
+    >>> print(consumer_set.getByKey(agent))
     None
     >>> logout()
 
@@ -116,7 +116,7 @@ request, with the OAuth consumer name being equal to the User-Agent.
     ...     return http(request)
 
     >>> response = request_with_user_agent(agent)
-    >>> print response.getOutput()
+    >>> print(response.getOutput())
     HTTP/1.1 200 Ok
     ...
     {...}
@@ -125,7 +125,7 @@ An unsigned request, like a request signed with the empty string,
 isn't logged in as any particular user:
 
     >>> response = request_with_user_agent(agent, "/devel/people/+me")
-    >>> print response.getOutput()
+    >>> print(response.getOutput())
     HTTP/1.1 401 Unauthorized
     ...
     You need to be logged in to view this URL.
@@ -155,7 +155,7 @@ to a different host.
     >>> webservice.domain = 'bugs.launchpad.test'
     >>> root = webservice.get(
     ...     'http://bugs.launchpad.test/api/devel/').jsonBody()
-    >>> print root['people_collection_link']
+    >>> print(root['people_collection_link'])
     http://bugs.launchpad.test/api/devel/people
 
 Requests on these hosts also honor the standard Launchpad authorization
@@ -167,9 +167,9 @@ scheme (and don't require OAuth).
     >>> noauth_webservice = LaunchpadWebServiceCaller(
     ...     domain='bugs.launchpad.test')
     >>> sample_auth = 'Basic %s' % base64.b64encode('test@xxxxxxxxxxxxx:test')
-    >>> print noauth_webservice.get(
+    >>> print(noauth_webservice.get(
     ...     'http://bugs.launchpad.test/api/devel/people/+me',
-    ...     headers={'Authorization': sample_auth})
+    ...     headers={'Authorization': sample_auth}))
     HTTP/1.1 303 See Other
     ...
     Location: http://bugs.launchpad.test/api/devel/~name12...
@@ -180,9 +180,9 @@ virtual host: an attempt to do HTTP Basic Auth will be treated as an
 anonymous request.
 
     >>> noauth_webservice.domain = 'api.launchpad.test'
-    >>> print noauth_webservice.get(
+    >>> print(noauth_webservice.get(
     ...     'http://api.launchpad.test/beta/people/+me',
-    ...     headers={'Authorization': sample_auth})
+    ...     headers={'Authorization': sample_auth}))
     HTTP/1.1 401 Unauthorized
     ...
     You need to be logged in to view this URL.
@@ -195,12 +195,12 @@ Launchpad's web service sets the Vary header differently from other
 parts of Launchpad.
 
     >>> browser.open("http://launchpad.test/";)
-    >>> print browser.headers['Vary']
+    >>> print(browser.headers['Vary'])
     Cookie, Authorization
 
     >>> response = webservice.get(
     ...     'http://bugs.launchpad.test/api/devel/')
-    >>> print response.getheader('Vary')
+    >>> print(response.getheader('Vary'))
     Accept
 
 The web service's Vary header does not mention the 'Cookie' header,
diff --git a/lib/lp/services/webservice/stories/xx-wadl.txt b/lib/lp/services/webservice/stories/xx-wadl.txt
index 6ce83e7..f7180ef 100644
--- a/lib/lp/services/webservice/stories/xx-wadl.txt
+++ b/lib/lp/services/webservice/stories/xx-wadl.txt
@@ -33,8 +33,8 @@ Let's write some fake WADL to disk.
 When we request the WADL for version "devel", the fake WADL is loaded
 from disk.
 
-    >>> print webservice.get(
-    ...     '/', 'application/vd.sun.wadl+xml', api_version='devel').body
+    >>> print(webservice.get(
+    ...     '/', 'application/vd.sun.wadl+xml', api_version='devel').body)
     Some fake WADL.
 
 The fake WADL is now present in the cache.
@@ -46,8 +46,8 @@ Change the cached value, and we change the document served.
 
     >>> WebServiceApplication.cached_wadl['devel'] = "More fake WADL."
 
-    >>> print webservice.get(
-    ...     '/', 'application/vd.sun.wadl+xml', api_version='devel').body
+    >>> print(webservice.get(
+    ...     '/', 'application/vd.sun.wadl+xml', api_version='devel').body)
     More fake WADL.
 
 If there's no value in the cache and no cached file on disk, the WADL
diff --git a/lib/lp/services/webservice/tests/test_doc.py b/lib/lp/services/webservice/tests/test_doc.py
index ce59e0e..47384c7 100644
--- a/lib/lp/services/webservice/tests/test_doc.py
+++ b/lib/lp/services/webservice/tests/test_doc.py
@@ -15,9 +15,11 @@ from lp.testing.layers import (
     AppServerLayer,
     LaunchpadFunctionalLayer,
     )
+from lp.testing.pages import setUpGlobs
 from lp.testing.systemdocs import (
     LayeredDocFileSuite,
     setGlobs,
+    setUp,
     )
 
 
@@ -32,7 +34,9 @@ def layerlessTearDown(test):
 special = {
     'webservice-configuration.txt': LayeredDocFileSuite(
         '../doc/webservice-configuration.txt',
-        setUp=setGlobs, tearDown=layerlessTearDown, layer=None),
+        setUp=lambda test: setGlobs(test, future=True),
+        tearDown=layerlessTearDown,
+        layer=None),
     # This test is actually run twice to prove that the AppServerLayer
     # properly isolates the database between tests.
     'launchpadlib.txt': LayeredDocFileSuite(
@@ -46,4 +50,7 @@ special = {
 
 
 def test_suite():
-    return build_test_suite(here, special, layer=LaunchpadFunctionalLayer)
+    return build_test_suite(
+        here, special, setUp=lambda test: setUp(test, future=True),
+        pageTestsSetUp=lambda test: setUpGlobs(test, future=True),
+        layer=LaunchpadFunctionalLayer)
diff --git a/lib/lp/services/webservice/tests/test_wadllib.py b/lib/lp/services/webservice/tests/test_wadllib.py
index e963e44..10a7238 100644
--- a/lib/lp/services/webservice/tests/test_wadllib.py
+++ b/lib/lp/services/webservice/tests/test_wadllib.py
@@ -3,6 +3,8 @@
 
 """Run the standalone wadllib tests."""
 
+from __future__ import absolute_import, print_function
+
 __metaclass__ = type
 __all__ = ['test_suite']
 
@@ -19,6 +21,11 @@ from lp.testing.systemdocs import LayeredDocFileSuite
 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)
+
+
 def test_suite():
     suite = unittest.TestSuite()
 
@@ -36,7 +43,7 @@ def test_suite():
     # Sort the tests.
     for filename in sorted(doctest_files):
         path = doctest_files[filename]
-        doctest = LayeredDocFileSuite(path, package=wadllib)
+        doctest = LayeredDocFileSuite(path, package=wadllib, setUp=setUp)
         suite.addTest(doctest)
 
     return suite