Merge lp:~cjwatson/lazr.restful/py3-print into lp:lazr.restful

Proposed by Colin Watson
Status: Merged
Merged at revision: 232
Proposed branch: lp:~cjwatson/lazr.restful/py3-print
Merge into: lp:lazr.restful
Diff against target: 4807 lines (+722/-600)
75 files modified
src/lazr/restful/__init__.py (+2/-0)
src/lazr/restful/_bytestorage.py (+2/-0)
src/lazr/restful/_operation.py (+2/-0)
src/lazr/restful/_resource.py (+2/-0)
src/lazr/restful/debug.py (+4/-3)
src/lazr/restful/declarations.py (+2/-0)
src/lazr/restful/directives/__init__.py (+2/-0)
src/lazr/restful/docs/absoluteurl.rst (+10/-10)
src/lazr/restful/docs/checker-utilities.rst (+3/-3)
src/lazr/restful/docs/debug.rst (+4/-4)
src/lazr/restful/docs/django.rst (+3/-3)
src/lazr/restful/docs/interface.rst (+4/-4)
src/lazr/restful/docs/multiversion.rst (+33/-33)
src/lazr/restful/docs/utils.rst (+28/-28)
src/lazr/restful/docs/webservice-declarations.rst (+94/-94)
src/lazr/restful/docs/webservice-error.rst (+5/-5)
src/lazr/restful/docs/webservice-marshallers.rst (+27/-27)
src/lazr/restful/docs/webservice-request.rst (+3/-3)
src/lazr/restful/docs/webservice.rst (+41/-41)
src/lazr/restful/error.py (+2/-0)
src/lazr/restful/example/base/filemanager.py (+2/-0)
src/lazr/restful/example/base/interfaces.py (+2/-0)
src/lazr/restful/example/base/root.py (+2/-0)
src/lazr/restful/example/base/security.py (+2/-0)
src/lazr/restful/example/base/subscribers.py (+2/-0)
src/lazr/restful/example/base/tests/collection.txt (+16/-16)
src/lazr/restful/example/base/tests/entry.txt (+130/-130)
src/lazr/restful/example/base/tests/field.txt (+47/-47)
src/lazr/restful/example/base/tests/hostedfile.txt (+21/-21)
src/lazr/restful/example/base/tests/redirect.txt (+5/-5)
src/lazr/restful/example/base/tests/representation-cache.txt (+33/-33)
src/lazr/restful/example/base/tests/root.txt (+12/-12)
src/lazr/restful/example/base/tests/service.txt (+12/-12)
src/lazr/restful/example/base/tests/test_integration.py (+8/-1)
src/lazr/restful/example/base/tests/wadl.txt (+8/-8)
src/lazr/restful/example/base/traversal.py (+2/-0)
src/lazr/restful/example/base_extended/README.txt (+1/-1)
src/lazr/restful/example/base_extended/comments.py (+2/-0)
src/lazr/restful/example/base_extended/tests/test_integration.py (+8/-1)
src/lazr/restful/example/multiversion/resources.py (+2/-0)
src/lazr/restful/example/multiversion/root.py (+2/-0)
src/lazr/restful/example/multiversion/tests/introduction.txt (+26/-26)
src/lazr/restful/example/multiversion/tests/operation.txt (+13/-13)
src/lazr/restful/example/multiversion/tests/test_integration.py (+8/-1)
src/lazr/restful/example/multiversion/tests/wadl.txt (+7/-7)
src/lazr/restful/example/wsgi/resources.py (+2/-0)
src/lazr/restful/example/wsgi/root.py (+2/-0)
src/lazr/restful/example/wsgi/run.py (+3/-0)
src/lazr/restful/example/wsgi/tests/introduction.txt (+2/-2)
src/lazr/restful/example/wsgi/tests/test_integration.py (+8/-1)
src/lazr/restful/fields.py (+2/-0)
src/lazr/restful/interface.py (+2/-0)
src/lazr/restful/interfaces/__init__.py (+2/-0)
src/lazr/restful/interfaces/_fields.py (+2/-0)
src/lazr/restful/interfaces/_rest.py (+2/-0)
src/lazr/restful/jsoncache.py (+2/-0)
src/lazr/restful/marshallers.py (+2/-0)
src/lazr/restful/metazcml.py (+2/-0)
src/lazr/restful/publisher.py (+2/-0)
src/lazr/restful/security.py (+2/-0)
src/lazr/restful/simple.py (+2/-0)
src/lazr/restful/tales.py (+2/-0)
src/lazr/restful/testing/event.py (+2/-0)
src/lazr/restful/testing/helpers.py (+2/-0)
src/lazr/restful/testing/tales.py (+2/-0)
src/lazr/restful/testing/webservice.py (+6/-4)
src/lazr/restful/tests/test_declarations.py (+2/-0)
src/lazr/restful/tests/test_docs.py (+7/-1)
src/lazr/restful/tests/test_error.py (+2/-0)
src/lazr/restful/tests/test_etag.py (+2/-0)
src/lazr/restful/tests/test_navigation.py (+2/-0)
src/lazr/restful/tests/test_utils.py (+2/-0)
src/lazr/restful/tests/test_webservice.py (+2/-0)
src/lazr/restful/utils.py (+2/-0)
src/lazr/restful/wsgi.py (+2/-0)
To merge this branch: bzr merge lp:~cjwatson/lazr.restful/py3-print
Reviewer Review Type Date Requested Status
Kristian Glass (community) Approve
Review via email: mp+378511@code.launchpad.net

Commit message

Apply absolute_import and print_function __future__ imports.

Description of the change

There's some minor fiddling to get doctests set up properly, but aside from that this is a more or less mechanical translation to Python 3's print syntax.

To post a comment you must log in.
Revision history for this message
Kristian Glass (doismellburning) wrote :

I skimmed and sample-reviewed this and what I saw looked good - given the nature of it, I'd happily approve merging it on that basis

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/lazr/restful/__init__.py'
2--- src/lazr/restful/__init__.py 2009-08-05 17:34:30 +0000
3+++ src/lazr/restful/__init__.py 2020-02-04 11:56:15 +0000
4@@ -17,6 +17,8 @@
5
6 # pylint: disable-msg=W0401
7
8+from __future__ import absolute_import, print_function
9+
10 import pkg_resources
11 __version__ = pkg_resources.resource_string("lazr.restful", "version.txt").strip()
12
13
14=== modified file 'src/lazr/restful/_bytestorage.py'
15--- src/lazr/restful/_bytestorage.py 2016-02-17 01:07:21 +0000
16+++ src/lazr/restful/_bytestorage.py 2020-02-04 11:56:15 +0000
17@@ -16,6 +16,8 @@
18
19 """Classes for a resource that implements a binary file repository."""
20
21+from __future__ import absolute_import, print_function
22+
23 __metaclass__ = type
24 __all__ = [
25 'ByteStorageResource',
26
27=== modified file 'src/lazr/restful/_operation.py'
28--- src/lazr/restful/_operation.py 2018-04-23 12:42:00 +0000
29+++ src/lazr/restful/_operation.py 2020-02-04 11:56:15 +0000
30@@ -2,6 +2,8 @@
31
32 """Base classes for one-off HTTP operations."""
33
34+from __future__ import absolute_import, print_function
35+
36 import simplejson
37
38 from zope.component import getMultiAdapter, getUtility, queryMultiAdapter
39
40=== modified file 'src/lazr/restful/_resource.py'
41--- src/lazr/restful/_resource.py 2019-11-12 14:26:41 +0000
42+++ src/lazr/restful/_resource.py 2020-02-04 11:56:15 +0000
43@@ -2,6 +2,8 @@
44
45 """Base classes for HTTP resources."""
46
47+from __future__ import absolute_import, print_function
48+
49 __metaclass__ = type
50
51 __all__ = [
52
53=== modified file 'src/lazr/restful/debug.py'
54--- src/lazr/restful/debug.py 2009-04-06 11:59:33 +0000
55+++ src/lazr/restful/debug.py 2020-02-04 11:56:15 +0000
56@@ -2,6 +2,8 @@
57
58 """Module docstring goes here."""
59
60+from __future__ import absolute_import, print_function
61+
62 __metaclass__ = type
63 __all__ = [
64 "debug_proxy",
65@@ -64,7 +66,7 @@
66 def debug_proxy(obj):
67 """Return informative text about the proxies wrapping obj.
68
69- Usually used like print debug_proxy(obj).
70+ Usually used like print(debug_proxy(obj)).
71 """
72 if not zope.proxy.isProxy(obj):
73 return "%r doesn't have any proxies." % obj
74@@ -73,6 +75,5 @@
75 if not zope.proxy.isProxy(proxy):
76 break
77 printer = proxy_formatters.get(type(proxy), default_proxy_formatter)
78- print >>buf, printer(proxy)
79+ print(printer(proxy), file=buf)
80 return buf.getvalue()
81-
82
83=== modified file 'src/lazr/restful/declarations.py'
84--- src/lazr/restful/declarations.py 2018-09-28 15:46:34 +0000
85+++ src/lazr/restful/declarations.py 2020-02-04 11:56:15 +0000
86@@ -2,6 +2,8 @@
87
88 """Declaration helpers to define a web service."""
89
90+from __future__ import absolute_import, print_function
91+
92 __metaclass__ = type
93 __all__ = [
94 'COLLECTION_TYPE',
95
96=== modified file 'src/lazr/restful/directives/__init__.py'
97--- src/lazr/restful/directives/__init__.py 2018-04-23 12:42:00 +0000
98+++ src/lazr/restful/directives/__init__.py 2020-02-04 11:56:15 +0000
99@@ -2,6 +2,8 @@
100
101 """Martian directives used in lazr.restful."""
102
103+from __future__ import absolute_import, print_function
104+
105 __metaclass__ = type
106 __all__ = ['request_class',
107 'publication_class',
108
109=== modified file 'src/lazr/restful/docs/absoluteurl.rst'
110--- src/lazr/restful/docs/absoluteurl.rst 2019-11-04 09:54:43 +0000
111+++ src/lazr/restful/docs/absoluteurl.rst 2020-02-04 11:56:15 +0000
112@@ -56,13 +56,13 @@
113 Calling the RootResourceAbsoluteURL will give the service root's
114 absolute URL.
115
116- >>> print adapter()
117+ >>> print(adapter())
118 https://hostname:1000/root_uri_prefix/active_version/
119
120 Converting the adapter to a string will give the same result, but
121 without the trailing slash.
122
123- >>> print str(adapter)
124+ >>> print(str(adapter))
125 https://hostname:1000/root_uri_prefix/active_version
126
127 (This is useful for the recursive case. When finding the URL to a
128@@ -74,11 +74,11 @@
129 Changing the web service configuration changes the generated URLs.
130
131 >>> configuration.use_https = False
132- >>> print getMultiAdapter((resource, request), IAbsoluteURL)()
133+ >>> print(getMultiAdapter((resource, request), IAbsoluteURL)())
134 http://hostname:1000/root_uri_prefix/active_version/
135
136 >>> configuration.port = None
137- >>> print getMultiAdapter((resource, request), IAbsoluteURL)()
138+ >>> print(getMultiAdapter((resource, request), IAbsoluteURL)())
139 http://hostname/root_uri_prefix/active_version/
140
141 The URL generated includes a version identifier taken from the
142@@ -87,7 +87,7 @@
143 >>> request.annotations[request.VERSION_ANNOTATION] = (
144 ... 'latest_version')
145 >>> adapter = getMultiAdapter((resource, request), IAbsoluteURL)
146- >>> print adapter()
147+ >>> print(adapter())
148 http://hostname/root_uri_prefix/latest_version/
149
150 For purposes of URL generation, the annotation doesn't have to be a
151@@ -96,7 +96,7 @@
152 >>> request.annotations[request.VERSION_ANNOTATION] = (
153 ... 'no_such_version')
154 >>> adapter = getMultiAdapter((resource, request), IAbsoluteURL)
155- >>> print adapter()
156+ >>> print(adapter())
157 http://hostname/root_uri_prefix/no_such_version/
158
159 (However, the lazr.restful traversal code will reject an invalid
160@@ -168,7 +168,7 @@
161 followed by two from the ChildResource itself.
162
163 >>> resource = ChildResource()
164- >>> print str(getMultiAdapter((resource, request), IAbsoluteURL))
165+ >>> print(str(getMultiAdapter((resource, request), IAbsoluteURL)))
166 http://dummyurl/child-part1/child-part2
167
168 Now let's put an object underneath the child resource that implements
169@@ -184,8 +184,8 @@
170 resource, the two from the ChildResource, and one from the
171 GrandchildResource itself.
172
173- >>> print str(getMultiAdapter(
174- ... (GrandchildResource(), request), IAbsoluteURL))
175+ >>> print(str(getMultiAdapter(
176+ ... (GrandchildResource(), request), IAbsoluteURL)))
177 http://dummyurl/child-part1/child-part2/grandchild
178
179 Edge cases and error handling
180@@ -195,7 +195,7 @@
181 It even escapes slashes, if a slash shows up inside a path part.
182
183 >>> resource.__path_parts__ = ["!foo!", "bar/baz"]
184- >>> print str(getMultiAdapter((resource, request), IAbsoluteURL))
185+ >>> print(str(getMultiAdapter((resource, request), IAbsoluteURL)))
186 http://dummyurl/%21foo%21/bar%2Fbaz
187
188 If the __path_parts__ is not iterable, an attempt to get the URL
189
190=== modified file 'src/lazr/restful/docs/checker-utilities.rst'
191--- src/lazr/restful/docs/checker-utilities.rst 2019-11-04 09:54:43 +0000
192+++ src/lazr/restful/docs/checker-utilities.rst 2020-02-04 11:56:15 +0000
193@@ -46,7 +46,7 @@
194
195 ProxyFactory wraps the content using the defined checker.
196
197- >>> print debug_proxy(ProxyFactory(content))
198+ >>> print(debug_proxy(ProxyFactory(content)))
199 zope.security._proxy._Proxy (using zope.security.checker.Checker)
200 public: aMethod, a_field, a_read_only_field, an_attr
201
202@@ -55,7 +55,7 @@
203
204 >>> undefineChecker(MyContent)
205 >>> protect_schema(MyContent, MySchema, read_permission='lazr.View')
206- >>> print debug_proxy(ProxyFactory(content))
207+ >>> print(debug_proxy(ProxyFactory(content)))
208 zope.security._proxy._Proxy (using zope.security.checker.Checker)
209 lazr.View: aMethod, a_field, a_read_only_field, an_attr
210
211@@ -64,7 +64,7 @@
212
213 >>> undefineChecker(MyContent)
214 >>> protect_schema(MyContent, MySchema, write_permission='lazr.Edit')
215- >>> print debug_proxy(ProxyFactory(content))
216+ >>> print(debug_proxy(ProxyFactory(content)))
217 zope.security._proxy._Proxy (using zope.security.checker.Checker)
218 lazr.Edit (set): a_field, an_attr
219 public: aMethod, a_field, a_read_only_field, an_attr
220
221=== modified file 'src/lazr/restful/docs/debug.rst'
222--- src/lazr/restful/docs/debug.rst 2019-11-04 09:54:43 +0000
223+++ src/lazr/restful/docs/debug.rst 2020-02-04 11:56:15 +0000
224@@ -15,14 +15,14 @@
225
226 In the simple case, where no proxy is used, as simple message is output:
227
228- >>> print debug_proxy(1)
229+ >>> print(debug_proxy(1))
230 1 doesn't have any proxies.
231
232 Otherwise, it prints the proxy type for each proxy used:
233
234 >>> from zope.proxy import ProxyBase
235
236- >>> print debug_proxy(ProxyBase(1))
237+ >>> print(debug_proxy(ProxyBase(1)))
238 zope.proxy.ProxyBase
239
240 If more than one proxy is used, information about the proxies will be
241@@ -31,7 +31,7 @@
242 >>> class SimpleProxy(ProxyBase):
243 ... """A very simple proxy."""
244
245- >>> print debug_proxy(SimpleProxy(ProxyBase(1)))
246+ >>> print(debug_proxy(SimpleProxy(ProxyBase(1))))
247 SimpleProxy
248 zope.proxy.ProxyBase
249
250@@ -45,7 +45,7 @@
251 ... {'value': CheckerPublic,
252 ... 'some_other_value': 'lazr.Edit'})
253 >>> p = ProxyFactory(1, checker)
254- >>> print debug_proxy(p)
255+ >>> print(debug_proxy(p))
256 zope.security._proxy._Proxy (using zope.security.checker.Checker)
257 lazr.Edit: __add__
258 lazr.Edit (set): some_other_value
259
260=== modified file 'src/lazr/restful/docs/django.rst'
261--- src/lazr/restful/docs/django.rst 2019-11-04 09:54:43 +0000
262+++ src/lazr/restful/docs/django.rst 2020-02-04 11:56:15 +0000
263@@ -166,7 +166,7 @@
264 >>> from zope.location.interfaces import ILocation
265 >>> resource = SubordinateResource()
266 >>> as_location = ILocation(resource)
267- >>> print as_location.__name__
268+ >>> print(as_location.__name__)
269 myname
270
271 It's also possible to adapt a Django model object to IAbsoluteURL and
272@@ -176,7 +176,7 @@
273 >>> from zope.traversing.browser.interfaces import IAbsoluteURL
274 >>> from lazr.restful.simple import Request
275 >>> request = Request("", {})
276- >>> print str(getMultiAdapter((resource, request), IAbsoluteURL))
277+ >>> print(str(getMultiAdapter((resource, request), IAbsoluteURL)))
278 http://dummyurl/myname
279
280
281@@ -227,7 +227,7 @@
282 >>> len(sequence)
283 3
284
285- >>> print sequence[1]
286+ >>> print(sequence[1])
287 bar
288
289 >>> sequence[1:3]
290
291=== modified file 'src/lazr/restful/docs/interface.rst'
292--- src/lazr/restful/docs/interface.rst 2019-11-04 09:54:43 +0000
293+++ src/lazr/restful/docs/interface.rst 2020-02-04 11:56:15 +0000
294@@ -52,9 +52,9 @@
295
296 >>> sorted(MyForm1.names())
297 ['age', 'name']
298- >>> print MyForm1.get('age').title
299+ >>> print(MyForm1.get('age').title)
300 Your age:
301- >>> print MyForm1.get('name').title
302+ >>> print(MyForm1.get('name').title)
303 Your name:
304
305 The interface attribute points to the correct interface:
306@@ -64,7 +64,7 @@
307
308 And the original field wasn't updated:
309
310- >>> print MyModel.get('age').title
311+ >>> print(MyModel.get('age').title)
312 Number of years since birth
313 >>> MyModel.get('name').interface is MyModel
314 True
315@@ -132,7 +132,7 @@
316
317 The interface attribute is cleared:
318
319- >>> print illuminated.interface
320+ >>> print(illuminated.interface)
321 None
322
323 It also supports the Field ordering (the copied field will have an
324
325=== modified file 'src/lazr/restful/docs/multiversion.rst'
326--- src/lazr/restful/docs/multiversion.rst 2019-11-04 09:54:43 +0000
327+++ src/lazr/restful/docs/multiversion.rst 2020-02-04 11:56:15 +0000
328@@ -433,19 +433,19 @@
329 >>> request_beta = create_web_service_request('/beta/')
330 >>> alsoProvides(request_beta, IBetaVersion)
331 >>> beta_entry = getMultiAdapter((C1, request_beta), IEntry)
332- >>> print beta_entry.fax
333+ >>> print(beta_entry.fax)
334 111-2121
335
336 >>> request_10 = create_web_service_request('/1.0/')
337 >>> alsoProvides(request_10, I10Version)
338 >>> one_oh_entry = getMultiAdapter((C1, request_10), IEntry)
339- >>> print one_oh_entry.fax_number
340+ >>> print(one_oh_entry.fax_number)
341 111-2121
342
343 >>> request_dev = create_web_service_request('/dev/')
344 >>> alsoProvides(request_dev, IDevVersion)
345 >>> dev_entry = getMultiAdapter((C1, request_dev), IEntry)
346- >>> print dev_entry.fax
347+ >>> print(dev_entry.fax)
348 Traceback (most recent call last):
349 ...
350 AttributeError: 'ContactEntryDev' object has no attribute 'fax'
351@@ -636,17 +636,17 @@
352 ... RootResourceAbsoluteURL, [cls, IBrowserRequest])
353
354 >>> beta_request = create_web_service_request('/beta/')
355- >>> print beta_request.traverse(None)
356+ >>> print(beta_request.traverse(None))
357 <BetaServiceRootResource object...>
358
359- >>> print absoluteURL(beta_app, beta_request)
360+ >>> print(absoluteURL(beta_app, beta_request))
361 http://api.multiversion.dev/beta/
362
363 >>> dev_request = create_web_service_request('/dev/')
364- >>> print dev_request.traverse(None)
365+ >>> print(dev_request.traverse(None))
366 <PostBetaServiceRootResource object...>
367
368- >>> print absoluteURL(dev_app, dev_request)
369+ >>> print(absoluteURL(dev_app, dev_request))
370 http://api.multiversion.dev/dev/
371
372 Request lifecycle
373@@ -668,7 +668,7 @@
374 <BetaServiceRootResource object ...>
375 >>> IBetaVersion.providedBy(request_beta)
376 True
377- >>> print request_beta.version
378+ >>> print(request_beta.version)
379 beta
380
381 Using the web service
382@@ -686,10 +686,10 @@
383 >>> request = create_web_service_request('/beta/')
384 >>> resource = request.traverse(None)
385 >>> body = simplejson.loads(resource())
386- >>> print sorted(body.keys())
387+ >>> print(sorted(body.keys()))
388 ['contacts_collection_link', 'resource_type_link']
389
390- >>> print body['contacts_collection_link']
391+ >>> print(body['contacts_collection_link'])
392 http://api.multiversion.dev/beta/contact_list
393
394 Here's the contact list.
395@@ -701,7 +701,7 @@
396 but since we happen to know which object it is, we can pass it into
397 absoluteURL along with the request object, and get the correct URL.
398
399- >>> print absoluteURL(contact_set, request)
400+ >>> print(absoluteURL(contact_set, request))
401 http://api.multiversion.dev/beta/contact_list
402
403 >>> body = simplejson.loads(resource())
404@@ -709,7 +709,7 @@
405 3
406 >>> for link in sorted(
407 ... [contact['self_link'] for contact in body['entries']]):
408- ... print link
409+ ... print(link)
410 http://api.multiversion.dev/beta/contact_list/Cleo%20Python
411 http://api.multiversion.dev/beta/contact_list/Fax-your-order%20Pizza
412 http://api.multiversion.dev/beta/contact_list/Oliver%20Bluth
413@@ -725,15 +725,15 @@
414 pass it into absoluteURL along with this request object, and get the
415 object's URL.
416
417- >>> print C1.name
418+ >>> print(C1.name)
419 Cleo Python
420- >>> print absoluteURL(C1, request_beta)
421+ >>> print(absoluteURL(C1, request_beta))
422 http://api.multiversion.dev/beta/contact_list/Cleo%20Python
423
424 >>> body = simplejson.loads(resource())
425 >>> sorted(body.keys())
426 ['fax', 'http_etag', 'name', 'phone', 'resource_type_link', 'self_link']
427- >>> print body['name']
428+ >>> print(body['name'])
429 Cleo Python
430
431 We can traverse through an entry to one of its fields.
432@@ -741,7 +741,7 @@
433 >>> request_beta = create_web_service_request(
434 ... '/beta/contact_list/Cleo Python/fax')
435 >>> field = request_beta.traverse(None)
436- >>> print simplejson.loads(field())
437+ >>> print(simplejson.loads(field()))
438 111-2121
439
440 We can invoke a named operation, and it returns a total_size (because
441@@ -778,13 +778,13 @@
442 >>> request = create_web_service_request('/1.0/')
443 >>> resource = request.traverse(None)
444 >>> body = simplejson.loads(resource())
445- >>> print sorted(body.keys())
446+ >>> print(sorted(body.keys()))
447 ['contacts_collection_link', 'resource_type_link']
448
449 Note that 'contacts_collection_link' points to a different URL in
450 '1.0' than in 'dev'.
451
452- >>> print body['contacts_collection_link']
453+ >>> print(body['contacts_collection_link'])
454 http://api.multiversion.dev/1.0/contacts
455
456 An attempt to use the 'beta' name of the contact list in the '1.0' web
457@@ -800,7 +800,7 @@
458
459 >>> request = create_web_service_request('/1.0/contacts')
460 >>> resource = request.traverse(None)
461- >>> print absoluteURL(contact_set, request)
462+ >>> print(absoluteURL(contact_set, request))
463 http://api.multiversion.dev/1.0/contacts
464
465 >>> body = simplejson.loads(resource())
466@@ -808,7 +808,7 @@
467 3
468 >>> for link in sorted(
469 ... [contact['self_link'] for contact in body['entries']]):
470- ... print link
471+ ... print(link)
472 http://api.multiversion.dev/1.0/contacts/Cleo%20Python
473 http://api.multiversion.dev/1.0/contacts/Fax-your-order%20Pizza
474 http://api.multiversion.dev/1.0/contacts/Oliver%20Bluth
475@@ -818,7 +818,7 @@
476 >>> request_10 = create_web_service_request(
477 ... '/1.0/contacts/Cleo Python')
478 >>> resource = request_10.traverse(None)
479- >>> print absoluteURL(C1, request_10)
480+ >>> print(absoluteURL(C1, request_10))
481 http://api.multiversion.dev/1.0/contacts/Cleo%20Python
482
483 Note that the 'fax' and 'phone' fields are now called 'fax_number' and
484@@ -828,7 +828,7 @@
485 >>> sorted(body.keys())
486 ['fax_number', 'http_etag', 'name', 'phone_number',
487 'resource_type_link', 'self_link']
488- >>> print body['name']
489+ >>> print(body['name'])
490 Cleo Python
491
492 We can traverse through an entry to one of its fields.
493@@ -836,7 +836,7 @@
494 >>> request_10 = create_web_service_request(
495 ... '/1.0/contacts/Cleo Python/fax_number')
496 >>> field = request_10.traverse(None)
497- >>> print simplejson.loads(field())
498+ >>> print(simplejson.loads(field()))
499 111-2121
500
501 The fax field in '1.0' is called 'fax_number', and attempting
502@@ -867,7 +867,7 @@
503 ...
504 KeyError: 'total_size'
505
506- >>> print result['total_size_link']
507+ >>> print(result['total_size_link'])
508 http://.../1.0/contacts?string=e&ws.op=find&ws.show=total_size
509 >>> size_request = create_web_service_request(
510 ... '/1.0/contacts',
511@@ -875,7 +875,7 @@
512 ... 'string=e&ws.op=find&ws.show=total_size'})
513 >>> operation = size_request.traverse(None)
514 >>> result = simplejson.loads(operation())
515- >>> print result
516+ >>> print(result)
517 3
518
519 If the resultset fits on a single page, total_size will be provided
520@@ -897,7 +897,7 @@
521 ... '/1.0/contacts',
522 ... environ={'QUERY_STRING' : 'ws.op=findContacts&string=Cleo'})
523 >>> operation = request_10.traverse(None)
524- >>> print operation()
525+ >>> print(operation())
526 No such operation: findContacts
527
528 Dev
529@@ -908,17 +908,17 @@
530 >>> request = create_web_service_request('/dev/')
531 >>> resource = request.traverse(None)
532 >>> body = simplejson.loads(resource())
533- >>> print sorted(body.keys())
534+ >>> print(sorted(body.keys()))
535 ['contacts_collection_link', 'resource_type_link']
536
537- >>> print body['contacts_collection_link']
538+ >>> print(body['contacts_collection_link'])
539 http://api.multiversion.dev/dev/contacts
540
541 Here's the contact list.
542
543 >>> request_dev = create_web_service_request('/dev/contacts')
544 >>> resource = request_dev.traverse(None)
545- >>> print absoluteURL(contact_set, request_dev)
546+ >>> print(absoluteURL(contact_set, request_dev))
547 http://api.multiversion.dev/dev/contacts
548
549 >>> body = simplejson.loads(resource())
550@@ -926,7 +926,7 @@
551 2
552 >>> for link in sorted(
553 ... [contact['self_link'] for contact in body['entries']]):
554- ... print link
555+ ... print(link)
556 http://api.multiversion.dev/dev/contacts/Cleo%20Python
557 http://api.multiversion.dev/dev/contacts/Oliver%20Bluth
558
559@@ -935,7 +935,7 @@
560 >>> request_dev = create_web_service_request(
561 ... '/dev/contacts/Cleo Python')
562 >>> resource = request_dev.traverse(None)
563- >>> print absoluteURL(C1, request_dev)
564+ >>> print(absoluteURL(C1, request_dev))
565 http://api.multiversion.dev/dev/contacts/Cleo%20Python
566
567 Note that the published field names have changed between 'dev' and
568@@ -945,7 +945,7 @@
569 >>> body = simplejson.loads(resource())
570 >>> sorted(body.keys())
571 ['http_etag', 'name', 'phone_number', 'resource_type_link', 'self_link']
572- >>> print body['name']
573+ >>> print(body['name'])
574 Cleo Python
575
576 We can traverse through an entry to one of its fields.
577@@ -953,7 +953,7 @@
578 >>> request_dev = create_web_service_request(
579 ... '/dev/contacts/Cleo Python/name')
580 >>> field = request_dev.traverse(None)
581- >>> print simplejson.loads(field())
582+ >>> print(simplejson.loads(field()))
583 Cleo Python
584
585 We cannot use 'dev' to traverse to a field not published in the 'dev'
586
587=== modified file 'src/lazr/restful/docs/utils.rst'
588--- src/lazr/restful/docs/utils.rst 2019-11-04 09:54:43 +0000
589+++ src/lazr/restful/docs/utils.rst 2020-02-04 11:56:15 +0000
590@@ -39,9 +39,9 @@
591 Traceback (most recent call last):
592 ...
593 KeyError: 'key'
594- >>> print stack.get('key')
595+ >>> print(stack.get('key'))
596 None
597- >>> print stack.get('key', 'default')
598+ >>> print(stack.get('key', 'default'))
599 default
600
601 >>> del stack['key']
602@@ -54,9 +54,9 @@
603
604 >>> stack.push('dict #1')
605 >>> stack['key'] = 'value'
606- >>> print stack['key']
607+ >>> print(stack['key'])
608 value
609- >>> print stack.get('key', 'default')
610+ >>> print(stack.get('key', 'default'))
611 value
612
613 >>> 'key' in stack
614@@ -70,9 +70,9 @@
615 dictionary.
616
617 >>> pair = stack.pop()
618- >>> print pair.version
619+ >>> print(pair.version)
620 dict #1
621- >>> print pair.object
622+ >>> print(pair.object)
623 {'key': 'value'}
624
625 >>> stack.push('dict #1')
626@@ -84,9 +84,9 @@
627 objects in the first.
628
629 >>> stack.push('dict #2')
630- >>> print stack['key']
631+ >>> print(stack['key'])
632 value
633- >>> print stack['key2']
634+ >>> print(stack['key2'])
635 {'key': 'value'}
636
637 Every dict is initialized with a deep copy of the one below it.
638@@ -111,7 +111,7 @@
639 You can find the dict for a given name with dict_for_name():
640
641 >>> for key, value in sorted(stack.dict_for_name('dict #1').items()):
642- ... print "%s: %s" % (key, value)
643+ ... print("%s: %s" % (key, value))
644 key: value
645 key2: {'key': 'value'}
646
647@@ -128,7 +128,7 @@
648 VersionedDict not to copy in values from the next lowest dictionary
649 in the stack.
650
651- >>> print stack['key']
652+ >>> print(stack['key'])
653 Second dict value
654
655 >>> stack.push("An empty dictionary", empty=True)
656@@ -153,15 +153,15 @@
657 KeyError: 'key2'
658
659 >>> stack['key'] = 'Brand new value'
660- >>> print stack['key']
661+ >>> print(stack['key'])
662 Brand new value
663
664 If you pop the formerly empty dictionary off the stack...
665
666 >>> pair = stack.pop()
667- >>> print pair.version
668+ >>> print(pair.version)
669 An empty dictionary
670- >>> print pair.object
671+ >>> print(pair.object)
672 {'key': 'Brand new value'}
673
674 ...'key' and 'key2' are visible again.
675@@ -195,15 +195,15 @@
676 ... 'TwoFields', ITwoFields,
677 ... {'field_1': 'foo', 'field_2': 'bar', 'a_method': result})
678
679- >>> print implementation.__name__
680+ >>> print(implementation.__name__)
681 TwoFields
682 >>> ITwoFields.implementedBy(implementation)
683 True
684- >>> print implementation.field_1
685+ >>> print(implementation.field_1)
686 foo
687- >>> print implementation.field_2
688+ >>> print(implementation.field_2)
689 bar
690- >>> print implementation().a_method()
691+ >>> print(implementation().a_method())
692 result
693
694 If one of the interface's attributes is not defined in the dictionary,
695@@ -214,7 +214,7 @@
696 >>> implementation = implement_from_dict(
697 ... 'TwoFields', ITwoFields, {})
698
699- >>> print implementation.field_1
700+ >>> print(implementation.field_1)
701 field_1 default
702
703 If an attribute is not present in the dictionary and its interface
704@@ -241,7 +241,7 @@
705 >>> implementation = implement_from_dict(
706 ... 'TwoFields', ITwoFields, {}, superclass=TwoFieldsSuperclass)
707
708- >>> print implementation().a_method()
709+ >>> print(implementation().a_method())
710 superclass result
711
712 make_identifier_safe
713@@ -251,22 +251,22 @@
714 string that can be used as a Python identifier.
715
716 >>> from lazr.restful.utils import make_identifier_safe
717- >>> print make_identifier_safe("already_a_valid_IDENTIFIER_444")
718+ >>> print(make_identifier_safe("already_a_valid_IDENTIFIER_444"))
719 already_a_valid_IDENTIFIER_444
720
721- >>> print make_identifier_safe("!starts_with_punctuation")
722+ >>> print(make_identifier_safe("!starts_with_punctuation"))
723 _starts_with_punctuation
724
725- >>> print make_identifier_safe("_!contains!pu-nc.tuation")
726+ >>> print(make_identifier_safe("_!contains!pu-nc.tuation"))
727 __contains_pu_nc_tuation
728
729- >>> print make_identifier_safe("contains\nnewline")
730+ >>> print(make_identifier_safe("contains\nnewline"))
731 contains_newline
732
733- >>> print make_identifier_safe("")
734+ >>> print(make_identifier_safe(""))
735 _
736
737- >>> print make_identifier_safe(None)
738+ >>> print(make_identifier_safe(None))
739 Traceback (most recent call last):
740 ...
741 ValueError: Cannot make None value identifier-safe.
742@@ -354,9 +354,9 @@
743 code.
744
745 >>> from lazr.restful.utils import safe_js_escape
746- >>> print safe_js_escape('John "nasty" O\'Brien')
747+ >>> print(safe_js_escape('John "nasty" O\'Brien'))
748 "John &quot;nasty&quot; O'Brien"
749- >>> print safe_js_escape("John O\'Brien")
750+ >>> print(safe_js_escape("John O\'Brien"))
751 "John O'Brien"
752- >>> print safe_js_escape("John <strong>O\'Brien</strong>")
753+ >>> print(safe_js_escape("John <strong>O\'Brien</strong>"))
754 "John &lt;strong&gt;O'Brien&lt;/strong&gt;"
755
756=== modified file 'src/lazr/restful/docs/webservice-declarations.rst'
757--- src/lazr/restful/docs/webservice-declarations.rst 2019-11-04 17:40:25 +0000
758+++ src/lazr/restful/docs/webservice-declarations.rst 2020-02-04 11:56:15 +0000
759@@ -63,11 +63,11 @@
760 ... return repr(value)
761 ... tag = element.queryTaggedValue('lazr.restful.exported')
762 ... if tag is None:
763- ... print "tag 'lazr.restful.exported' is not present"
764+ ... print("tag 'lazr.restful.exported' is not present")
765 ... else:
766- ... print "\n".join(
767+ ... print("\n".join(
768 ... "%s: %s" %(key, format_value(value))
769- ... for key, value in sorted(tag.items()))
770+ ... for key, value in sorted(tag.items())))
771 >>> print_export_tag(IBook)
772 _as_of_was_used: False
773 contributes_to: None
774@@ -465,7 +465,7 @@
775
776 >>> for name, param in sorted(IBookSetOnSteroids['new'].getTaggedValue(
777 ... 'lazr.restful.exported')['params'].items()):
778- ... print "%s: %s" % (name, param.__name__)
779+ ... print("%s: %s" % (name, param.__name__))
780 author: author
781 base_price: price
782 title: title
783@@ -791,7 +791,7 @@
784 ... """Sends a message to another named object."""
785
786 >>> for name in sorted(IUser.names(True)):
787- ... print '== %s ==' % name
788+ ... print('== %s ==' % name)
789 ... print_export_tag(IUser[name])
790 == name ==
791 as: 'name'
792@@ -937,7 +937,7 @@
793 >>> def dump_entry_interface(entry_interface):
794 ... for name, field in sorted(
795 ... entry_interface.namesAndDescriptions()):
796- ... print "%s: %s" % (name, field.__class__.__name__)
797+ ... print("%s: %s" % (name, field.__class__.__name__))
798 >>> dump_entry_interface(entry_interface)
799 author: TextLine
800 price: Float
801@@ -945,7 +945,7 @@
802
803 The field __name__ attribute contains the exported name:
804
805- >>> print entry_interface['price'].__name__
806+ >>> print(entry_interface['price'].__name__)
807 price
808
809 Associated with the interface through tags are automatically-generated
810@@ -953,9 +953,9 @@
811
812 >>> from lazr.restful.interfaces import LAZR_WEBSERVICE_NAME
813 >>> tags = entry_interface.queryTaggedValue(LAZR_WEBSERVICE_NAME)
814- >>> print tags['singular']
815+ >>> print(tags['singular'])
816 book
817- >>> print tags['plural']
818+ >>> print(tags['plural'])
819 books
820
821 It's an error to use generate_entry_interfaces() on an interface that
822@@ -989,7 +989,7 @@
823 adapter.
824
825 >>> [factory] = entry_adapter_factories
826- >>> print factory.version
827+ >>> print(factory.version)
828 beta
829 >>> entry_adapter_factory = factory.object
830
831@@ -1000,7 +1000,7 @@
832
833 The resulting class is named based on the interface:
834
835- >>> print entry_adapter_factory.__name__
836+ >>> print(entry_adapter_factory.__name__)
837 BookEntry_betaAdapter
838
839 Its docstring is also copied over from the original interface:
840@@ -1109,8 +1109,8 @@
841 ... """Simple ICheckedOutBookSet implementation."""
842 ...
843 ... def getByTitle(self, title, user):
844- ... print '%s searched for checked out book matching "%s".' % (
845- ... user, title)
846+ ... print('%s searched for checked out book matching "%s".' % (
847+ ... user, title))
848
849 >>> checked_out_adapter = generate_collection_adapter(
850 ... ICheckedOutBookSet)(CheckedOutBookSet(), request)
851@@ -1173,7 +1173,7 @@
852 >>> def print_params(params):
853 ... """Print the name and type of the defined parameters."""
854 ... for param in sorted(params, key=attrgetter('__name__')):
855- ... print "%s: %s" % (param.__name__, param.__class__.__name__)
856+ ... print("%s: %s" % (param.__name__, param.__class__.__name__))
857 >>> print_params(read_method_adapter_factory.params)
858 text: TextLine
859
860@@ -1208,7 +1208,7 @@
861 >>> import simplejson
862 >>> for key, value in sorted(
863 ... simplejson.loads(read_method_adapter.call(text='')).items()):
864- ... print '%s: %s' % (key, value)
865+ ... print('%s: %s' % (key, value))
866 entries: []
867 start: 0
868 total_size: 0
869@@ -1225,7 +1225,7 @@
870
871 The generated adapter class name is POST_<interface>_<operation>_beta.
872
873- >>> print write_method_adapter_factory.__name__
874+ >>> print(write_method_adapter_factory.__name__)
875 POST_IBookOnSteroids_checkout_beta
876
877 The adapter's params property also contains the available parameters
878@@ -1236,8 +1236,8 @@
879 >>> @implementer(IBookOnSteroids)
880 ... class BookOnSteroids(Book):
881 ... def checkout(self, who, kind):
882- ... print "%s did a %s check out of '%s'." % (
883- ... who, kind, self.title)
884+ ... print("%s did a %s check out of '%s'." % (
885+ ... who, kind, self.title))
886
887 >>> write_method_adapter = write_method_adapter_factory(
888 ... BookOnSteroids(
889@@ -1275,7 +1275,7 @@
890 The generated adapter class name is also
891 POST_<interface>_<operation>_beta.
892
893- >>> print write_method_adapter_factory.__name__
894+ >>> print(write_method_adapter_factory.__name__)
895 POST_IBookOnSteroids_checkout_beta
896
897 The adapter's params property also contains the available parameters.
898@@ -1321,7 +1321,7 @@
899 >>> response = factory_method_adapter.request.response
900 >>> response.status
901 201
902- >>> print response.headers['Location']
903+ >>> print(response.headers['Location'])
904 http://api.example.org/books/Eyeless%20in%20Gaza
905
906 The generate_operation_adapter() function can only be called on an
907@@ -1350,7 +1350,7 @@
908 The generated adapter class name is
909 DELETE_<interface>_<operation>_beta.
910
911- >>> print destructor_method_adapter_factory.__name__
912+ >>> print(destructor_method_adapter_factory.__name__)
913 DELETE_IBookOnSteroids_destroy_beta
914
915 Destructor
916@@ -1451,7 +1451,7 @@
917 ... IHasText, [], [hastext_entry_interface])
918
919 >>> obj = HasText()
920- >>> print hastext_entry_adapter_factory.version
921+ >>> print(hastext_entry_adapter_factory.version)
922 beta
923 >>> hastext_entry_adapter = hastext_entry_adapter_factory.object(
924 ... obj, request)
925@@ -1625,10 +1625,10 @@
926 ... ICachedBookSet['getAllBooks'])
927 >>> read_method_adapter = read_method_adapter_factory(
928 ... CachedBookSet(['Cool book']), request)
929- >>> print read_method_adapter.call()
930+ >>> print(read_method_adapter.call())
931 ['Cool book']
932 >>> for name, value in sorted(request.response.headers.items()):
933- ... print '%s: %s' % (name, value)
934+ ... print('%s: %s' % (name, value))
935 Cache-control: max-age=60
936 Content-Type: application/json
937
938@@ -1708,11 +1708,11 @@
939 >>> interface = IMultiVersionCollection
940 >>> adapter_earliest_factory = generate_collection_adapter(
941 ... interface, None)
942- >>> print adapter_earliest_factory.__name__
943+ >>> print(adapter_earliest_factory.__name__)
944 MultiVersionCollectionCollectionAdapter___Earliest
945
946 >>> collection_earliest = adapter_earliest_factory(data_object, request)
947- >>> print collection_earliest.find()
948+ >>> print(collection_earliest.find())
949 ['you', 'passed', 'in', 'pre-1.0 value']
950
951 Passing in '1.0' gets us the collection as it appears in the 1.0
952@@ -1721,22 +1721,22 @@
953 slightly different.
954
955 >>> adapter_10_factory = generate_collection_adapter(interface, '1.0')
956- >>> print adapter_10_factory.__name__
957+ >>> print(adapter_10_factory.__name__)
958 MultiVersionCollectionCollectionAdapter_1_0
959
960 >>> collection_10 = adapter_10_factory(data_object, request)
961- >>> print collection_10.find()
962+ >>> print(collection_10.find())
963 ['you', 'passed', 'in', '1.0 value']
964
965 Passing in '2.0' gets us a collection with totally different contents,
966 because a totally different method is being called.
967
968 >>> adapter_20_factory = generate_collection_adapter(interface, '2.0')
969- >>> print adapter_20_factory.__name__
970+ >>> print(adapter_20_factory.__name__)
971 MultiVersionCollectionCollectionAdapter_2_0
972
973 >>> collection_20 = adapter_20_factory(data_object, request)
974- >>> print collection_20.find()
975+ >>> print(collection_20.find())
976 ['contents', 'for', 'version', '2.0']
977
978 An error occurs when we try to generate an adapter for a version
979@@ -1792,7 +1792,7 @@
980 ... IMultiVersionEntry, [], *versions)
981
982 >>> for version, interface in versions_and_interfaces:
983- ... print version
984+ ... print(version)
985 beta
986 1.0
987 2.0
988@@ -1850,7 +1850,7 @@
989 ... IMultiVersionEntry, [], versions_and_interfaces)
990
991 >>> for version, adapter in entry_adapters:
992- ... print version
993+ ... print(version)
994 beta
995 1.0
996 2.0
997@@ -1862,22 +1862,22 @@
998 Here's the 'beta' version of the object:
999
1000 >>> object_beta = adapter_beta(data_object, request)
1001- >>> print object_beta.field
1002+ >>> print(object_beta.field)
1003 field value
1004- >>> print object_beta.field3
1005+ >>> print(object_beta.field3)
1006 field 3 value
1007- >>> print object_beta.unchanging_name
1008+ >>> print(object_beta.unchanging_name)
1009 unchanging value
1010
1011 The 'field4' field is not available in the 'beta' version under any name.
1012
1013- >>> print object_beta.field4
1014+ >>> print(object_beta.field4)
1015 Traceback (most recent call last):
1016 ...
1017 AttributeError: 'MultiVersionEntryEntry_betaAdapter' object has no
1018 attribute 'field4'
1019
1020- >>> print object_beta.new_in_10
1021+ >>> print(object_beta.new_in_10)
1022 Traceback (most recent call last):
1023 ...
1024 AttributeError: 'MultiVersionEntryEntry_betaAdapter' object has no
1025@@ -1887,11 +1887,11 @@
1026 now available as 'new_in_10'.
1027
1028 >>> object_10 = adapter_10(data_object, request)
1029- >>> print object_10.field
1030+ >>> print(object_10.field)
1031 field value
1032- >>> print object_10.unchanging_name
1033+ >>> print(object_10.unchanging_name)
1034 unchanging value
1035- >>> print object_10.new_in_10
1036+ >>> print(object_10.new_in_10)
1037 1.0
1038
1039 >>> object_10.field3
1040@@ -1903,26 +1903,26 @@
1041 Here's the '2.0' version. 'field3' is back, but now it's called '20_name'.
1042
1043 >>> object_20 = adapter_20(data_object, request)
1044- >>> print object_20.field
1045+ >>> print(object_20.field)
1046 field value
1047- >>> print object_20.unchanging_name
1048+ >>> print(object_20.unchanging_name)
1049 unchanging value
1050- >>> print getattr(object_20, '20_name')
1051+ >>> print(getattr(object_20, '20_name'))
1052 field 3 value
1053- >>> print object_20.new_in_10
1054+ >>> print(object_20.new_in_10)
1055 1.0
1056
1057 Here's the '3.0' version. 'field3' has been renamed to '30_name' and
1058 'field4' has been renamed to 'renamed_in_30'
1059
1060 >>> object_30 = adapter_30(data_object, request)
1061- >>> print object_30.field
1062+ >>> print(object_30.field)
1063 field value
1064- >>> print object_30.unchanging_name
1065+ >>> print(object_30.unchanging_name)
1066 unchanging value
1067- >>> print getattr(object_30, '30_name')
1068+ >>> print(getattr(object_30, '30_name'))
1069 field 3 value
1070- >>> print object_30.renamed_in_30
1071+ >>> print(object_30.renamed_in_30)
1072 1.0
1073
1074 >>> getattr(object_30, '20_name')
1075@@ -1958,13 +1958,13 @@
1076 >>> foo, bar = generate_entry_interfaces(
1077 ... IAmbiguousMultiVersion, [], 'foo', 'bar')
1078
1079- >>> print foo.version
1080+ >>> print(foo.version)
1081 foo
1082 >>> dump_entry_interface(foo.object)
1083 field2: TextLine
1084 foo_name: TextLine
1085
1086- >>> print bar.version
1087+ >>> print(bar.version)
1088 bar
1089 >>> dump_entry_interface(bar.object)
1090 bar_name: TextLine
1091@@ -1986,13 +1986,13 @@
1092 >>> bar, foo = generate_entry_interfaces(
1093 ... IAmbiguousMultiVersion, [], 'bar', 'foo')
1094
1095- >>> print bar.version
1096+ >>> print(bar.version)
1097 bar
1098 >>> dump_entry_interface(bar.object)
1099 bar_name: TextLine
1100 field1: TextLine
1101
1102- >>> print foo.version
1103+ >>> print(foo.version)
1104 foo
1105 >>> dump_entry_interface(foo.object)
1106 bar_name: TextLine
1107@@ -2167,11 +2167,11 @@
1108
1109 >>> method = IMultiVersionMethod['a_method']
1110 >>> adapter_earliest_factory = generate_operation_adapter(method, None)
1111- >>> print adapter_earliest_factory.__name__
1112+ >>> print(adapter_earliest_factory.__name__)
1113 GET_IMultiVersionMethod_a_method_beta
1114
1115 >>> method_earliest = adapter_earliest_factory(data_object, request)
1116- >>> print method_earliest.call(required="foo")
1117+ >>> print(method_earliest.call(required="foo"))
1118 Required value: foo. Fixed value: pre-1.0 value. User: A user.
1119
1120 Passing in '1.0' or '2.0' gets us the method as it appears in the
1121@@ -2180,26 +2180,26 @@
1122 1.0 is 'new_name', not 'a_method'.
1123
1124 >>> adapter_10_factory = generate_operation_adapter(method, '1.0')
1125- >>> print adapter_10_factory.__name__
1126+ >>> print(adapter_10_factory.__name__)
1127 GET_IMultiVersionMethod_new_name_1_0
1128
1129 >>> method_10 = adapter_10_factory(data_object, request)
1130- >>> print method_10.call(required="bar")
1131+ >>> print(method_10.call(required="bar"))
1132 Required value: bar. Fixed value: 1.0 value. User: A user.
1133
1134 >>> adapter_20_factory = generate_operation_adapter(method, '2.0')
1135- >>> print adapter_20_factory.__name__
1136+ >>> print(adapter_20_factory.__name__)
1137 GET_IMultiVersionMethod_new_name_2_0
1138
1139 >>> method_20 = adapter_20_factory(data_object, request)
1140- >>> print method_20.call(required="baz")
1141+ >>> print(method_20.call(required="baz"))
1142 Required value: baz. Fixed value: 2.0 value. User: A user.
1143
1144 >>> adapter_30_factory = generate_operation_adapter(method, '3.0')
1145- >>> print adapter_30_factory.__name__
1146+ >>> print(adapter_30_factory.__name__)
1147 GET_IMultiVersionMethod_new_name_3_0
1148 >>> method_30 = adapter_30_factory(data_object, request)
1149- >>> print method_30.call(required="baz")
1150+ >>> print(method_30.call(required="baz"))
1151 Required value: baz. Fixed value: 2.0 value. User: A user.
1152
1153 An error occurs when we try to generate an adapter for a version
1154@@ -2228,9 +2228,9 @@
1155 arguments ('2.0 value' and REQUEST_USER) from the 2.0 version, but it
1156 also sets a new value for 'cache_for'.
1157
1158- >>> print dictionary['as']
1159+ >>> print(dictionary['as'])
1160 new_name
1161- >>> print pformat(dictionary['call_with'])
1162+ >>> print(pformat(dictionary['call_with']))
1163 {'fixed': '2.0 value',
1164 'user': <class '...REQUEST_USER'>}
1165 >>> dictionary['cache_for']
1166@@ -2242,9 +2242,9 @@
1167 value for 'cache_for' from version 1.0.
1168
1169 >>> ignored = dictionary.pop()
1170- >>> print dictionary['as']
1171+ >>> print(dictionary['as'])
1172 new_name
1173- >>> print pformat(dictionary['call_with'])
1174+ >>> print(pformat(dictionary['call_with']))
1175 {'fixed': '2.0 value',
1176 'user': <class '...REQUEST_USER'>}
1177 >>> dictionary['cache_for']
1178@@ -2253,7 +2253,7 @@
1179 The published name of the 'required' argument is 'required_argument',
1180 not 'required'.
1181
1182- >>> print dictionary['params']['required'].__name__
1183+ >>> print(dictionary['params']['required'].__name__)
1184 required_argument
1185
1186 Let's pop the 2.0 version off the stack. Now we can see how the method
1187@@ -2262,12 +2262,12 @@
1188 is fixed to the string '1.0 value'.
1189
1190 >>> ignored = dictionary.pop()
1191- >>> print dictionary['as']
1192+ >>> print(dictionary['as'])
1193 new_name
1194- >>> print pformat(dictionary['call_with'])
1195+ >>> print(pformat(dictionary['call_with']))
1196 {'fixed': '1.0 value',
1197 'user': <class '...REQUEST_USER'>}
1198- >>> print dictionary['params']['required'].__name__
1199+ >>> print(dictionary['params']['required'].__name__)
1200 required_argument
1201 >>> dictionary['cache_for']
1202 100
1203@@ -2278,11 +2278,11 @@
1204 'fixed' argument is fixed to the string 'pre-1.0 value'.
1205
1206 >>> ignored = dictionary.pop()
1207- >>> print dictionary['as']
1208+ >>> print(dictionary['as'])
1209 a_method
1210- >>> print dictionary['params']['required'].__name__
1211+ >>> print(dictionary['params']['required'].__name__)
1212 required
1213- >>> print pformat(dictionary['call_with'])
1214+ >>> print(pformat(dictionary['call_with']))
1215 {'fixed': 'pre-1.0 value',
1216 'user': <class '...REQUEST_USER'>}
1217 >>> dictionary['cache_for']
1218@@ -2313,7 +2313,7 @@
1219 The method is not present in 2.0:
1220
1221 >>> version, attrs = dictionary.pop()
1222- >>> print version
1223+ >>> print(version)
1224 2.0
1225 >>> sorted(attrs.items())
1226 [('type', 'removed_operation')]
1227@@ -2321,20 +2321,20 @@
1228 It is present in 1.0:
1229
1230 >>> version, attrs = dictionary.pop()
1231- >>> print version
1232+ >>> print(version)
1233 1.0
1234- >>> print attrs['type']
1235+ >>> print(attrs['type'])
1236 read_operation
1237- >>> print attrs['params']['arg']
1238+ >>> print(attrs['params']['arg'])
1239 <zope.schema._field.Float object...>
1240
1241 But it's not present in the unnamed pre-1.0 version, since it hadn't
1242 been defined yet:
1243
1244 >>> pre_10 = dictionary.pop()
1245- >>> print pre_10.version
1246+ >>> print(pre_10.version)
1247 None
1248- >>> print pre_10.object
1249+ >>> print(pre_10.object)
1250 {'type': 'removed_operation'}
1251
1252 The @operation_removed_in_version declaration can also be used to
1253@@ -2372,22 +2372,22 @@
1254 takes two TextLine arguments and has no special return value.
1255
1256 >>> version, attrs = dictionary.pop()
1257- >>> print version
1258+ >>> print(version)
1259 1.0
1260- >>> print attrs['type']
1261+ >>> print(attrs['type'])
1262 write_operation
1263 >>> attrs['params']['arg']
1264 <zope.schema._bootstrapfields.TextLine object...>
1265 >>> attrs['params']['arg2']
1266 <zope.schema._bootstrapfields.TextLine object...>
1267- >>> print attrs.get('return_type')
1268+ >>> print(attrs.get('return_type'))
1269 None
1270
1271 In the unnamed pre-1.0 version, the 'method' operation is a read
1272 operation that takes a single Float argument and returns a collection.
1273
1274 >>> version, attrs = dictionary.pop()
1275- >>> print attrs['type']
1276+ >>> print(attrs['type'])
1277 read_operation
1278
1279 >>> attrs['params']['arg']
1280@@ -2577,24 +2577,24 @@
1281 >>> from zope.security.checker import ProxyFactory
1282
1283 # ProxyFactory wraps the content using the defined checker.
1284- >>> print debug_proxy(ProxyFactory(entry_adapter))
1285+ >>> print(debug_proxy(ProxyFactory(entry_adapter)))
1286 zope.security._proxy._Proxy (using zope.security.checker.Checker)
1287 public: author, price, schema, title
1288 public (set): author, price, schema, title
1289
1290- >>> print debug_proxy(ProxyFactory(collection_adapter))
1291+ >>> print(debug_proxy(ProxyFactory(collection_adapter)))
1292 zope.security._proxy._Proxy (using zope.security.checker.Checker)
1293 public: entry_schema, find
1294
1295- >>> print debug_proxy(ProxyFactory(read_method_adapter))
1296+ >>> print(debug_proxy(ProxyFactory(read_method_adapter)))
1297 zope.security._proxy._Proxy (using zope.security.checker.Checker)
1298 public: __call__, return_type, send_modification_event
1299
1300- >>> print debug_proxy(ProxyFactory(write_method_adapter))
1301+ >>> print(debug_proxy(ProxyFactory(write_method_adapter)))
1302 zope.security._proxy._Proxy (using zope.security.checker.Checker)
1303 public: __call__, send_modification_event
1304
1305- >>> print debug_proxy(ProxyFactory(factory_method_adapter))
1306+ >>> print(debug_proxy(ProxyFactory(factory_method_adapter)))
1307 zope.security._proxy._Proxy (using zope.security.checker.Checker)
1308 public: __call__, send_modification_event
1309
1310@@ -2624,7 +2624,7 @@
1311 >>> verifyObject(IEntry, entry_adapter)
1312 True
1313
1314- >>> print entry_adapter.schema.__name__
1315+ >>> print(entry_adapter.schema.__name__)
1316 IBookEntry_beta
1317 >>> verifyObject(entry_adapter.schema, entry_adapter)
1318 True
1319@@ -2874,7 +2874,7 @@
1320 The operation is not available in 'beta', because it hasn't been
1321 defined yet.
1322
1323- >>> print operation_for(context, 'beta', 'set_value').__class__.__name__
1324+ >>> print(operation_for(context, 'beta', 'set_value').__class__.__name__)
1325 Traceback (most recent call last):
1326 ...
1327 ComponentLookupError: ...
1328@@ -2884,10 +2884,10 @@
1329 1.0. This is because the operation doesn't become a mutator operation
1330 until 3.0.
1331
1332- >>> print operation_for(context, '1.0', 'set_value').__class__.__name__
1333+ >>> print(operation_for(context, '1.0', 'set_value').__class__.__name__)
1334 POST_IOperationPromotedToMutator_set_value_1_0
1335
1336- >>> print operation_for(context, '2.0', 'set_value').__class__.__name__
1337+ >>> print(operation_for(context, '2.0', 'set_value').__class__.__name__)
1338 POST_IOperationPromotedToMutator_set_value_1_0
1339
1340 The operation is not available in 3.0, the version in which it becomes
1341@@ -2904,7 +2904,7 @@
1342 >>> request_30 = request_for('3.0')
1343 >>> entry = getMultiAdapter((context, request_30), IEntry)
1344 >>> entry.field = 'foo'
1345- >>> print entry.field
1346+ >>> print(entry.field)
1347 !foo!
1348
1349 You can immediately reinstate a mutator operation as a named operation
1350@@ -2952,15 +2952,15 @@
1351 The mutator is accessible for version 1.0, as you'd expect.
1352
1353 >>> context = MutatorPlusNamedOperation()
1354- >>> print operation_for(context, '1.0', 'set_value').__class__.__name__
1355+ >>> print(operation_for(context, '1.0', 'set_value').__class__.__name__)
1356 POST_IMutatorPlusNamedOperationEntry_set_value_1_0
1357
1358 The named operations that replace the mutator in versions 2.0 and 3.0 are
1359 also accessible.
1360
1361- >>> print operation_for(context, '2.0', 'set_value').__class__.__name__
1362+ >>> print(operation_for(context, '2.0', 'set_value').__class__.__name__)
1363 POST_IMutatorPlusNamedOperationEntry_set_value_2_0
1364- >>> print operation_for(context, '3.0', 'set_value').__class__.__name__
1365+ >>> print(operation_for(context, '3.0', 'set_value').__class__.__name__)
1366 POST_IMutatorPlusNamedOperationEntry_set_value_3_0
1367
1368 So, in the version that gets rid of named operations for mutator methods,
1369
1370=== modified file 'src/lazr/restful/docs/webservice-error.rst'
1371--- src/lazr/restful/docs/webservice-error.rst 2019-11-04 09:54:43 +0000
1372+++ src/lazr/restful/docs/webservice-error.rst 2020-02-04 11:56:15 +0000
1373@@ -81,19 +81,19 @@
1374 When the request contains an OOPSID, it will be set in the X-Lazr-OopsId
1375 header:
1376
1377- >>> print request.response.headers.get('X-Lazr-OopsId')
1378+ >>> print(request.response.headers.get('X-Lazr-OopsId'))
1379 None
1380 >>> request = FakeRequest()
1381 >>> request.oopsid = 'OOPS-001'
1382 >>> ignored = render_error_view(InvalidInput('bad email'), request)
1383- >>> print request.response.headers['X-Lazr-OopsId']
1384+ >>> print(request.response.headers['X-Lazr-OopsId'])
1385 OOPS-001
1386
1387 Even if show_tracebacks is set to true, non-5xx error codes will not
1388 produce a traceback.
1389
1390 >>> webservice_configuration.show_tracebacks = True
1391- >>> print render_error_view(InvalidInput('bad email'), request)
1392+ >>> print(render_error_view(InvalidInput('bad email'), request))
1393 bad email
1394
1395
1396@@ -111,7 +111,7 @@
1397 so there's no point in hiding the exception message. When tracebacks are
1398 shown, the view puts a traceback dump in the response.
1399
1400- >>> print render_error_view(ServerError('DB crash'), request)
1401+ >>> print(render_error_view(ServerError('DB crash'), request))
1402 DB crash
1403 <BLANKLINE>
1404 Traceback (most recent call last):
1405@@ -122,7 +122,7 @@
1406 will see the exception class name instead of a message.
1407
1408 >>> webservice_configuration.show_tracebacks = False
1409- >>> print render_error_view(ServerError('DB crash'), request)
1410+ >>> print(render_error_view(ServerError('DB crash'), request))
1411 ServerError
1412
1413
1414
1415=== modified file 'src/lazr/restful/docs/webservice-marshallers.rst'
1416--- src/lazr/restful/docs/webservice-marshallers.rst 2019-11-04 09:54:43 +0000
1417+++ src/lazr/restful/docs/webservice-marshallers.rst 2020-02-04 11:56:15 +0000
1418@@ -60,7 +60,7 @@
1419 u'unicode\u2122'
1420 >>> marshaller.marshall_from_json_data("")
1421 ''
1422- >>> print marshaller.marshall_from_json_data(None)
1423+ >>> print(marshaller.marshall_from_json_data(None))
1424 None
1425
1426 marshall_from_request()
1427@@ -73,7 +73,7 @@
1428 SimpleFieldMarshaller tries first to parse the value as a JSON-encoded
1429 string, the resulting value is passed on to marshall_from_json_data().
1430
1431- >>> print marshaller.marshall_from_request("null")
1432+ >>> print(marshaller.marshall_from_request("null"))
1433 None
1434 >>> marshaller.marshall_from_request("true")
1435 True
1436@@ -121,9 +121,9 @@
1437 the SimpleFieldMarshaller implementation, the value is returned
1438 unchanged.
1439
1440- >>> print marshaller.unmarshall(None, 'foo')
1441+ >>> print(marshaller.unmarshall(None, 'foo'))
1442 foo
1443- >>> print marshaller.unmarshall(None, None)
1444+ >>> print(marshaller.unmarshall(None, None))
1445 None
1446
1447 When a more detailed representation is needed, unmarshall_to_closeup()
1448@@ -172,7 +172,7 @@
1449
1450 None is passed through though.
1451
1452- >>> print marshaller.marshall_from_json_data(None)
1453+ >>> print(marshaller.marshall_from_json_data(None))
1454 None
1455
1456 Booleans are encoded using the standard JSON representation of 'true' or
1457@@ -209,7 +209,7 @@
1458
1459 None is passed through though.
1460
1461- >>> print marshaller.marshall_from_json_data(None)
1462+ >>> print(marshaller.marshall_from_json_data(None))
1463 None
1464
1465 Integers are encoded using strings when in a request.
1466@@ -268,7 +268,7 @@
1467
1468 None is passed through though.
1469
1470- >>> print marshaller.marshall_from_json_data(None)
1471+ >>> print(marshaller.marshall_from_json_data(None))
1472 None
1473
1474 And integers are automatically converted to a float.
1475@@ -392,7 +392,7 @@
1476
1477 None is passed through though.
1478
1479- >>> print marshaller.marshall_from_json_data(None)
1480+ >>> print(marshaller.marshall_from_json_data(None))
1481 None
1482
1483 When coming from the request, everything is interpreted as a unicode
1484@@ -409,7 +409,7 @@
1485
1486 Except that 'null' still returns None.
1487
1488- >>> print marshaller.marshall_from_request('null')
1489+ >>> print(marshaller.marshall_from_request('null'))
1490 None
1491
1492 Bytes
1493@@ -436,7 +436,7 @@
1494
1495 Again, except for None which is passed through.
1496
1497- >>> print marshaller.marshall_from_json_data(None)
1498+ >>> print(marshaller.marshall_from_json_data(None))
1499 None
1500
1501 When coming over the request, the value is also converted into a UTF-8
1502@@ -451,7 +451,7 @@
1503
1504 But again, None is returned as is.
1505
1506- >>> print marshaller.marshall_from_request('null')
1507+ >>> print(marshaller.marshall_from_request('null'))
1508 None
1509
1510 Since multipart/form-data can be used to upload data, file-like objects
1511@@ -511,7 +511,7 @@
1512
1513 None is passed through.
1514
1515- >>> print marshaller.marshall_from_json_data(None)
1516+ >>> print(marshaller.marshall_from_json_data(None))
1517 None
1518
1519 When coming from the request, everything is interpreted as a unicode
1520@@ -532,7 +532,7 @@
1521
1522 But again, 'null' is returned as None.
1523
1524- >>> print marshaller.marshall_from_request('null')
1525+ >>> print(marshaller.marshall_from_request('null'))
1526 None
1527
1528 Unlike a Bytes field, an ASCIILine field used in an entry is stored
1529@@ -581,7 +581,7 @@
1530
1531 None is always returned unchanged.
1532
1533- >>> print marshaller.marshall_from_json_data(None)
1534+ >>> print(marshaller.marshall_from_json_data(None))
1535 None
1536
1537 Since this marshaller's Choice fields deal with small, fixed
1538@@ -589,7 +589,7 @@
1539 describe the vocabulary as a whole.
1540
1541 >>> for token in marshaller.unmarshall_to_closeup(None, '10'):
1542- ... print sorted(token.items())
1543+ ... print(sorted(token.items()))
1544 [('title', None), ('token', '10')]
1545 [('title', None), ('token', 'a value')]
1546 [('title', None), ('token', 'True')]
1547@@ -597,7 +597,7 @@
1548 And None is handled correctly.
1549
1550 >>> for token in marshaller.unmarshall_to_closeup(None, None):
1551- ... print sorted(token.items())
1552+ ... print(sorted(token.items()))
1553 [('title', None), ('token', '10')]
1554 [('title', None), ('token', 'a value')]
1555 [('title', None), ('token', 'True')]
1556@@ -613,7 +613,7 @@
1557 ... try:
1558 ... callable(*args)
1559 ... except ValueError as e:
1560- ... print 'ValueError:', unicode(e)
1561+ ... print('ValueError:', unicode(e))
1562
1563
1564 Choice of EnumeratedTypes
1565@@ -641,7 +641,7 @@
1566
1567 None is returned unchanged:
1568
1569- >>> print marshaller.marshall_from_json_data(None)
1570+ >>> print(marshaller.marshall_from_json_data(None))
1571 None
1572
1573 This marshaller is for a Choice field describing a small, fixed
1574@@ -651,7 +651,7 @@
1575
1576 >>> for cuisine in sorted(
1577 ... marshaller.unmarshall_to_closeup(None, "Triaged")):
1578- ... print sorted(cuisine.items())
1579+ ... print(sorted(cuisine.items()))
1580 [('title', 'American'), ('token', 'AMERICAN')]
1581 ...
1582 [('title', 'Vegetarian'), ('token', 'VEGETARIAN')]
1583@@ -673,7 +673,7 @@
1584 >>> from lazr.restful.example.base.root import COOKBOOKS
1585 >>> cookbook = COOKBOOKS[0]
1586 >>> cookbook_url = reference_marshaller.unmarshall(None, cookbook)
1587- >>> print cookbook_url
1588+ >>> print(cookbook_url)
1589 http://.../cookbooks/Mastering%20the%20Art%20of%20French%20Cooking
1590
1591 A URL is unmarshalled to the underlying object.
1592@@ -692,7 +692,7 @@
1593 ...
1594 ValueError: got 'int', expected string: 4
1595
1596- >>> print reference_marshaller.marshall_from_json_data(None)
1597+ >>> print(reference_marshaller.marshall_from_json_data(None))
1598 None
1599
1600 Relative URLs
1601@@ -702,7 +702,7 @@
1602
1603 >>> cookbook = reference_marshaller.marshall_from_json_data(
1604 ... '/cookbooks/Everyday%20Greens')
1605- >>> print cookbook.name
1606+ >>> print(cookbook.name)
1607 Everyday Greens
1608
1609 Collections
1610@@ -817,10 +817,10 @@
1611
1612 None is passed through though.
1613
1614- >>> print list_marshaller.marshall_from_json_data(None)
1615+ >>> print(list_marshaller.marshall_from_json_data(None))
1616 None
1617
1618- >>> print dict_marshaller.marshall_from_json_data(None)
1619+ >>> print(dict_marshaller.marshall_from_json_data(None))
1620 None
1621
1622 ValueError is also raised if one of the value in the list doesn't
1623@@ -892,10 +892,10 @@
1624
1625 Except that 'null' still returns None.
1626
1627- >>> print list_marshaller.marshall_from_request('null')
1628+ >>> print(list_marshaller.marshall_from_request('null'))
1629 None
1630
1631- >>> print dict_marshaller.marshall_from_request('null')
1632+ >>> print(dict_marshaller.marshall_from_request('null'))
1633 None
1634
1635 Also, as a convenience for web client, so that they don't have to JSON
1636@@ -920,7 +920,7 @@
1637
1638 The unmarshall() method will return None when given None.
1639
1640- >>> print dict_marshaller.unmarshall(None, None)
1641+ >>> print(dict_marshaller.unmarshall(None, None))
1642 None
1643
1644 CollectionField
1645
1646=== modified file 'src/lazr/restful/docs/webservice-request.rst'
1647--- src/lazr/restful/docs/webservice-request.rst 2019-11-04 09:54:43 +0000
1648+++ src/lazr/restful/docs/webservice-request.rst 2020-02-04 11:56:15 +0000
1649@@ -67,7 +67,7 @@
1650 >>> cache.objects['object1'] = 'foo'
1651 >>> cache.objects['object2'] = 'bar'
1652 >>> for key in sorted(cache.objects):
1653- ... print "%s: %s" % (key, cache.objects[key])
1654+ ... print("%s: %s" % (key, cache.objects[key]))
1655 object1: foo
1656 object2: bar
1657
1658@@ -77,7 +77,7 @@
1659 >>> cache.links['objectA'] = 'foo'
1660 >>> cache.links['objectB'] = 'bar'
1661 >>> for key in sorted(cache.links):
1662- ... print "%s: %s" % (key, cache.links[key])
1663+ ... print("%s: %s" % (key, cache.links[key]))
1664 objectA: foo
1665 objectB: bar
1666
1667@@ -95,6 +95,6 @@
1668 >>> cache = test_tales(
1669 ... "request/webservicerequest:cache", request=website_request)
1670 >>> for key in sorted(cache.links):
1671- ... print "%s: %s" % (key, cache.links[key])
1672+ ... print("%s: %s" % (key, cache.links[key]))
1673 objectA: foo
1674 objectB: bar
1675
1676=== modified file 'src/lazr/restful/docs/webservice.rst'
1677--- src/lazr/restful/docs/webservice.rst 2019-11-04 09:54:43 +0000
1678+++ src/lazr/restful/docs/webservice.rst 2020-02-04 11:56:15 +0000
1679@@ -862,7 +862,7 @@
1680 >>> from lazr.restful._resource import get_entry_fields_in_write_order
1681 >>> def print_fields_in_write_order(entry):
1682 ... for name, field in get_entry_fields_in_write_order(entry):
1683- ... print name
1684+ ... print(name)
1685
1686 >>> print_fields_in_write_order(author_entry)
1687 name
1688@@ -1123,7 +1123,7 @@
1689 >>> wadl_request = create_web_service_request(
1690 ... '/beta/', environ=wadl_headers)
1691 >>> wadl_resource = wadl_request.traverse(app)
1692- >>> print wadl_resource(wadl_request)
1693+ >>> print(wadl_resource(wadl_request))
1694 <?xml version="1.0"?>
1695 <!DOCTYPE...
1696 <wadl:application ...>
1697@@ -1139,7 +1139,7 @@
1698 so there's an ``AssertionError``.
1699
1700 >>> sm.registerAdapter(DishCollection, [IAuthorSet], ICollection)
1701- >>> print wadl_resource(wadl_request)
1702+ >>> print(wadl_resource(wadl_request))
1703 Traceback (most recent call last):
1704 ...
1705 AssertionError: There must be one (and only one) adapter
1706@@ -1249,7 +1249,7 @@
1707 ... environ={'QUERY_STRING' :
1708 ... 'ws.op=find_recipes&name=NoSuchRecipe'})
1709 >>> operation_resource = request.traverse(app)
1710- >>> print operation_resource()
1711+ >>> print(operation_resource())
1712 No matches for NoSuchRecipe
1713
1714 Collections may also support named POST operations. These requests
1715@@ -1260,7 +1260,7 @@
1716
1717 >>> def modified_cookbook(object, event):
1718 ... """Print a message when triggered."""
1719- ... print "You just modified a cookbook."
1720+ ... print("You just modified a cookbook.")
1721
1722 >>> from lazr.lifecycle.interfaces import IObjectModifiedEvent
1723 >>> from lazr.restful.testing.event import TestEventListener
1724@@ -1269,7 +1269,7 @@
1725
1726 >>> def modified_cookbook_set(object, event):
1727 ... """Print a message when triggered."""
1728- ... print "You just modified the cookbook set."
1729+ ... print("You just modified the cookbook set.")
1730
1731 Here we create a new cookbook for an existing author. Because the
1732 operation's definition doesn't set send_modified_event to True, no
1733@@ -1506,11 +1506,11 @@
1734 expect.
1735
1736 >>> request, operation = make_dummy_operation_request("A string.")
1737- >>> print operation()
1738+ >>> print(operation())
1739 "A string."
1740 >>> request.response.getStatus()
1741 200
1742- >>> print request.response.getHeader('Content-Type')
1743+ >>> print(request.response.getHeader('Content-Type'))
1744 application/json
1745
1746 >>> request, operation = make_dummy_operation_request(True)
1747@@ -1579,7 +1579,7 @@
1748 >>> request, operation = make_dummy_operation_request(recipes)
1749 >>> response = operation()
1750 >>> for key, value in sorted(simplejson.loads(response).items()):
1751- ... print '%s: %s' % (key, value)
1752+ ... print('%s: %s' % (key, value))
1753 entries: [{...}, {...}]
1754 start: ...
1755 total_size: 2
1756@@ -1591,7 +1591,7 @@
1757 >>> request, operation = make_dummy_operation_request(DishSet())
1758 >>> response = operation()
1759 >>> for key, value in sorted(simplejson.loads(response).items()):
1760- ... print '%s: %s' % (key, value)
1761+ ... print('%s: %s' % (key, value))
1762 entries: ...
1763 start: ...
1764 total_size: ...
1765@@ -1661,13 +1661,13 @@
1766 ... return dict(entity_body=entity_body,
1767 ... response=get_request.response)
1768
1769- >>> print get_julia(etag_original)['response'].getStatus()
1770+ >>> print(get_julia(etag_original)['response'].getStatus())
1771 304
1772
1773 If the ETags don't match, the server assumes the client has an old
1774 representation, and sends the new representation.
1775
1776- >>> print get_julia('bad etag')['entity_body']
1777+ >>> print(get_julia('bad etag')['entity_body'])
1778 {...}
1779
1780 Change the state of the resource, and the ETag changes.
1781@@ -1706,27 +1706,27 @@
1782 Under normal circumstances, lazr.restful won't recognize an ETag
1783 modified by mod_compress.
1784
1785- >>> print get_julia(modified_etag_1)['entity_body']
1786+ >>> print(get_julia(modified_etag_1)['entity_body'])
1787 {...}
1788
1789 When 'compensate_for_mod_compress_etag_modification' is set,
1790 lazr.restful will recognize an ETag modified by mod_compress.
1791
1792 >>> c = webservice_configuration
1793- >>> print c.compensate_for_mod_compress_etag_modification
1794+ >>> print(c.compensate_for_mod_compress_etag_modification)
1795 False
1796 >>> c.compensate_for_mod_compress_etag_modification = True
1797
1798- >>> print get_julia(modified_etag_1)['response'].getStatus()
1799+ >>> print(get_julia(modified_etag_1)['response'].getStatus())
1800 304
1801
1802- >>> print get_julia(modified_etag_2)['response'].getStatus()
1803+ >>> print(get_julia(modified_etag_2)['response'].getStatus())
1804 304
1805
1806 Of course, that doesn't mean lazr.restful will recognize any random
1807 ETag.
1808
1809- >>> print get_julia(etag + "-not-gzip")['entity_body']
1810+ >>> print(get_julia(etag + "-not-gzip")['entity_body'])
1811 {...}
1812
1813 Cleanup.
1814@@ -1831,10 +1831,10 @@
1815 >>> body = simplejson.dumps(author)
1816 >>> put_request = create_web_service_request(
1817 ... beard_url, body=body, environ=headers, method='PUT')
1818- >>> print put_request.traverse(app)()
1819+ >>> print(put_request.traverse(app)())
1820 (<Recipe object...>, 'dish', ...)
1821
1822- >>> print put_request.response.getStatus()
1823+ >>> print(put_request.response.getStatus())
1824 401
1825
1826 Stored file resources
1827@@ -1863,7 +1863,7 @@
1828 ...
1829 NotFound: ... name: 'cover'
1830
1831- >>> print C2.cover
1832+ >>> print(C2.cover)
1833 None
1834
1835 A cookbook can be given a cover with PUT.
1836@@ -1885,7 +1885,7 @@
1837 >>> file_resource()
1838 >>> get_request.response.getStatus()
1839 303
1840- >>> print get_request.response.getHeader('Location')
1841+ >>> print(get_request.response.getHeader('Location'))
1842 http://cookbooks.dev/.../filemanager/0
1843
1844 The cover can be deleted with DELETE.
1845@@ -1902,7 +1902,7 @@
1846 ...
1847 NotFound: ... name: 'cover'
1848
1849- >>> print C2.cover
1850+ >>> print(C2.cover)
1851 None
1852
1853 Field resources
1854@@ -1912,7 +1912,7 @@
1855
1856 >>> field_resource = create_web_service_request(
1857 ... '/beta/cookbooks/The%20Joy%20of%20Cooking/name').traverse(app)
1858- >>> print field_resource()
1859+ >>> print(field_resource())
1860 "The Joy of Cooking"
1861
1862 Requesting non available resources
1863@@ -2050,39 +2050,39 @@
1864 matches the hostname you're requesting. If they don't match, your
1865 request will fail.
1866
1867- >>> print change_joy_author(u'http://not.the.same.host' + path)
1868+ >>> print(change_joy_author(u'http://not.the.same.host' + path))
1869 author_link: No such object...
1870
1871 One possible source of hostname mismatches is the HTTP port. If the
1872 web service is served from a strange port, you'll need to specify that
1873 port in the URLs you send.
1874
1875- >>> print change_joy_author(u'http://api.cookbooks.dev' + path,
1876- ... host='api.cookbooks.dev:9000')
1877+ >>> print(change_joy_author(u'http://api.cookbooks.dev' + path,
1878+ ... host='api.cookbooks.dev:9000'))
1879 author_link: No such object...
1880
1881- >>> print change_joy_author(u'http://api.cookbooks.dev:9000' + path,
1882- ... host='api.cookbooks.dev:9000')
1883+ >>> print(change_joy_author(u'http://api.cookbooks.dev:9000' + path,
1884+ ... host='api.cookbooks.dev:9000'))
1885 {...}
1886
1887 You don't have to specify the default port in the URLs you send, even
1888 if you specified it when you made the request.
1889
1890- >>> print change_joy_author(u'http://api.cookbooks.dev' + path,
1891- ... host='api.cookbooks.dev:80')
1892- {...}
1893-
1894- >>> print change_joy_author(u'http://api.cookbooks.dev:80' + path,
1895- ... host='api.cookbooks.dev')
1896- {...}
1897-
1898- >>> print change_joy_author(u'https://api.cookbooks.dev' + path,
1899- ... host='api.cookbooks.dev:443')
1900+ >>> print(change_joy_author(u'http://api.cookbooks.dev' + path,
1901+ ... host='api.cookbooks.dev:80'))
1902+ {...}
1903+
1904+ >>> print(change_joy_author(u'http://api.cookbooks.dev:80' + path,
1905+ ... host='api.cookbooks.dev'))
1906+ {...}
1907+
1908+ >>> print(change_joy_author(u'https://api.cookbooks.dev' + path,
1909+ ... host='api.cookbooks.dev:443'))
1910 author_link: No such object...
1911
1912 >>> webservice_configuration.use_https = True
1913- >>> print change_joy_author(u'https://api.cookbooks.dev' + path,
1914- ... host='api.cookbooks.dev:443')
1915+ >>> print(change_joy_author(u'https://api.cookbooks.dev' + path,
1916+ ... host='api.cookbooks.dev:443'))
1917 {...}
1918 >>> webservice_configuration.use_https = False
1919
1920@@ -2098,7 +2098,7 @@
1921
1922 >>> resource = create_web_service_request(
1923 ... recipe_url, method='GET').traverse(app)
1924- >>> print resource()
1925+ >>> print(resource())
1926 {...}
1927
1928 >>> resource = create_web_service_request(
1929
1930=== modified file 'src/lazr/restful/error.py'
1931--- src/lazr/restful/error.py 2016-02-17 01:07:21 +0000
1932+++ src/lazr/restful/error.py 2020-02-04 11:56:15 +0000
1933@@ -2,6 +2,8 @@
1934
1935 """Error handling on the webservice."""
1936
1937+from __future__ import absolute_import, print_function
1938+
1939 __metaclass__ = type
1940 __all__ = [
1941 'ClientErrorView',
1942
1943=== modified file 'src/lazr/restful/example/base/filemanager.py'
1944--- src/lazr/restful/example/base/filemanager.py 2016-02-17 01:07:21 +0000
1945+++ src/lazr/restful/example/base/filemanager.py 2020-02-04 11:56:15 +0000
1946@@ -2,6 +2,8 @@
1947
1948 """The file manager for the LAZR example web service."""
1949
1950+from __future__ import absolute_import, print_function
1951+
1952 __metaclass__ = type
1953 __all__ = ['FileManager',
1954 'ManagedFileResource']
1955
1956=== modified file 'src/lazr/restful/example/base/interfaces.py'
1957--- src/lazr/restful/example/base/interfaces.py 2018-09-28 15:42:18 +0000
1958+++ src/lazr/restful/example/base/interfaces.py 2020-02-04 11:56:15 +0000
1959@@ -3,6 +3,8 @@
1960
1961 """Interface objects for the LAZR example web service."""
1962
1963+from __future__ import absolute_import, print_function
1964+
1965 __metaclass__ = type
1966 __all__ = ['AlreadyNew',
1967 'Cuisine',
1968
1969=== modified file 'src/lazr/restful/example/base/root.py'
1970--- src/lazr/restful/example/base/root.py 2016-02-17 01:07:21 +0000
1971+++ src/lazr/restful/example/base/root.py 2020-02-04 11:56:15 +0000
1972@@ -2,6 +2,8 @@
1973
1974 """Data model objects for the LAZR example web service."""
1975
1976+from __future__ import absolute_import, print_function
1977+
1978 __metaclass__ = type
1979 __all__ = ['Cookbook',
1980 'CookbookServiceRootResource',
1981
1982=== modified file 'src/lazr/restful/example/base/security.py'
1983--- src/lazr/restful/example/base/security.py 2015-04-08 20:11:29 +0000
1984+++ src/lazr/restful/example/base/security.py 2020-02-04 11:56:15 +0000
1985@@ -2,6 +2,8 @@
1986
1987 """A simple security policy for the LAZR example web service."""
1988
1989+from __future__ import absolute_import, print_function
1990+
1991 __metaclass__ = type
1992 __all__ = [
1993 'CookbookWebServiceSecurityPolicy',
1994
1995=== modified file 'src/lazr/restful/example/base/subscribers.py'
1996--- src/lazr/restful/example/base/subscribers.py 2015-04-08 20:11:29 +0000
1997+++ src/lazr/restful/example/base/subscribers.py 2020-02-04 11:56:15 +0000
1998@@ -2,6 +2,8 @@
1999
2000 """Event listeners for the example web service."""
2001
2002+from __future__ import absolute_import, print_function
2003+
2004 __metaclass__ = type
2005 __all__ = ['update_cookbook_revision_number']
2006
2007
2008=== modified file 'src/lazr/restful/example/base/tests/collection.txt'
2009--- src/lazr/restful/example/base/tests/collection.txt 2019-10-30 11:03:09 +0000
2010+++ src/lazr/restful/example/base/tests/collection.txt 2020-02-04 11:56:15 +0000
2011@@ -40,7 +40,7 @@
2012
2013 There are no XHTML representations available for collections.
2014
2015- >>> print webservice.get('/cookbooks', 'application/xhtml+xml')
2016+ >>> print(webservice.get('/cookbooks', 'application/xhtml+xml'))
2017 HTTP/1.1 200 Ok
2018 ...
2019 Content-Type: application/json
2020@@ -76,7 +76,7 @@
2021 But requesting a batch size higher than the maximum configured value
2022 results in a 400 error.
2023
2024- >>> print webservice.get("/cookbooks?ws.start=0&ws.size=1000")
2025+ >>> print(webservice.get("/cookbooks?ws.start=0&ws.size=1000"))
2026 HTTP/1.1 400 Bad Request
2027 ...
2028 Content-Type: text/plain...
2029@@ -144,15 +144,15 @@
2030
2031 >>> url = quote("/dishes/Roast chicken/recipes")
2032 >>> result = webservice.get(url).jsonBody()
2033- >>> print result['resource_type_link']
2034+ >>> print(result['resource_type_link'])
2035 http://...#recipe-page-resource
2036 >>> cookbooks_with_recipe = sorted(
2037 ... [r['cookbook_link'] for r in result['entries']])
2038 >>> len(cookbooks_with_recipe)
2039 3
2040- >>> print cookbooks_with_recipe[0]
2041+ >>> print(cookbooks_with_recipe[0])
2042 http://.../cookbooks/James%20Beard%27s%20American%20Cookery
2043- >>> print cookbooks_with_recipe[-1]
2044+ >>> print(cookbooks_with_recipe[-1])
2045 http://.../cookbooks/The%20Joy%20of%20Cooking
2046
2047 ================
2048@@ -201,13 +201,13 @@
2049 When an operation yields a collection of objects, the representation
2050 includes a link that yields the total size of the collection.
2051
2052- >>> print s_recipes['total_size_link']
2053+ >>> print(s_recipes['total_size_link'])
2054 http://.../cookbooks?search=chicken&vegetarian=false&ws.op=find_recipes&ws.show=total_size
2055
2056 Sending a GET request to that link yields a JSON representation of the
2057 total size.
2058
2059- >>> print webservice.get(s_recipes['total_size_link']).jsonBody()
2060+ >>> print(webservice.get(s_recipes['total_size_link']).jsonBody())
2061 3
2062
2063 If the entire collection fits in a single 'page' of results, the
2064@@ -239,7 +239,7 @@
2065 Custom operations may have error handling. In this case, the error
2066 handling is in the validate() method of the 'search' field.
2067
2068- >>> print webservice.get("/cookbooks?ws.op=find_recipes")
2069+ >>> print(webservice.get("/cookbooks?ws.op=find_recipes"))
2070 HTTP/1.1 400 Bad Request
2071 ...
2072 search: Required input is missing.
2073@@ -249,7 +249,7 @@
2074 >>> from lazr.restful.testing.helpers import encode_response
2075 >>> url = u"/cookbooks?ws.op=find_for_cuisine&cuisine=%E2%98%83"
2076 >>> response = webservice.get(url.encode("utf-8"))
2077- >>> print encode_response(response)
2078+ >>> print(encode_response(response))
2079 HTTP/1.1 400 Bad Request
2080 ...
2081 cuisine: Invalid value "\u2603". Acceptable values are:...
2082@@ -261,7 +261,7 @@
2083
2084 >>> general_cookbooks = webservice.get(
2085 ... "/cookbooks?ws.op=find_for_cuisine&cuisine=General")
2086- >>> print general_cookbooks.jsonBody()['total_size']
2087+ >>> print(general_cookbooks.jsonBody()['total_size'])
2088 3
2089
2090 POST operations
2091@@ -279,18 +279,18 @@
2092 ... name=name, cuisine=cuisine,
2093 ... copyright_date=date, last_printing=date, price=price)
2094
2095- >>> print webservice.get(quote('/cookbooks/The Cake Bible'))
2096+ >>> print(webservice.get(quote('/cookbooks/The Cake Bible')))
2097 HTTP/1.1 404 Not Found
2098 ...
2099
2100 >>> from datetime import date
2101- >>> print create_cookbook("The Cake Bible", "Dessert", date(1988, 1, 1))
2102+ >>> print(create_cookbook("The Cake Bible", "Dessert", date(1988, 1, 1)))
2103 HTTP/1.1 201 Created
2104 ...
2105 Location: http://.../cookbooks/The%20Cake%20Bible
2106 ...
2107
2108- >>> print webservice.get("/cookbooks/The%20Cake%20Bible")
2109+ >>> print(webservice.get("/cookbooks/The%20Cake%20Bible"))
2110 HTTP/1.1 200 Ok
2111 ...
2112
2113@@ -298,21 +298,21 @@
2114 create a cookbook with a name that's already in use. This exception is
2115 raised by the create() method itself.
2116
2117- >>> print create_cookbook("The Cake Bible", "Dessert", date(1988, 1, 1))
2118+ >>> print(create_cookbook("The Cake Bible", "Dessert", date(1988, 1, 1)))
2119 HTTP/1.1 409 Conflict
2120 ...
2121 A cookbook called "The Cake Bible" already exists.
2122
2123 A POST request has no meaning unless it specifies a custom operation.
2124
2125- >>> print webservice.post("/cookbooks", 'text/plain', '')
2126+ >>> print(webservice.post("/cookbooks", 'text/plain', ''))
2127 HTTP/1.1 400 Bad Request
2128 ...
2129 No operation name given.
2130
2131 You can't invoke a nonexistent operation:
2132
2133- >>> print webservice.named_post("/cookbooks", "nosuchop", {})
2134+ >>> print(webservice.named_post("/cookbooks", "nosuchop", {}))
2135 HTTP/1.1 400 Bad Request
2136 ...
2137 No such operation: nosuchop
2138
2139=== modified file 'src/lazr/restful/example/base/tests/entry.txt'
2140--- src/lazr/restful/example/base/tests/entry.txt 2018-09-28 15:46:34 +0000
2141+++ src/lazr/restful/example/base/tests/entry.txt 2020-02-04 11:56:15 +0000
2142@@ -108,7 +108,7 @@
2143 Every entry has an XHTML representation. The default representation is
2144 a simple definition list.
2145
2146- >>> print webservice.get(greens_url, 'application/xhtml+xml')
2147+ >>> print(webservice.get(greens_url, 'application/xhtml+xml'))
2148 HTTP/1.1 200 Ok
2149 ...
2150 <dl ...>
2151@@ -118,7 +118,7 @@
2152 Getting the XHTML representation works correctly even when some of the fields
2153 have non-ascii values.
2154
2155- >>> print webservice.get(construsions_url, 'application/xhtml+xml')
2156+ >>> print(webservice.get(construsions_url, 'application/xhtml+xml'))
2157 HTTP/1.1 200 Ok
2158 ...
2159 <dl ...>
2160@@ -158,7 +158,7 @@
2161 ...and the XHTML representation of an ICookbook will be the result of
2162 calling a DummyView object.
2163
2164- >>> print webservice.get(greens_url, 'application/xhtml+xml')
2165+ >>> print(webservice.get(greens_url, 'application/xhtml+xml'))
2166 HTTP/1.1 200 Ok
2167 ...
2168 <html>foo</html>
2169@@ -172,7 +172,7 @@
2170 ... required=[ICookbook, IWebServiceClientRequest],
2171 ... provided=IInterface, name=view_name)
2172
2173- >>> print webservice.get(greens_url, 'application/xhtml+xml')
2174+ >>> print(webservice.get(greens_url, 'application/xhtml+xml'))
2175 HTTP/1.1 200 Ok
2176 ...
2177 <dl ...>
2178@@ -185,11 +185,11 @@
2179 There are two recipes in "James Beard's American Cookery", but one of
2180 them has been marked private. The private one cannot be retrieved.
2181
2182- >>> print webservice.get('/recipes/3')
2183+ >>> print(webservice.get('/recipes/3'))
2184 HTTP/1.1 200 Ok
2185 ...
2186
2187- >>> print webservice.get('/recipes/5')
2188+ >>> print(webservice.get('/recipes/5'))
2189 HTTP/1.1 401 Unauthorized
2190 ...
2191
2192@@ -199,9 +199,9 @@
2193 value for the 'confirmed' field is not visible.
2194
2195 >>> cookbook = webservice.get(greens_url).jsonBody()
2196- >>> print cookbook['name']
2197+ >>> print(cookbook['name'])
2198 Everyday Greens
2199- >>> print cookbook['confirmed']
2200+ >>> print(cookbook['confirmed'])
2201 tag:launchpad.net:2008:redacted
2202
2203 Named operations
2204@@ -235,7 +235,7 @@
2205 may be relative to the versioned service root. This is for developer
2206 convenience only, as lazr.restful never serves relative URLs.
2207
2208- >>> print dish_url
2209+ >>> print(dish_url)
2210 http://cookbooks.dev/devel/dishes/Roast%20chicken
2211 >>> relative_url = quote("/dishes/Roast chicken")
2212 >>> find_recipe_in_joy(relative_url)['instructions']
2213@@ -255,22 +255,22 @@
2214 interesting. As a result of the operation, the cookbook's location will
2215 change so we get a 301 response with the new URL.
2216
2217- >>> print webservice.get(joy_url).jsonBody()['cuisine']
2218+ >>> print(webservice.get(joy_url).jsonBody()['cuisine'])
2219 General
2220
2221- >>> print webservice.named_post(joy_url, 'make_more_interesting', {})
2222+ >>> print(webservice.named_post(joy_url, 'make_more_interesting', {}))
2223 HTTP/1.1 301 Moved Permanently
2224 ...
2225 Location: http://cookbooks.dev/devel/cookbooks/The%20New%20The%20Joy%20of%20Cooking
2226 ...
2227
2228 >>> new_joy_url = quote("/cookbooks/The New The Joy of Cooking")
2229- >>> print webservice.get(new_joy_url).jsonBody()['name']
2230+ >>> print(webservice.get(new_joy_url).jsonBody()['name'])
2231 The New The Joy of Cooking
2232
2233 Custom operations may have error handling.
2234
2235- >>> print webservice.named_post(new_joy_url, 'make_more_interesting', {})
2236+ >>> print(webservice.named_post(new_joy_url, 'make_more_interesting', {}))
2237 HTTP/1.1 400 Bad Request
2238 ...
2239 The 'New' trick can't be used on this cookbook because its
2240@@ -283,7 +283,7 @@
2241
2242 Trying to invoke a nonexistent custom operation yields an error.
2243
2244- >>> print webservice.get("%s?ws.op=no_such_operation" % joy_url)
2245+ >>> print(webservice.get("%s?ws.op=no_such_operation" % joy_url))
2246 HTTP/1.1 400 Bad Request
2247 ...
2248 No such operation: no_such_operation
2249@@ -316,12 +316,12 @@
2250 Greens" cookbook. The data returned is the new JSON representation of
2251 the object.
2252
2253- >>> print webservice.get(greens_url).jsonBody()['revision_number']
2254+ >>> print(webservice.get(greens_url).jsonBody()['revision_number'])
2255 0
2256
2257 >>> result = modify_cookbook('Everyday Greens', {'cuisine' : 'American'},
2258 ... 'PATCH')
2259- >>> print result
2260+ >>> print(result)
2261 HTTP/1.1 209 Content Returned
2262 ...
2263 Content-Type: application/json
2264@@ -329,13 +329,13 @@
2265 {...}
2266
2267 >>> greens = result.jsonBody()
2268- >>> print greens['cuisine']
2269+ >>> print(greens['cuisine'])
2270 American
2271
2272 Whenever a client modifies a cookbook, the revision_number is
2273 incremented behind the scenes.
2274
2275- >>> print greens['revision_number']
2276+ >>> print(greens['revision_number'])
2277 1
2278
2279 A modification may cause one of en entry's links to point to another
2280@@ -343,16 +343,16 @@
2281 recipe, turning it into a recipe for baked beans.
2282
2283 >>> old_dish = webservice.get("/recipes/1").jsonBody()['dish_link']
2284- >>> print old_dish
2285+ >>> print(old_dish)
2286 http://.../dishes/Roast%20chicken
2287
2288 >>> new_dish = webservice.get("/recipes/4").jsonBody()['dish_link']
2289- >>> print new_dish
2290+ >>> print(new_dish)
2291 http://.../dishes/Baked%20beans
2292
2293 >>> new_entry = modify_entry(
2294 ... "/recipes/2", {'dish_link' : new_dish}, 'PATCH').jsonBody()
2295- >>> print new_entry['dish_link']
2296+ >>> print(new_entry['dish_link'])
2297 http://.../dishes/Baked%20beans
2298
2299 When changing one of an entry's links, you can use an absolute URL (as
2300@@ -364,14 +364,14 @@
2301 >>> new_entry = modify_entry(
2302 ... "/recipes/2", {'dish_link' : relative_old_dish},
2303 ... 'PATCH').jsonBody()
2304- >>> print new_entry['dish_link']
2305+ >>> print(new_entry['dish_link'])
2306 http://.../dishes/Roast%20chicken
2307
2308 A modification might cause an entry's address to change. Here we use
2309 the web service to change the cookbook's name to 'Everyday Greens 2'.
2310
2311- >>> print modify_cookbook('Everyday Greens',
2312- ... {'name' : 'Everyday Greens 2'}, 'PATCH')
2313+ >>> print(modify_cookbook('Everyday Greens',
2314+ ... {'name' : 'Everyday Greens 2'}, 'PATCH'))
2315 HTTP/1.1 301 Moved Permanently
2316 ...
2317 Location: http://.../Everyday%20Greens%202
2318@@ -384,8 +384,8 @@
2319 the cookbook name back, we need to send a PATCH request to the new
2320 address.
2321
2322- >>> print modify_cookbook('Everyday Greens 2',
2323- ... {'name' : 'Everyday Greens'}, 'PATCH')
2324+ >>> print(modify_cookbook('Everyday Greens 2',
2325+ ... {'name' : 'Everyday Greens'}, 'PATCH'))
2326 HTTP/1.1 301 Moved Permanently
2327 ...
2328 Location: http://.../cookbooks/Everyday%20Greens
2329@@ -398,19 +398,19 @@
2330 also set the X-Content-Type-Override header, which will override the
2331 value of Content-Type.
2332
2333- >>> print modify_cookbook('Everyday Greens',
2334+ >>> print(modify_cookbook('Everyday Greens',
2335 ... {'cuisine' : 'General'}, 'POST',
2336 ... {'X-HTTP-Method-Override' : 'PATCH',
2337 ... 'Content-Type': 'not-a-valid-content/type',
2338- ... 'X-Content-Type-Override': 'application/json'})
2339+ ... 'X-Content-Type-Override': 'application/json'}))
2340 HTTP/1.1 209 Content Returned
2341 ...
2342
2343 Here, the use of a nonexistent HTTP method causes an error.
2344
2345- >>> print modify_cookbook('Everyday Greens',
2346+ >>> print(modify_cookbook('Everyday Greens',
2347 ... {'cuisine' : 'General'}, 'POST',
2348- ... {'X-HTTP-Method-Override' : 'NOSUCHMETHOD'})
2349+ ... {'X-HTTP-Method-Override' : 'NOSUCHMETHOD'}))
2350 HTTP/1.1 405 Method Not Allowed
2351 ...
2352
2353@@ -419,8 +419,8 @@
2354 method, your value is ignored. Here, a nonexistent HTTP method is
2355 ignored in favor of HTTP GET.
2356
2357- >>> print webservice('/cookbooks/Everyday%20Greens', 'GET',
2358- ... headers={'X-HTTP-Method-Override' : 'NOSUCHMETHOD'})
2359+ >>> print(webservice('/cookbooks/Everyday%20Greens', 'GET',
2360+ ... headers={'X-HTTP-Method-Override' : 'NOSUCHMETHOD'}))
2361 HTTP/1.1 200 Ok
2362 ...
2363 Content-Type: application/json
2364@@ -437,24 +437,24 @@
2365 the object that was modified.
2366
2367 >>> greens = webservice.get(greens_url).jsonBody()
2368- >>> print greens['cuisine']
2369+ >>> print(greens['cuisine'])
2370 General
2371
2372 >>> greens['cuisine'] = 'Vegetarian'
2373- >>> print modify_cookbook('Everyday Greens', greens, 'PUT')
2374+ >>> print(modify_cookbook('Everyday Greens', greens, 'PUT'))
2375 HTTP/1.1 209 Content Returned
2376 ...
2377 {...}
2378
2379 >>> greens = webservice.get(greens_url).jsonBody()
2380- >>> print greens['cuisine']
2381+ >>> print(greens['cuisine'])
2382 Vegetarian
2383
2384 Because our patch format is the same as our representation format (a
2385 JSON hash), any document that works with a PUT request will also work
2386 with a PATCH request.
2387
2388- >>> print modify_cookbook('Everyday Greens', greens, 'PATCH')
2389+ >>> print(modify_cookbook('Everyday Greens', greens, 'PATCH'))
2390 HTTP/1.1 209 Content Returned
2391 ...
2392
2393@@ -464,8 +464,8 @@
2394 When making a PATCH, you don't have to get a JSON representation
2395 back. You can also get an HTML representation.
2396
2397- >>> print modify_cookbook('Everyday Greens', {}, 'PATCH',
2398- ... headers={'Accept': 'application/xhtml+xml'})
2399+ >>> print(modify_cookbook('Everyday Greens', {}, 'PATCH',
2400+ ... headers={'Accept': 'application/xhtml+xml'}))
2401 HTTP/1.1 209 Content Returned
2402 ...
2403 Content-Type: application/xhtml+xml
2404@@ -476,8 +476,8 @@
2405 You can even get a WADL representation, though that's pretty useless.
2406
2407 >>> headers = {'Accept':'application/vd.sun.wadl+xml'}
2408- >>> print modify_cookbook('Everyday Greens', {}, 'PATCH',
2409- ... headers=headers)
2410+ >>> print(modify_cookbook('Everyday Greens', {}, 'PATCH',
2411+ ... headers=headers))
2412 HTTP/1.1 209 Content Returned
2413 ...
2414 Content-Type: application/vd.sun.wadl+xml
2415@@ -556,8 +556,8 @@
2416 If-None-Match header. This lets you save time when the resource hasn't
2417 changed.
2418
2419- >>> print webservice.get(greens_url,
2420- ... headers={'If-None-Match': greens_etag})
2421+ >>> print(webservice.get(greens_url,
2422+ ... headers={'If-None-Match': greens_etag}))
2423 HTTP/1.1 304 Not Modified
2424 ...
2425
2426@@ -570,7 +570,7 @@
2427 >>> etag = 'dummy-etag'
2428 >>> response = ajax.get(greens_url, headers={'If-None-Match' : etag})
2429 >>> etag = response.getheader("Etag")
2430- >>> print ajax.get(greens_url, headers={'If-None-Match' : etag})
2431+ >>> print(ajax.get(greens_url, headers={'If-None-Match' : etag}))
2432 HTTP/1.1 304 Not Modified
2433 ...
2434
2435@@ -581,8 +581,8 @@
2436 If the ETag you provide in If-Match matches the entry's current ETag,
2437 your request goes through.
2438
2439- >>> print modify_cookbook('Everyday Greens', greens, 'PATCH',
2440- ... {'If-Match' : greens_etag})
2441+ >>> print(modify_cookbook('Everyday Greens', greens, 'PATCH',
2442+ ... {'If-Match' : greens_etag}))
2443 HTTP/1.1 209 Content Returned
2444 ...
2445
2446@@ -590,8 +590,8 @@
2447 after you got your copy of it. Your request will fail with status code
2448 412.
2449
2450- >>> print modify_cookbook('Everyday Greens', greens, 'PATCH',
2451- ... {'If-Match' : '"an-old-etag"'})
2452+ >>> print(modify_cookbook('Everyday Greens', greens, 'PATCH',
2453+ ... {'If-Match' : '"an-old-etag"'}))
2454 HTTP/1.1 412 Precondition Failed
2455 ...
2456
2457@@ -600,15 +600,15 @@
2458
2459 >>> greens = webservice.get(greens_url).jsonBody()
2460 >>> match = '"an-old-etag", %s' % greens['http_etag']
2461- >>> print modify_cookbook('Everyday Greens', greens, 'PATCH',
2462- ... {'If-Match' : match})
2463+ >>> print(modify_cookbook('Everyday Greens', greens, 'PATCH',
2464+ ... {'If-Match' : match}))
2465 HTTP/1.1 209 Content Returned
2466 ...
2467
2468 Both PUT and PATCH requests work this way.
2469
2470- >>> print modify_cookbook('Everyday Greens', greens, 'PUT',
2471- ... {'If-Match' : 'an-old-etag'})
2472+ >>> print(modify_cookbook('Everyday Greens', greens, 'PUT',
2473+ ... {'If-Match' : 'an-old-etag'}))
2474 HTTP/1.1 412 Precondition Failed
2475 ...
2476
2477@@ -623,7 +623,7 @@
2478 read-only field?
2479
2480 >>> greens = webservice.get(greens_url).jsonBody()
2481- >>> print greens['copyright_date']
2482+ >>> print(greens['copyright_date'])
2483 2003-01-01
2484 >>> etag_before_server_modification = greens['http_etag']
2485
2486@@ -639,7 +639,7 @@
2487 >>> greens_object.copyright_date = datetime.date(2005, 12, 12)
2488
2489 >>> new_greens = webservice.get(greens_url).jsonBody()
2490- >>> print new_greens['copyright_date']
2491+ >>> print(new_greens['copyright_date'])
2492 2005-12-12
2493 >>> etag_after_server_modification = new_greens['http_etag']
2494
2495@@ -652,8 +652,8 @@
2496 fail, right?
2497
2498 >>> body = {'description' : 'New description.'}
2499- >>> print modify_cookbook('Everyday Greens', body, 'PATCH',
2500- ... {'If-Match' : etag_before_server_modification})
2501+ >>> print(modify_cookbook('Everyday Greens', body, 'PATCH',
2502+ ... {'If-Match' : etag_before_server_modification}))
2503 HTTP/1.1 209 Content Returned
2504 ...
2505
2506@@ -690,8 +690,8 @@
2507 ETag will never match anything, you'll always get a 412 error.)
2508
2509 >>> body = {'description' : 'New description.'}
2510- >>> print modify_cookbook('Everyday Greens', body, 'PATCH',
2511- ... {'If-Match' : "Weird etag"})
2512+ >>> print(modify_cookbook('Everyday Greens', body, 'PATCH',
2513+ ... {'If-Match' : "Weird etag"}))
2514 HTTP/1.1 412 Precondition Failed
2515 ...
2516
2517@@ -706,16 +706,16 @@
2518 A totally bogus ETag fails with a 412 error.
2519
2520 >>> greens['description'] = 'Another new description'
2521- >>> print modify_cookbook('Everyday Greens', greens, 'PUT',
2522- ... {'If-Match' : "Not the old ETag"})
2523+ >>> print(modify_cookbook('Everyday Greens', greens, 'PUT',
2524+ ... {'If-Match' : "Not the old ETag"}))
2525 HTTP/1.1 412 Precondition Failed
2526 ...
2527
2528 When we use the original ETag, we don't cause a 412 error, but the PUT
2529 request fails anyway.
2530
2531- >>> print modify_cookbook('Everyday Greens', greens, 'PUT',
2532- ... {'If-Match' : old_etag})
2533+ >>> print(modify_cookbook('Everyday Greens', greens, 'PUT',
2534+ ... {'If-Match' : old_etag}))
2535 HTTP/1.1 400 Bad Request
2536 ...
2537 http_etag: You tried to modify a read-only attribute.
2538@@ -735,15 +735,15 @@
2539
2540 >>> new_etag = webservice.get(greens_url).jsonBody()['http_etag']
2541
2542- >>> print webservice.get(
2543+ >>> print(webservice.get(
2544 ... greens_url,
2545- ... headers={'If-None-Match': new_etag})
2546+ ... headers={'If-None-Match': new_etag}))
2547 HTTP/1.1 304 Not Modified
2548 ...
2549
2550- >>> print webservice.get(
2551+ >>> print(webservice.get(
2552 ... greens_url,
2553- ... headers={'If-None-Match': "changed" + new_etag})
2554+ ... headers={'If-None-Match': "changed" + new_etag}))
2555 HTTP/1.1 200 Ok
2556 ...
2557
2558@@ -767,7 +767,7 @@
2559
2560 >>> recipe_url = '/recipes/3'
2561 >>> recipe = webservice.get(recipe_url).jsonBody()
2562- >>> print recipe['dish_link']
2563+ >>> print(recipe['dish_link'])
2564 http://.../dishes/Roast%20chicken
2565
2566 >>> def modify_dish(url, recipe, new_dish_url):
2567@@ -778,18 +778,18 @@
2568 >>> new_dish = webservice.get(quote('/dishes/Baked beans')).jsonBody()
2569 >>> new_dish_url = new_dish['self_link']
2570 >>> recipe['dish_link'] = new_dish_url
2571- >>> print modify_dish(recipe_url, recipe, new_dish_url)
2572+ >>> print(modify_dish(recipe_url, recipe, new_dish_url))
2573 HTTP/1.1 209 Content Returned
2574 ...
2575
2576 >>> recipe = webservice.get(recipe_url).jsonBody()
2577- >>> print recipe['dish_link']
2578+ >>> print(recipe['dish_link'])
2579 http://.../dishes/Baked%20beans
2580
2581 Identification of the dish is done by specifying a URL; a random
2582 string won't work.
2583
2584- >>> print modify_dish(recipe_url, recipe, 'A random string')
2585+ >>> print(modify_dish(recipe_url, recipe, 'A random string'))
2586 HTTP/1.1 400 Bad Request
2587 ...
2588 dish_link: "A random string" is not a valid URI.
2589@@ -797,14 +797,14 @@
2590 But not just any URL will do. It has to identify an object in the web
2591 service.
2592
2593- >>> print modify_dish(recipe_url, recipe, 'http://www.canonical.com')
2594+ >>> print(modify_dish(recipe_url, recipe, 'http://www.canonical.com'))
2595 HTTP/1.1 400 Bad Request
2596 ...
2597 dish_link: No such object "http://www.canonical.com".
2598
2599- >>> print modify_dish(
2600+ >>> print(modify_dish(
2601 ... recipe_url, recipe,
2602- ... 'http://www.canonical.com/dishes/Baked%20beans')
2603+ ... 'http://www.canonical.com/dishes/Baked%20beans'))
2604 HTTP/1.1 400 Bad Request
2605 ...
2606 dish_link: No such object "http://www.canonical.com/dishes/Baked%20beans".
2607@@ -813,7 +813,7 @@
2608 of HTTP).
2609
2610 >>> https_link = recipe['dish_link'].replace('http:', 'https:')
2611- >>> print modify_dish(recipe_url, recipe, https_link)
2612+ >>> print(modify_dish(recipe_url, recipe, https_link))
2613 HTTP/1.1 400 Bad Request
2614 ...
2615 dish_link: No such object "https://.../Baked%20beans".
2616@@ -822,7 +822,7 @@
2617 the object isn't the right kind of object. A recipe must be for a
2618 dish, not a cookbook:
2619
2620- >>> print modify_dish(recipe_url, recipe, recipe['cookbook_link'])
2621+ >>> print(modify_dish(recipe_url, recipe, recipe['cookbook_link']))
2622 HTTP/1.1 400 Bad Request
2623 ...
2624 dish_link: Your value points to the wrong kind of object
2625@@ -858,53 +858,53 @@
2626 The two 400 error codes below are caused by a failure to understand
2627 the assertion. The string used in the assertion might not be a date.
2628
2629- >>> print patch_greens_copyright_date('dummy')
2630+ >>> print(patch_greens_copyright_date('dummy'))
2631 HTTP/1.1 400 Bad Request
2632 ...
2633 copyright_date: Value doesn't look like a date.
2634
2635 Or it might be a date that's not in UTC.
2636
2637- >>> print patch_greens_copyright_date(u'2005-06-06T00:00:00.000000+05:00')
2638+ >>> print(patch_greens_copyright_date(u'2005-06-06T00:00:00.000000+05:00'))
2639 HTTP/1.1 400 Bad Request
2640 ...
2641 copyright_date: Time not in UTC.
2642
2643 There are five ways to specify UTC:
2644
2645- >>> print patch_greens_copyright_date(u'2003-01-01T00:00:00.000000Z')
2646- HTTP/1.1 209 Content Returned
2647- ...
2648-
2649- >>> print patch_greens_copyright_date(u'2003-01-01T00:00:00.000000+00:00')
2650- HTTP/1.1 209 Content Returned
2651- ...
2652-
2653- >>> print patch_greens_copyright_date(u'2003-01-01T00:00:00.000000+0000')
2654- HTTP/1.1 209 Content Returned
2655- ...
2656-
2657- >>> print patch_greens_copyright_date(u'2003-01-01T00:00:00.000000-00:00')
2658- HTTP/1.1 209 Content Returned
2659- ...
2660-
2661- >>> print patch_greens_copyright_date(u'2003-01-01T00:00:00.000000-0000')
2662+ >>> print(patch_greens_copyright_date(u'2003-01-01T00:00:00.000000Z'))
2663+ HTTP/1.1 209 Content Returned
2664+ ...
2665+
2666+ >>> print(patch_greens_copyright_date(u'2003-01-01T00:00:00.000000+00:00'))
2667+ HTTP/1.1 209 Content Returned
2668+ ...
2669+
2670+ >>> print(patch_greens_copyright_date(u'2003-01-01T00:00:00.000000+0000'))
2671+ HTTP/1.1 209 Content Returned
2672+ ...
2673+
2674+ >>> print(patch_greens_copyright_date(u'2003-01-01T00:00:00.000000-00:00'))
2675+ HTTP/1.1 209 Content Returned
2676+ ...
2677+
2678+ >>> print(patch_greens_copyright_date(u'2003-01-01T00:00:00.000000-0000'))
2679 HTTP/1.1 209 Content Returned
2680 ...
2681
2682 A value with a missing timezone is treated as UTC.
2683
2684- >>> print patch_greens_copyright_date(u'2003-01-01T00:00:00.000000')
2685+ >>> print(patch_greens_copyright_date(u'2003-01-01T00:00:00.000000'))
2686 HTTP/1.1 209 Content Returned
2687 ...
2688
2689 Less precise time measurements may also be acceptable.
2690
2691- >>> print patch_greens_copyright_date(u'2003-01-01T00:00:00Z')
2692+ >>> print(patch_greens_copyright_date(u'2003-01-01T00:00:00Z'))
2693 HTTP/1.1 209 Content Returned
2694 ...
2695
2696- >>> print patch_greens_copyright_date(u'2003-01-01')
2697+ >>> print(patch_greens_copyright_date(u'2003-01-01'))
2698 HTTP/1.1 209 Content Returned
2699 ...
2700
2701@@ -914,30 +914,30 @@
2702 A document that would be acceptable as the payload of a PATCH request
2703 might not be acceptable as the payload of a PUT request.
2704
2705- >>> print modify_cookbook('Everyday Greens', {'name' : 'Greens'}, 'PUT')
2706+ >>> print(modify_cookbook('Everyday Greens', {'name' : 'Greens'}, 'PUT'))
2707 HTTP/1.1 400 Bad Request
2708 ...
2709 You didn't specify a value for the attribute 'description'.
2710
2711 A document that's not a valid JSON document is also unacceptable.
2712
2713- >>> print webservice.patch(greens_url, "application/json", "{")
2714+ >>> print(webservice.patch(greens_url, "application/json", "{"))
2715 HTTP/1.1 400 Bad Request
2716 ...
2717 Entity-body was not a well-formed JSON document.
2718
2719 A document that's valid JSON but is not a JSON hash is unacceptable.
2720
2721- >>> print modify_cookbook('Everyday Greens', 'name=Greens', 'PATCH')
2722+ >>> print(modify_cookbook('Everyday Greens', 'name=Greens', 'PATCH'))
2723 HTTP/1.1 400 Bad Request
2724 ...
2725 Expected a JSON hash.
2726
2727 An entry's read-only attributes can't be modified.
2728
2729- >>> print modify_cookbook(
2730+ >>> print(modify_cookbook(
2731 ... 'Everyday Greens',
2732- ... {'copyright_date' : u'2001-01-01T01:01:01+00:00Z'}, 'PATCH')
2733+ ... {'copyright_date' : u'2001-01-01T01:01:01+00:00Z'}, 'PATCH'))
2734 HTTP/1.1 400 Bad Request
2735 ...
2736 copyright_date: You tried to modify a read-only attribute.
2737@@ -945,17 +945,17 @@
2738 You can send a document that includes a value for a read-only
2739 attribute, but it has to be the same as the current value.
2740
2741- >>> print modify_cookbook(
2742+ >>> print(modify_cookbook(
2743 ... 'Everyday Greens',
2744- ... {'copyright_date' : greens['copyright_date']}, 'PATCH')
2745+ ... {'copyright_date' : greens['copyright_date']}, 'PATCH'))
2746 HTTP/1.1 209 Content Returned
2747 ...
2748
2749 You can't change the link to an entry's associated collection.
2750
2751- >>> print modify_cookbook('Everyday Greens',
2752+ >>> print(modify_cookbook('Everyday Greens',
2753 ... {'recipes_collection_link' : 'dummy'},
2754- ... 'PATCH')
2755+ ... 'PATCH'))
2756 HTTP/1.1 400 Bad Request
2757 ...
2758 recipes_collection_link: You tried to modify a collection...
2759@@ -963,33 +963,33 @@
2760 Again, you can send a document that includes a value for an associated
2761 collection link; you just can't _change_ the value.
2762
2763- >>> print modify_cookbook(
2764+ >>> print(modify_cookbook(
2765 ... 'Everyday Greens',
2766 ... {'recipes_collection_link' : greens['recipes_collection_link']},
2767- ... 'PATCH')
2768+ ... 'PATCH'))
2769 HTTP/1.1 209 Content Returned
2770 ...
2771
2772 You can't directly change an entry's URL address.
2773
2774- >>> print modify_cookbook('Everyday Greens',
2775- ... {'self_link' : 'dummy'}, 'PATCH')
2776+ >>> print(modify_cookbook('Everyday Greens',
2777+ ... {'self_link' : 'dummy'}, 'PATCH'))
2778 HTTP/1.1 400 Bad Request
2779 ...
2780 self_link: You tried to modify a read-only attribute.
2781
2782 You can't directly change an entry's ETag.
2783
2784- >>> print modify_cookbook('Everyday Greens',
2785- ... {'http_etag' : 'dummy'}, 'PATCH')
2786+ >>> print(modify_cookbook('Everyday Greens',
2787+ ... {'http_etag' : 'dummy'}, 'PATCH'))
2788 HTTP/1.1 400 Bad Request
2789 ...
2790 http_etag: You tried to modify a read-only attribute.
2791
2792 You can't change an entry's resource type.
2793
2794- >>> print modify_cookbook('Everyday Greens',
2795- ... {'resource_type_link' : 'dummy'}, 'PATCH')
2796+ >>> print(modify_cookbook('Everyday Greens',
2797+ ... {'resource_type_link' : 'dummy'}, 'PATCH'))
2798 HTTP/1.1 400 Bad Request
2799 ...
2800 resource_type_link: You tried to modify a read-only attribute.
2801@@ -998,8 +998,8 @@
2802 though it were the actual object. A cookbook has a
2803 'recipes_collection_link', but it doesn't have 'recipes' directly.
2804
2805- >>> print modify_cookbook(
2806- ... 'Everyday Greens', {'recipes' : 'dummy'}, 'PATCH')
2807+ >>> print(modify_cookbook(
2808+ ... 'Everyday Greens', {'recipes' : 'dummy'}, 'PATCH'))
2809 HTTP/1.1 400 Bad Request
2810 ...
2811 recipes: You tried to modify a nonexistent attribute.
2812@@ -1007,8 +1007,8 @@
2813 A recipe has a 'dish_link', but it doesn't have a 'dish' directly.
2814
2815 >>> url = quote('/cookbooks/The Joy of Cooking/Roast chicken')
2816- >>> print webservice.patch(url, 'application/json',
2817- ... simplejson.dumps({'dish' : 'dummy'}))
2818+ >>> print(webservice.patch(url, 'application/json',
2819+ ... simplejson.dumps({'dish' : 'dummy'})))
2820 HTTP/1.1 400 Bad Request
2821 ...
2822 dish: You tried to modify a nonexistent attribute.
2823@@ -1016,16 +1016,16 @@
2824 You can't set values that violate data integrity rules. For instance,
2825 you can't set a required value to None.
2826
2827- >>> print modify_cookbook('Everyday Greens',
2828- ... {'name' : None}, 'PATCH')
2829+ >>> print(modify_cookbook('Everyday Greens',
2830+ ... {'name' : None}, 'PATCH'))
2831 HTTP/1.1 400 Bad Request
2832 ...
2833 name: Missing required value.
2834
2835 And of course you can't modify attributes that don't exist.
2836
2837- >>> print modify_cookbook(
2838- ... 'Everyday Greens', {'nonesuch' : 'dummy'}, 'PATCH')
2839+ >>> print(modify_cookbook(
2840+ ... 'Everyday Greens', {'nonesuch' : 'dummy'}, 'PATCH'))
2841 HTTP/1.1 400 Bad Request
2842 ...
2843 nonesuch: You tried to modify a nonexistent attribute.
2844@@ -1037,14 +1037,14 @@
2845 example web service, recipes can be deleted.
2846
2847 >>> recipe_url = "/recipes/6"
2848- >>> print webservice.get(recipe_url)
2849- HTTP/1.1 200 Ok
2850- ...
2851-
2852- >>> print webservice.delete(recipe_url)
2853- HTTP/1.1 200 Ok
2854- ...
2855-
2856- >>> print webservice.get(recipe_url)
2857+ >>> print(webservice.get(recipe_url))
2858+ HTTP/1.1 200 Ok
2859+ ...
2860+
2861+ >>> print(webservice.delete(recipe_url))
2862+ HTTP/1.1 200 Ok
2863+ ...
2864+
2865+ >>> print(webservice.get(recipe_url))
2866 HTTP/1.1 404 Not Found
2867 ...
2868
2869=== modified file 'src/lazr/restful/example/base/tests/field.txt'
2870--- src/lazr/restful/example/base/tests/field.txt 2011-07-27 21:28:35 +0000
2871+++ src/lazr/restful/example/base/tests/field.txt 2020-02-04 11:56:15 +0000
2872@@ -18,10 +18,10 @@
2873 ... return webservice(field_url, 'PATCH',
2874 ... simplejson.dumps(description)).jsonBody()
2875
2876- >>> print set_description("New description")
2877+ >>> print(set_description("New description"))
2878 New description
2879
2880- >>> print webservice.get(field_url)
2881+ >>> print(webservice.get(field_url))
2882 HTTP/1.1 200 Ok
2883 ...
2884 Content-Type: application/json
2885@@ -31,20 +31,20 @@
2886 PATCH on a field resource works identically to PUT.
2887
2888 >>> representation = simplejson.dumps('<b>Bold description</b>')
2889- >>> print webservice.put(field_url, 'application/json',
2890- ... representation).jsonBody()
2891+ >>> print(webservice.put(field_url, 'application/json',
2892+ ... representation).jsonBody())
2893 <b>Bold description</b>
2894
2895 If you get a field that contains a link to another object, you'll see
2896 the link, rather than the actual object.
2897
2898 >>> link_field_url = "/recipes/3/cookbook_link"
2899- >>> print webservice.get(link_field_url).jsonBody()
2900+ >>> print(webservice.get(link_field_url).jsonBody())
2901 http://.../cookbooks/James%20Beard%27s%20American%20Cookery
2902
2903 >>> collection_url = quote(
2904 ... "/cookbooks/The Joy of Cooking/recipes_collection_link")
2905- >>> print webservice.get(collection_url).jsonBody()
2906+ >>> print(webservice.get(collection_url).jsonBody())
2907 http://.../cookbooks/The%20Joy%20of%20Cooking/recipes
2908
2909 Changing a field resource that contains a link works the same way as
2910@@ -52,10 +52,10 @@
2911
2912 >>> new_value = simplejson.dumps(
2913 ... webservice.get(cookbook_url).jsonBody()['self_link'])
2914- >>> print new_value
2915+ >>> print(new_value)
2916 "http://.../cookbooks/The%20Joy%20of%20Cooking"
2917
2918- >>> print webservice(link_field_url, 'PATCH', new_value)
2919+ >>> print(webservice(link_field_url, 'PATCH', new_value))
2920 HTTP/1.1 209 Content Returned
2921 ...
2922 Content-Type: application/json
2923@@ -67,13 +67,13 @@
2924 the entry as a whole or just modifying a single field.
2925
2926 >>> date_field_url = cookbook_url + "/copyright_date"
2927- >>> print webservice.put(date_field_url, 'application/json',
2928- ... simplejson.dumps("string"))
2929+ >>> print(webservice.put(date_field_url, 'application/json',
2930+ ... simplejson.dumps("string")))
2931 HTTP/1.1 400 Bad Request
2932 ...
2933 copyright_date: Value doesn't look like a date.
2934
2935- >>> print webservice(collection_url, 'PATCH', new_value)
2936+ >>> print(webservice(collection_url, 'PATCH', new_value))
2937 HTTP/1.1 400 Bad Request
2938 ...
2939 recipes_collection_link: You tried to modify a collection attribute.
2940@@ -81,10 +81,10 @@
2941 Field resources also support GET, for when you only need part of an
2942 entry. You can get either a JSON or XHTML-fragment representation.
2943
2944- >>> print webservice.get(field_url).jsonBody()
2945+ >>> print(webservice.get(field_url).jsonBody())
2946 <b>Bold description</b>
2947
2948- >>> print webservice.get(field_url, 'application/xhtml+xml')
2949+ >>> print(webservice.get(field_url, 'application/xhtml+xml'))
2950 HTTP/1.1 200 Ok
2951 ...
2952 Content-Type: application/xhtml+xml
2953@@ -104,8 +104,8 @@
2954
2955 >>> name_url = cookbook_url + "/name"
2956 >>> representation = simplejson.dumps("The Joy of Cooking Extreme")
2957- >>> print webservice.put(name_url, 'application/json',
2958- ... representation)
2959+ >>> print(webservice.put(name_url, 'application/json',
2960+ ... representation))
2961 HTTP/1.1 301 Moved Permanently
2962 ...
2963 Location: http://.../cookbooks/The%20Joy%20of%20Cooking%20Extreme/name
2964@@ -113,12 +113,12 @@
2965
2966 Note that the entry's URL has also changed.
2967
2968- >>> print webservice.get(cookbook_url)
2969+ >>> print(webservice.get(cookbook_url))
2970 HTTP/1.1 404 Not Found
2971 ...
2972
2973 >>> new_cookbook_url = quote("/cookbooks/The Joy of Cooking Extreme")
2974- >>> print webservice.get(new_cookbook_url)
2975+ >>> print(webservice.get(new_cookbook_url))
2976 HTTP/1.1 200 Ok
2977 ...
2978
2979@@ -126,8 +126,8 @@
2980
2981 >>> representation = simplejson.dumps("The Joy of Cooking")
2982 >>> new_name_url = new_cookbook_url + "/name"
2983- >>> print webservice.put(new_name_url, 'application/json',
2984- ... representation)
2985+ >>> print(webservice.put(new_name_url, 'application/json',
2986+ ... representation))
2987 HTTP/1.1 301 Moved Permanently
2988 ...
2989 Location: http://.../cookbooks/The%20Joy%20of%20Cooking/name
2990@@ -144,7 +144,7 @@
2991 within the cookbook entry itself.
2992
2993 >>> cookbook = webservice.get(cookbook_url).jsonBody()
2994- >>> print cookbook['cuisine']
2995+ >>> print(cookbook['cuisine'])
2996 General
2997
2998 Here's the representation of the resource for the same 'cuisine' field.
2999@@ -167,8 +167,8 @@
3000 HTML-escaped string, similar to what's seen in the JSON representation
3001 of the entry.
3002
3003- >>> print webservice.get(cookbook_url + '/cuisine',
3004- ... 'application/xhtml+xml')
3005+ >>> print(webservice.get(cookbook_url + '/cuisine',
3006+ ... 'application/xhtml+xml'))
3007 HTTP/1.1 200 Ok
3008 ...
3009 General
3010@@ -180,7 +180,7 @@
3011 Field resources support GET, PUT, and PATCH.
3012
3013 >>> for method in ['HEAD', 'POST', 'DELETE', 'OPTIONS']:
3014- ... print webservice(field_url, method)
3015+ ... print(webservice(field_url, method))
3016 HTTP/1.1 405 Method Not Allowed...
3017 Allow: GET PUT PATCH
3018 ...
3019@@ -210,13 +210,13 @@
3020 >>> cookbook_etag == etag
3021 False
3022
3023- >>> print webservice.get(field_url, headers={'If-None-Match': etag})
3024+ >>> print(webservice.get(field_url, headers={'If-None-Match': etag}))
3025 HTTP/1.1 304 Not Modified
3026 ...
3027
3028 >>> ignored = set_description("new description")
3029- >>> print webservice.get(field_url,
3030- ... headers={'If-None-Match': etag})
3031+ >>> print(webservice.get(field_url,
3032+ ... headers={'If-None-Match': etag}))
3033 HTTP/1.1 200 Ok
3034 ...
3035
3036@@ -234,18 +234,18 @@
3037 provided in If-Match is the one we just got from a GET request.
3038
3039 >>> representation = simplejson.dumps("New description")
3040- >>> print webservice.put(field_url, 'application/json',
3041+ >>> print(webservice.put(field_url, 'application/json',
3042 ... representation,
3043- ... headers={'If-Match': cookbook_etag})
3044+ ... headers={'If-Match': cookbook_etag}))
3045 HTTP/1.1 209 Content Returned
3046 ...
3047
3048 But when the field is modified, the ETag changes. Any subsequent
3049 requests that use that ETag in If-Match will fail.
3050
3051- >>> print webservice.put(field_url, 'application/json',
3052+ >>> print(webservice.put(field_url, 'application/json',
3053 ... representation,
3054- ... headers={'If-Match': cookbook_etag})
3055+ ... headers={'If-Match': cookbook_etag}))
3056 HTTP/1.1 412 Precondition Failed
3057 ...
3058
3059@@ -258,7 +258,7 @@
3060 Every entry has an XHTML representation. The default representation is
3061 a simple text node.
3062
3063- >>> print webservice.get(field_url, 'application/xhtml+xml')
3064+ >>> print(webservice.get(field_url, 'application/xhtml+xml'))
3065 HTTP/1.1 200 Ok
3066 ...
3067 Description
3068@@ -281,7 +281,7 @@
3069 ... """Bold the original string and add a snowman."""
3070 ... return simple_renderer
3071
3072- >>> print webservice.get(cookbook_url +'/name', 'application/xhtml+xml')
3073+ >>> print(webservice.get(cookbook_url +'/name', 'application/xhtml+xml'))
3074 HTTP/1.1 200 Ok
3075 ...
3076 The Joy of Cooking
3077@@ -298,7 +298,7 @@
3078
3079 >>> from lazr.restful.testing.helpers import encode_response
3080 >>> response = webservice.get(field_url, 'application/xhtml+xml')
3081- >>> print encode_response(response)
3082+ >>> print(encode_response(response))
3083 HTTP/1.1 200 Ok
3084 ...
3085 \u2603 <b>Description</b>
3086@@ -306,8 +306,8 @@
3087 In fact, that adapter will be used for every ITextLine field of an
3088 ICookbook.
3089
3090- >>> print encode_response(
3091- ... webservice.get(cookbook_url +'/name', 'application/xhtml+xml'))
3092+ >>> print(encode_response(
3093+ ... webservice.get(cookbook_url +'/name', 'application/xhtml+xml')))
3094 HTTP/1.1 200 Ok
3095 ...
3096 <b>The Joy of Cooking</b>
3097@@ -315,15 +315,15 @@
3098 The adapter will not be used for ITextLine fields of other interfaces:
3099
3100 >>> dish_field_url = quote('/dishes/Roast chicken/name')
3101- >>> print webservice.get(dish_field_url, 'application/xhtml+xml')
3102+ >>> print(webservice.get(dish_field_url, 'application/xhtml+xml'))
3103 HTTP/1.1 200 Ok
3104 ...
3105 Roast chicken
3106
3107 It will not be used for non-text fields of ICookbook.
3108
3109- >>> print webservice.get(cookbook_url + '/copyright_date',
3110- ... 'application/xhtml+xml')
3111+ >>> print(webservice.get(cookbook_url + '/copyright_date',
3112+ ... 'application/xhtml+xml'))
3113 HTTP/1.1 200 Ok
3114 ...
3115 1995-01-01
3116@@ -336,13 +336,13 @@
3117
3118 >>> response = webservice.get(
3119 ... cookbook_url, 'application/json;include=lp_html')
3120- >>> print response.getheader("Content-Type")
3121+ >>> print(response.getheader("Content-Type"))
3122 application/json;include=lp_html
3123
3124 The cookbook's description is a normal JSON representation...
3125
3126 >>> json = response.jsonBody()
3127- >>> print json['description']
3128+ >>> print(json['description'])
3129 Description
3130
3131 ...but the JSON dictionary will include a 'lp_html' sub-dictionary...
3132@@ -356,10 +356,10 @@
3133 [u'description', u'name']
3134
3135 >>> from lazr.restful.testing.helpers import encode_unicode
3136- >>> print encode_unicode(html['description'])
3137+ >>> print(encode_unicode(html['description']))
3138 \u2603 <b>Description</b>
3139
3140- >>> print encode_unicode(html['name'])
3141+ >>> print(encode_unicode(html['name']))
3142 \u2603 <b>The Joy of Cooking</b>
3143
3144 Cleanup
3145@@ -375,7 +375,7 @@
3146
3147 >>> ignored = set_description("<b>Bold description</b>")
3148
3149- >>> print webservice.get(field_url, 'application/xhtml+xml')
3150+ >>> print(webservice.get(field_url, 'application/xhtml+xml'))
3151 HTTP/1.1 200 Ok
3152 ...
3153 &lt;b&gt;Bold description&lt;/b&gt;
3154@@ -409,7 +409,7 @@
3155 returns UTF-8 instead of Unicode.
3156
3157 >>> response = webservice.get(field_url, 'application/xhtml+xml')
3158- >>> print encode_response(response)
3159+ >>> print(encode_response(response))
3160 HTTP/1.1 200 Ok
3161 ...
3162 \u2603 <b>Description</b>
3163@@ -418,7 +418,7 @@
3164 ICookbook/ITextLine, other ITextLine fields of ICookbook are not
3165 affected.
3166
3167- >>> print webservice.get(cookbook_url + '/name', 'application/xhtml+xml')
3168+ >>> print(webservice.get(cookbook_url + '/name', 'application/xhtml+xml'))
3169 HTTP/1.1 200 Ok
3170 ...
3171 The Joy of Cooking
3172@@ -427,7 +427,7 @@
3173 representations of that entry's fields.
3174
3175 >>> response = webservice.get(cookbook_url, 'application/xhtml+xml')
3176- >>> print encode_response(response)
3177+ >>> print(encode_response(response))
3178 HTTP/1.1 200 Ok
3179 ...
3180 <dt>description</dt>
3181@@ -439,7 +439,7 @@
3182 >>> ignored = getGlobalSiteManager().unregisterAdapter(
3183 ... dummy_renderer, name='description')
3184
3185- >>> print webservice.get(field_url, 'application/xhtml+xml')
3186+ >>> print(webservice.get(field_url, 'application/xhtml+xml'))
3187 HTTP/1.1 200 Ok
3188 ...
3189 Description
3190
3191=== modified file 'src/lazr/restful/example/base/tests/hostedfile.txt'
3192--- src/lazr/restful/example/base/tests/hostedfile.txt 2009-11-12 16:35:38 +0000
3193+++ src/lazr/restful/example/base/tests/hostedfile.txt 2020-02-04 11:56:15 +0000
3194@@ -22,14 +22,14 @@
3195 u'http://.../cookbooks/Everyday%20Greens/cover'
3196
3197 >>> greens_cover = greens['cover_link']
3198- >>> print webservice.get(greens_cover)
3199+ >>> print(webservice.get(greens_cover))
3200 HTTP/1.1 404 Not Found
3201 ...
3202
3203 We can upload a cover with PUT.
3204
3205- >>> print webservice.put(greens_cover, 'image/png',
3206- ... "Pretend this is an image file.")
3207+ >>> print(webservice.put(greens_cover, 'image/png',
3208+ ... "Pretend this is an image file."))
3209 HTTP/1.1 200 Ok
3210 ...
3211
3212@@ -38,7 +38,7 @@
3213 Internet.
3214
3215 >>> result = webservice.get(greens_cover)
3216- >>> print result
3217+ >>> print(result)
3218 HTTP/1.1 303 See Other
3219 ...
3220 Location: http://cookbooks.dev/.../filemanager/0
3221@@ -53,7 +53,7 @@
3222
3223 >>> filemanager_url = result.getheader('location')
3224 >>> response = webservice.get(filemanager_url)
3225- >>> print response
3226+ >>> print(response)
3227 HTTP/1.1 200 Ok
3228 ...
3229 Content-Type: image/png
3230@@ -64,7 +64,7 @@
3231 The simple file manager has some nice features like setting the
3232 Content-Disposition, Last-Modified, and ETag headers.
3233
3234- >>> print response.getheader('Content-Disposition')
3235+ >>> print(response.getheader('Content-Disposition'))
3236 attachment; filename="cover"
3237
3238 Note that the name of the file is "cover", the same as the field
3239@@ -79,25 +79,25 @@
3240 Make a second request using the ETag, and you'll get the response code 304
3241 ("Not Modified").
3242
3243- >>> print webservice.get(filemanager_url,
3244- ... headers={'If-None-Match': etag})
3245+ >>> print(webservice.get(filemanager_url,
3246+ ... headers={'If-None-Match': etag}))
3247 HTTP/1.1 304 Not Modified
3248 ...
3249
3250 PUT is also used to modify a hosted file. Here's one that provides a
3251 filename as part of Content-Disposition.
3252
3253- >>> print webservice.put(greens_cover, 'image/png',
3254+ >>> print(webservice.put(greens_cover, 'image/png',
3255 ... "Pretend this is another image file.",
3256 ... {'Content-Disposition':
3257- ... 'attachment; filename="greens-cover.png"'})
3258+ ... 'attachment; filename="greens-cover.png"'}))
3259 HTTP/1.1 200 Ok
3260 ...
3261
3262 The new cover is available at a different URL.
3263
3264 >>> result = webservice.get(greens_cover)
3265- >>> print result
3266+ >>> print(result)
3267 HTTP/1.1 303 See Other
3268 ...
3269 Location: http://cookbooks.dev/.../filemanager/1
3270@@ -107,7 +107,7 @@
3271 back to us in the Content-Disposition header.
3272
3273 >>> filemanager_url = result.getheader('location')
3274- >>> print webservice.get(filemanager_url)
3275+ >>> print(webservice.get(filemanager_url))
3276 HTTP/1.1 200 Ok
3277 ...
3278 Content-Disposition: attachment; filename="greens-cover.png"
3279@@ -118,11 +118,11 @@
3280 real web service to define a more complex named operation that
3281 manipulates uploaded files.
3282
3283- >>> print webservice.named_post(greens_url, 'replace_cover',
3284- ... cover='\x01\x02')
3285+ >>> print(webservice.named_post(greens_url, 'replace_cover',
3286+ ... cover='\x01\x02'))
3287 HTTP/1.1 200 Ok
3288 ...
3289- >>> print webservice.get(greens_cover)
3290+ >>> print(webservice.get(greens_cover))
3291 HTTP/1.1 303 See Other
3292 ...
3293 Location: http://cookbooks.dev/devel/filemanager/2
3294@@ -130,11 +130,11 @@
3295
3296 Deleting a cover (with DELETE) disables the redirect.
3297
3298- >>> print webservice.delete(greens_cover)
3299+ >>> print(webservice.delete(greens_cover))
3300 HTTP/1.1 200 Ok
3301 ...
3302
3303- >>> print webservice.get(greens_cover)
3304+ >>> print(webservice.get(greens_cover))
3305 HTTP/1.1 404 Not Found
3306 ...
3307
3308@@ -148,8 +148,8 @@
3309 >>> greens['cover_link'] = 'http://google.com/logo.png'
3310
3311 >>> import simplejson
3312- >>> print webservice.put(greens_url, 'application/json',
3313- ... simplejson.dumps(greens))
3314+ >>> print(webservice.put(greens_url, 'application/json',
3315+ ... simplejson.dumps(greens)))
3316 HTTP/1.1 400 Bad Request
3317 ...
3318 cover_link: To modify this field you need to send a PUT request to its
3319@@ -159,12 +159,12 @@
3320 delete it.
3321
3322 >>> url = '/recipes/1/prepared_image'
3323- >>> print webservice.put(url, 'application/x-tar-gz', 'fakefiledata')
3324+ >>> print(webservice.put(url, 'application/x-tar-gz', 'fakefiledata'))
3325 HTTP/1.1 405 Method Not Allowed...
3326 Allow: GET
3327 ...
3328
3329- >>> print webservice.delete(url)
3330+ >>> print(webservice.delete(url))
3331 HTTP/1.1 405 Method Not Allowed...
3332 Allow: GET
3333 ...
3334
3335=== modified file 'src/lazr/restful/example/base/tests/redirect.txt'
3336--- src/lazr/restful/example/base/tests/redirect.txt 2011-01-17 23:48:11 +0000
3337+++ src/lazr/restful/example/base/tests/redirect.txt 2020-02-04 11:56:15 +0000
3338@@ -11,7 +11,7 @@
3339 >>> from lazr.restful.testing.webservice import WebServiceCaller
3340 >>> webservice = WebServiceCaller(domain='cookbooks.dev')
3341
3342- >>> print webservice.get("/cookbooks/featured")
3343+ >>> print(webservice.get("/cookbooks/featured"))
3344 HTTP/1.1 301 Moved Permanently
3345 ...
3346 Location: http://.../cookbooks/Mastering%20the%20Art%20of%20French%20Cooking
3347@@ -28,15 +28,15 @@
3348 >>> from lazr.restful.testing.webservice import (
3349 ... WebServiceAjaxCaller)
3350 >>> ajax = WebServiceAjaxCaller(domain='cookbooks.dev')
3351- >>> print ajax.get("/cookbooks/featured")
3352+ >>> print(ajax.get("/cookbooks/featured"))
3353 HTTP/1.1 301 Moved Permanently
3354 ...
3355 Location: http://.../cookbooks/Mastering%20the%20Art%20of%20French%20Cooking?ws.accept=application/json
3356 ...
3357
3358- >>> print ajax.get(
3359+ >>> print(ajax.get(
3360 ... "/cookbooks/featured",
3361- ... headers=dict(Accept="application/xhtml+xml"))
3362+ ... headers=dict(Accept="application/xhtml+xml")))
3363 HTTP/1.1 301 Moved Permanently
3364 ...
3365 Location: http://...?ws.accept=application/xhtml%2Bxml
3366@@ -46,7 +46,7 @@
3367 valid in URIs. In this case, the redirect is to a URL that contains
3368 curly braces (see traversal.py for details).
3369
3370- >>> print ajax.get("/cookbooks/featured-invalid")
3371+ >>> print(ajax.get("/cookbooks/featured-invalid"))
3372 HTTP/1.1 301 Moved Permanently
3373 ...
3374 Location: http://.../Mastering%20the%20Art%20of%20French%20Cooking{invalid}?ws.accept=application/json
3375
3376=== modified file 'src/lazr/restful/example/base/tests/representation-cache.txt'
3377--- src/lazr/restful/example/base/tests/representation-cache.txt 2010-06-14 15:24:20 +0000
3378+++ src/lazr/restful/example/base/tests/representation-cache.txt 2020-02-04 11:56:15 +0000
3379@@ -41,13 +41,13 @@
3380
3381 >>> from lazr.restful.example.base.root import C4 as greens_object
3382 >>> json = "application/json"
3383- >>> print cache.get(greens_object, json, "devel")
3384+ >>> print(cache.get(greens_object, json, "devel"))
3385 None
3386- >>> print cache.get(greens_object, json, "devel", "missing")
3387+ >>> print(cache.get(greens_object, json, "devel", "missing"))
3388 missing
3389
3390 >>> cache.set(greens_object, json, "devel", "This is the 'devel' value.")
3391- >>> print cache.get(greens_object, json, "devel")
3392+ >>> print(cache.get(greens_object, json, "devel"))
3393 This is the 'devel' value.
3394 >>> sorted(dictionary.keys())
3395 ['http://cookbooks.dev/devel/cookbooks/Everyday%20Greens,application/json']
3396@@ -56,7 +56,7 @@
3397 for different versions.
3398
3399 >>> cache.set(greens_object, json, "1.0", "This is the '1.0' value.")
3400- >>> print cache.get(greens_object, json, "1.0")
3401+ >>> print(cache.get(greens_object, json, "1.0"))
3402 This is the '1.0' value.
3403 >>> sorted(dictionary.keys())
3404 ['http://cookbooks.dev/1.0/cookbooks/Everyday%20Greens,application/json',
3405@@ -67,9 +67,9 @@
3406 >>> cache.delete(greens_object)
3407 >>> sorted(dictionary.keys())
3408 []
3409- >>> print cache.get(greens_object, json, "devel")
3410+ >>> print(cache.get(greens_object, json, "devel"))
3411 None
3412- >>> print cache.get(greens_object, json, "1.0")
3413+ >>> print(cache.get(greens_object, json, "1.0"))
3414 None
3415
3416 DO_NOT_CACHE
3417@@ -103,7 +103,7 @@
3418 >>> test_cache.set("Don't cache this.", json, "cache everything!",
3419 ... "representation")
3420 >>> for key in sorted(test_dict.keys()):
3421- ... print key
3422+ ... print(key)
3423 Cache this.,application/json,1.0
3424 Don't cache this.,application/json,cache everything!
3425
3426@@ -112,7 +112,7 @@
3427
3428 >>> bad_key = "Don't cache this.,application/json,1.0"
3429 >>> test_dict[bad_key] = "This representation should not be cached."
3430- >>> print test_cache.get("Don't cache this.", json, "1.0")
3431+ >>> print(test_cache.get("Don't cache this.", json, "1.0"))
3432 None
3433
3434 A representation cache
3435@@ -135,7 +135,7 @@
3436 >>> recipe_url = "/recipes/1"
3437 >>> ignored = webservice.get(recipe_url)
3438 >>> [the_only_key] = dictionary.keys()
3439- >>> print the_only_key
3440+ >>> print(the_only_key)
3441 http://cookbooks.dev/devel/recipes/1,application/json
3442
3443 Note that the cache key incorporates the web service version name
3444@@ -145,7 +145,7 @@
3445 Associated with the key is a string: the JSON representation of the object.
3446
3447 >>> import simplejson
3448- >>> print simplejson.loads(dictionary[the_only_key])['self_link']
3449+ >>> print(simplejson.loads(dictionary[the_only_key])['self_link'])
3450 http://cookbooks.dev/devel/recipes/1
3451
3452 If we get a representation of the same resource from a different web
3453@@ -153,7 +153,7 @@
3454
3455 >>> ignored = webservice.get(recipe_url, api_version="1.0")
3456 >>> for key in sorted(dictionary.keys()):
3457- ... print key
3458+ ... print(key)
3459 http://cookbooks.dev/1.0/recipes/1,application/json
3460 http://cookbooks.dev/devel/recipes/1,application/json
3461
3462@@ -174,14 +174,14 @@
3463
3464 >>> old_instructions = webservice.get(
3465 ... recipe_url, api_version='devel').jsonBody()['instructions']
3466- >>> print old_instructions
3467+ >>> print(old_instructions)
3468 You can always judge...
3469 >>> response = webservice.patch(recipe_url, 'application/json',
3470 ... simplejson.dumps(dict(instructions="New instructions")),
3471 ... api_version='devel')
3472- >>> print response.status
3473+ >>> print(response.status)
3474 209
3475- >>> print response.jsonBody()['instructions']
3476+ >>> print(response.jsonBody()['instructions'])
3477 New instructions
3478
3479 The modified representation is immediately available in the cache.
3480@@ -189,7 +189,7 @@
3481 >>> from lazr.restful.example.base.root import RECIPES
3482 >>> recipe = [recipe for recipe in RECIPES if recipe.id == 1][0]
3483 >>> cached_representation = cache.get(recipe, json, 'devel')
3484- >>> print simplejson.loads(cached_representation)['instructions']
3485+ >>> print(simplejson.loads(cached_representation)['instructions'])
3486 New instructions
3487
3488 Cleanup.
3489@@ -206,14 +206,14 @@
3490 >>> cookbook = [cookbook for cookbook in COOKBOOKS
3491 ... if cookbook.name == "Everyday Greens"][0]
3492 >>> cache.set(cookbook, json, 'devel', "Dummy value.")
3493- >>> print dictionary.keys()[0]
3494+ >>> print(dictionary.keys()[0])
3495 http://.../devel/cookbooks/Everyday%20Greens,application/json
3496
3497 >>> from urllib import quote
3498 >>> greens_url = quote("/cookbooks/Everyday Greens")
3499 >>> ignore = webservice.named_post(
3500 ... greens_url, "replace_cover", cover="foo")
3501- >>> print len(dictionary.keys())
3502+ >>> print(len(dictionary.keys()))
3503 0
3504
3505 But unless the web service is the only way to manipulate a data set,
3506@@ -231,13 +231,13 @@
3507 the cache's delete() method.
3508
3509 >>> ignore = webservice.get(recipe_url, api_version='devel')
3510- >>> print cache.get(recipe, json, 'devel')
3511+ >>> print(cache.get(recipe, json, 'devel'))
3512 {...}
3513 >>> cache.delete(recipe)
3514
3515 This deletes all the relevant representations.
3516
3517- >>> print cache.get(recipe, json, 'devel')
3518+ >>> print(cache.get(recipe, json, 'devel'))
3519 None
3520 >>> dictionary.keys()
3521 []
3522@@ -251,7 +251,7 @@
3523 representation is not added to the cache.
3524
3525 >>> greens = webservice.get(greens_url).jsonBody()
3526- >>> print greens['confirmed']
3527+ >>> print(greens['confirmed'])
3528 tag:launchpad.net:2008:redacted
3529
3530 >>> dictionary.keys()
3531@@ -274,12 +274,12 @@
3532 definitely comes from the cache, not the original data source.
3533
3534 >>> cached_greens = webservice.get(greens_url).jsonBody()
3535- >>> print cached_greens['name']
3536+ >>> print(cached_greens['name'])
3537 This comes from the cache; it is not generated.
3538
3539 But the redacted value is still redacted.
3540
3541- >>> print cached_greens['confirmed']
3542+ >>> print(cached_greens['confirmed'])
3543 tag:launchpad.net:2008:redacted
3544
3545 Cleanup: clear the cache.
3546@@ -294,7 +294,7 @@
3547
3548 >>> recipe_url ="/recipes/5"
3549 >>> response = webservice.get(recipe_url)
3550- >>> print response.status
3551+ >>> print(response.status)
3552 401
3553 >>> len(dictionary.keys())
3554 0
3555@@ -306,7 +306,7 @@
3556 >>> from lazr.restful.example.base.root import C3_D2 as recipe
3557 >>> recipe.private = False
3558
3559- >>> print webservice.get("/recipes/5").jsonBody()['instructions']
3560+ >>> print(webservice.get("/recipes/5").jsonBody()['instructions'])
3561 Without doubt the most famous...
3562
3563 Now there's a representation in the cache.
3564@@ -321,7 +321,7 @@
3565
3566 >>> recipe.private = True
3567 >>> response = webservice.get(recipe_url)
3568- >>> print response.status
3569+ >>> print(response.status)
3570 401
3571
3572 Cleanup: clear the cache.
3573@@ -351,7 +351,7 @@
3574
3575 >>> for instructions in (
3576 ... sorted(recipe['instructions'] for recipe in recipes)):
3577- ... print instructions
3578+ ... print(instructions)
3579 A perfectly roasted chicken is...
3580 Draw, singe, stuff, and truss...
3581 ...
3582@@ -362,7 +362,7 @@
3583 populated the cache.
3584
3585 >>> for key in sorted(dictionary.keys()):
3586- ... print key
3587+ ... print(key)
3588 http://cookbooks.dev/devel/recipes/1,application/json
3589 http://cookbooks.dev/devel/recipes/2,application/json
3590 http://cookbooks.dev/devel/recipes/3,application/json
3591@@ -379,7 +379,7 @@
3592 >>> recipes = webservice.get("/recipes").jsonBody()['entries']
3593 >>> for instructions in (
3594 ... sorted(recipe['instructions'] for recipe in recipes)):
3595- ... print instructions
3596+ ... print(instructions)
3597 This representation is from the cache.
3598 This representation is from the cache.
3599 This representation is from the cache.
3600@@ -394,7 +394,7 @@
3601
3602 >>> from lazr.restful.interfaces import IWebServiceConfiguration
3603 >>> config = getUtility(IWebServiceConfiguration)
3604- >>> print config.enable_server_side_representation_cache
3605+ >>> print(config.enable_server_side_representation_cache)
3606 True
3607
3608 Set this configuration value to False, and representations will not be
3609@@ -404,7 +404,7 @@
3610 >>> recipes = webservice.get("/recipes").jsonBody()['entries']
3611 >>> for instructions in (
3612 ... sorted(recipe['instructions'] for recipe in recipes)):
3613- ... print instructions
3614+ ... print(instructions)
3615 A perfectly roasted chicken is...
3616 Draw, singe, stuff, and truss...
3617 Preheat oven to...
3618@@ -419,7 +419,7 @@
3619
3620 The cache is still registered as a utility.
3621
3622- >>> print getUtility(IRepresentationCache)
3623+ >>> print(getUtility(IRepresentationCache))
3624 <lazr.restful.simple.DictionaryBasedRepresentationCache object ...>
3625
3626 And it's still populated, as we can see by re-enabling it.
3627@@ -428,7 +428,7 @@
3628 >>> recipes = webservice.get("/recipes").jsonBody()['entries']
3629 >>> for instructions in (
3630 ... sorted(recipe['instructions'] for recipe in recipes)):
3631- ... print instructions
3632+ ... print(instructions)
3633 This representation is from the cache.
3634 This representation is from the cache.
3635 This representation is from the cache.
3636@@ -454,7 +454,7 @@
3637 >>> recipes = webservice.get("/recipes").jsonBody()['entries']
3638 >>> for instructions in (
3639 ... sorted(recipe['instructions'] for recipe in recipes)):
3640- ... print instructions
3641+ ... print(instructions)
3642 A perfectly roasted chicken is...
3643 Draw, singe, stuff, and truss...
3644 Preheat oven to...
3645
3646=== modified file 'src/lazr/restful/example/base/tests/root.txt'
3647--- src/lazr/restful/example/base/tests/root.txt 2010-05-10 11:48:42 +0000
3648+++ src/lazr/restful/example/base/tests/root.txt 2020-02-04 11:56:15 +0000
3649@@ -17,7 +17,7 @@
3650 >>> top_level_links['cookbooks_collection_link']
3651 u'http://cookbooks.dev/devel/cookbooks'
3652
3653- >>> print top_level_links['resource_type_link']
3654+ >>> print(top_level_links['resource_type_link'])
3655 http://cookbooks.dev/devel/#service-root
3656
3657 The client can explore the entire web service by following these links
3658@@ -29,7 +29,7 @@
3659
3660 There is no XHTML representation available for the service root.
3661
3662- >>> print webservice.get('/', 'application/xhtml+xml')
3663+ >>> print(webservice.get('/', 'application/xhtml+xml'))
3664 HTTP/1.1 200 Ok
3665 ...
3666 Content-Type: application/json
3667@@ -40,7 +40,7 @@
3668 HEAD and OPTIONS.
3669
3670 >>> for method in ['HEAD', 'POST', 'PUT', 'DELETE', 'OPTIONS']:
3671- ... print webservice("/", method)
3672+ ... print(webservice("/", method))
3673 HTTP/1.1 405 Method Not Allowed...
3674 Allow: GET
3675 ...
3676@@ -110,7 +110,7 @@
3677 root. The cookbook web service has a 'featured cookbook' which may
3678 change over time.
3679
3680- >>> print top_level_links['featured_cookbook_link']
3681+ >>> print(top_level_links['featured_cookbook_link'])
3682 http://.../cookbooks/featured
3683
3684 Caching policy
3685@@ -121,13 +121,13 @@
3686 service root can be cached for a long time:
3687
3688 >>> response = webservice.get('/', api_version='1.0')
3689- >>> print response.getheader('Cache-Control')
3690+ >>> print(response.getheader('Cache-Control'))
3691 max-age=10000
3692
3693 The latest version of the service root should be cached for less time.
3694
3695 >>> response = webservice.get('/', api_version='devel')
3696- >>> print response.getheader('Cache-Control')
3697+ >>> print(response.getheader('Cache-Control'))
3698 max-age=2
3699
3700 Both the WADL and JSON representations of the service root are
3701@@ -135,7 +135,7 @@
3702
3703 >>> wadl_type = 'application/vnd.sun.wadl+xml'
3704 >>> response = webservice.get('/', wadl_type)
3705- >>> print response.getheader('Cache-Control')
3706+ >>> print(response.getheader('Cache-Control'))
3707 max-age=2
3708
3709 The Date header is set along with Cache-Control so that the client can
3710@@ -152,7 +152,7 @@
3711 ... '/', wadl_type, headers={'If-None-Match' : etag})
3712 >>> conditional_response.status
3713 304
3714- >>> print conditional_response.getheader('Cache-Control')
3715+ >>> print(conditional_response.getheader('Cache-Control'))
3716 max-age=2
3717 >>> conditional_response.getheader('Date') is None
3718 False
3719@@ -166,9 +166,9 @@
3720 >>> agent = 'Python-httplib2/$Rev: 259$'
3721 >>> response = webservice.get(
3722 ... '/', wadl_type, headers={'User-Agent' : agent})
3723- >>> print response.getheader('Cache-Control')
3724+ >>> print(response.getheader('Cache-Control'))
3725 None
3726- >>> print response.getheader('Date')
3727+ >>> print(response.getheader('Date'))
3728 None
3729
3730 If the client identifies as an agent _based on_ httplib2, we take a
3731@@ -177,7 +177,7 @@
3732 >>> agent = "Custom client (%s)" % agent
3733 >>> response = webservice.get(
3734 ... '/', wadl_type, headers={'User-Agent' : agent})
3735- >>> print response.getheader('Cache-Control')
3736+ >>> print(response.getheader('Cache-Control'))
3737 max-age=2
3738 >>> response.getheader('Date') is None
3739 False
3740@@ -192,7 +192,7 @@
3741 >>> policy[-1] = 0
3742
3743 >>> response = webservice.get('/')
3744- >>> print response.getheader('Cache-Control')
3745+ >>> print(response.getheader('Cache-Control'))
3746 None
3747 >>> response.getheader('Date') is None
3748 True
3749
3750=== modified file 'src/lazr/restful/example/base/tests/service.txt'
3751--- src/lazr/restful/example/base/tests/service.txt 2009-11-16 14:25:45 +0000
3752+++ src/lazr/restful/example/base/tests/service.txt 2020-02-04 11:56:15 +0000
3753@@ -17,7 +17,7 @@
3754
3755 >>> top_level_response = webservice.get(
3756 ... "/", api_version="devel").jsonBody()
3757- >>> print top_level_response['resource_type_link']
3758+ >>> print(top_level_response['resource_type_link'])
3759 http://cookbooks.dev/devel/#service-root
3760
3761 The web service in examples/multiversion is devoted solely to testing
3762@@ -28,18 +28,18 @@
3763
3764 An attempt to access a nonexistent resource yields a 404 error.
3765
3766- >>> print webservice.get("/no-such-resource")
3767+ >>> print(webservice.get("/no-such-resource"))
3768 HTTP/1.1 404 Not Found
3769 ...
3770
3771 An attempt to access an existing resource without versioning the URL
3772 yields a 404 error.
3773
3774- >>> print webservice.get("/cookbooks", api_version="/")
3775+ >>> print(webservice.get("/cookbooks", api_version="/"))
3776 HTTP/1.1 404 Not Found
3777 ...
3778
3779- >>> print webservice.get("/", api_version="/")
3780+ >>> print(webservice.get("/", api_version="/"))
3781 HTTP/1.1 404 Not Found
3782 ...
3783
3784@@ -49,23 +49,23 @@
3785 An attempt to use an unsupported or nonexistent HTTP method on a
3786 resource yields a 405 error.
3787
3788- >>> print webservice("/", method="COPY")
3789+ >>> print(webservice("/", method="COPY"))
3790 HTTP/1.1 405 Method Not Allowed...
3791 Allow: GET
3792 ...
3793
3794- >>> print webservice.delete("/cookbooks")
3795+ >>> print(webservice.delete("/cookbooks"))
3796 HTTP/1.1 405 Method Not Allowed...
3797 Allow: GET POST
3798 ...
3799
3800 >>> from urllib import quote
3801- >>> print webservice.delete(quote("/dishes/Roast chicken"))
3802+ >>> print(webservice.delete(quote("/dishes/Roast chicken")))
3803 HTTP/1.1 405 Method Not Allowed...
3804 Allow: GET PUT PATCH
3805 ...
3806
3807- >>> print webservice.delete(quote("/cookbooks/The Joy of Cooking"))
3808+ >>> print(webservice.delete(quote("/cookbooks/The Joy of Cooking")))
3809 HTTP/1.1 405 Method Not Allowed...
3810 Allow: GET PUT PATCH POST
3811 ...
3812@@ -76,18 +76,18 @@
3813 An attempt to PATCH a document with unsupported media type to a
3814 resource yields a 415 error.
3815
3816- >>> print webservice.patch("/recipes/1", 'text/plain', "Foo")
3817+ >>> print(webservice.patch("/recipes/1", 'text/plain', "Foo"))
3818 HTTP/1.1 415 Unsupported Media Type
3819 ...
3820
3821 The only supported media types are ones that begin with 'application/json'.
3822
3823- >>> print webservice.patch("/recipes/1", 'application/json', "{}")
3824+ >>> print(webservice.patch("/recipes/1", 'application/json', "{}"))
3825 HTTP/1.1 209 Content Returned
3826 ...
3827
3828- >>> print webservice.patch(
3829- ... "/recipes/1", 'application/json; charset=UTF-8', "{}")
3830+ >>> print(webservice.patch(
3831+ ... "/recipes/1", 'application/json; charset=UTF-8', "{}"))
3832 HTTP/1.1 209 Content Returned
3833 ...
3834
3835
3836=== modified file 'src/lazr/restful/example/base/tests/test_integration.py'
3837--- src/lazr/restful/example/base/tests/test_integration.py 2018-09-28 15:34:25 +0000
3838+++ src/lazr/restful/example/base/tests/test_integration.py 2020-02-04 11:56:15 +0000
3839@@ -2,6 +2,8 @@
3840
3841 """Test harness for LAZR doctests."""
3842
3843+from __future__ import absolute_import, print_function
3844+
3845 __metaclass__ = type
3846 __all__ = []
3847
3848@@ -45,7 +47,12 @@
3849 [name
3850 for name in os.listdir(os.path.dirname(__file__))
3851 if name.endswith('.txt')])
3852- suite = doctest.DocFileSuite(optionflags=DOCTEST_FLAGS, *doctest_files)
3853+ globs = {
3854+ 'absolute_import': absolute_import,
3855+ 'print_function': print_function,
3856+ }
3857+ suite = doctest.DocFileSuite(
3858+ *doctest_files, optionflags=DOCTEST_FLAGS, globs=globs)
3859 suite.layer = WSGILayer
3860 tests.addTest(suite)
3861 return tests
3862
3863=== modified file 'src/lazr/restful/example/base/tests/wadl.txt'
3864--- src/lazr/restful/example/base/tests/wadl.txt 2018-09-28 15:42:49 +0000
3865+++ src/lazr/restful/example/base/tests/wadl.txt 2020-02-04 11:56:15 +0000
3866@@ -21,7 +21,7 @@
3867
3868 It's an XML document.
3869
3870- >>> print wadl
3871+ >>> print(wadl)
3872 <?xml version="1.0"?>
3873 <wadl:application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3874 xmlns="http://research.sun.com/wadl/2006/10"
3875@@ -180,7 +180,7 @@
3876 A cookbook starts out with no hosted cover, and an ordinary
3877 GET to the place where the cover would be results in a 404 error.
3878
3879- >>> print webservice.get(entry_url + '/cover')
3880+ >>> print(webservice.get(entry_url + '/cover'))
3881 HTTP/1.1 404 Not Found
3882 ...
3883
3884@@ -264,17 +264,17 @@
3885 ... if not isinstance(child, _Comment)]
3886
3887 >>> service_doc, version_doc = children[:2]
3888- >>> print service_doc.attrib['title']
3889+ >>> print(service_doc.attrib['title'])
3890 About this service
3891 >>> for p_tag in service_doc:
3892- ... print p_tag.text
3893+ ... print(p_tag.text)
3894 This is a web service.
3895 It's got resources!
3896
3897- >>> print version_doc.attrib['title']
3898+ >>> print(version_doc.attrib['title'])
3899 About version devel
3900 >>> for p_tag in version_doc:
3901- ... print p_tag.text
3902+ ... print(p_tag.text)
3903 The unstable development version.
3904 Don't use this unless you like changing things.
3905
3906@@ -397,7 +397,7 @@
3907
3908 >>> resources.tag
3909 '...resources'
3910- >>> print resources.attrib['base']
3911+ >>> print(resources.attrib['base'])
3912 http://cookbooks.dev/devel/
3913
3914 As with the <resources> tags shown earlier, this one contains a single
3915@@ -746,7 +746,7 @@
3916 >>> doc = copyright_date[0]
3917 >>> doc.tag
3918 '...doc'
3919- >>> print "\n".join([node.text for node in doc])
3920+ >>> print("\n".join([node.text for node in doc]))
3921 Copyright Date
3922 The copyright date for this work.
3923
3924
3925=== modified file 'src/lazr/restful/example/base/traversal.py'
3926--- src/lazr/restful/example/base/traversal.py 2015-04-08 20:11:29 +0000
3927+++ src/lazr/restful/example/base/traversal.py 2020-02-04 11:56:15 +0000
3928@@ -2,6 +2,8 @@
3929
3930 """Traversal rules for the LAZR example web service."""
3931
3932+from __future__ import absolute_import, print_function
3933+
3934 __metaclass__ = type
3935 __all__ = [
3936 'BelowRootAbsoluteURL',
3937
3938=== modified file 'src/lazr/restful/example/base_extended/README.txt'
3939--- src/lazr/restful/example/base_extended/README.txt 2010-08-05 13:12:00 +0000
3940+++ src/lazr/restful/example/base_extended/README.txt 2020-02-04 11:56:15 +0000
3941@@ -14,7 +14,7 @@
3942
3943 And as we can see below, a recipe's representation now include its comments.
3944
3945- >>> print "\n".join(webservice.get('/recipes/1').jsonBody()['comments'])
3946+ >>> print("\n".join(webservice.get('/recipes/1').jsonBody()['comments']))
3947 Comment 1
3948 Comment 2
3949
3950
3951=== modified file 'src/lazr/restful/example/base_extended/comments.py'
3952--- src/lazr/restful/example/base_extended/comments.py 2016-02-17 01:07:21 +0000
3953+++ src/lazr/restful/example/base_extended/comments.py 2020-02-04 11:56:15 +0000
3954@@ -1,3 +1,5 @@
3955+from __future__ import absolute_import, print_function
3956+
3957 from zope.component import adapter
3958 from zope.interface import implementer, Interface
3959 from zope.schema import List, Text
3960
3961=== modified file 'src/lazr/restful/example/base_extended/tests/test_integration.py'
3962--- src/lazr/restful/example/base_extended/tests/test_integration.py 2018-09-28 15:34:25 +0000
3963+++ src/lazr/restful/example/base_extended/tests/test_integration.py 2020-02-04 11:56:15 +0000
3964@@ -2,6 +2,8 @@
3965
3966 """Test harness for LAZR doctests."""
3967
3968+from __future__ import absolute_import, print_function
3969+
3970 __metaclass__ = type
3971 __all__ = []
3972
3973@@ -33,7 +35,12 @@
3974 def load_tests(loader, tests, pattern):
3975 """See `zope.testing.testrunner`."""
3976 doctest_files = ['../README.txt']
3977- suite = doctest.DocFileSuite(optionflags=DOCTEST_FLAGS, *doctest_files)
3978+ globs = {
3979+ 'absolute_import': absolute_import,
3980+ 'print_function': print_function,
3981+ }
3982+ suite = doctest.DocFileSuite(
3983+ *doctest_files, optionflags=DOCTEST_FLAGS, globs=globs)
3984 suite.layer = WSGILayer
3985 tests.addTest(suite)
3986 return tests
3987
3988=== modified file 'src/lazr/restful/example/multiversion/resources.py'
3989--- src/lazr/restful/example/multiversion/resources.py 2016-02-17 01:07:21 +0000
3990+++ src/lazr/restful/example/multiversion/resources.py 2020-02-04 11:56:15 +0000
3991@@ -1,3 +1,5 @@
3992+from __future__ import absolute_import, print_function
3993+
3994 __metaclass__ = type
3995
3996 __all__ = ['IKeyValuePair',
3997
3998=== modified file 'src/lazr/restful/example/multiversion/root.py'
3999--- src/lazr/restful/example/multiversion/root.py 2010-08-18 15:33:46 +0000
4000+++ src/lazr/restful/example/multiversion/root.py 2020-02-04 11:56:15 +0000
4001@@ -1,5 +1,7 @@
4002 """The RESTful service root."""
4003
4004+from __future__ import absolute_import, print_function
4005+
4006 __metaclass__ = type
4007 __all__ = [
4008 'BelowRootAbsoluteURL',
4009
4010=== modified file 'src/lazr/restful/example/multiversion/tests/introduction.txt'
4011--- src/lazr/restful/example/multiversion/tests/introduction.txt 2011-02-01 00:57:27 +0000
4012+++ src/lazr/restful/example/multiversion/tests/introduction.txt 2020-02-04 11:56:15 +0000
4013@@ -19,22 +19,22 @@
4014
4015 >>> top_level_response = webservice.get(
4016 ... "/", api_version="beta").jsonBody()
4017- >>> print top_level_response['key_value_pairs_collection_link']
4018+ >>> print(top_level_response['key_value_pairs_collection_link'])
4019 http://multiversion.dev/beta/pairs
4020
4021 >>> top_level_response = webservice.get(
4022 ... "/", api_version="1.0").jsonBody()
4023- >>> print top_level_response['key_value_pairs_collection_link']
4024+ >>> print(top_level_response['key_value_pairs_collection_link'])
4025 http://multiversion.dev/1.0/pairs
4026
4027 >>> top_level_response = webservice.get(
4028 ... "/", api_version="2.0").jsonBody()
4029- >>> print top_level_response['key_value_pairs_collection_link']
4030+ >>> print(top_level_response['key_value_pairs_collection_link'])
4031 http://multiversion.dev/2.0/pairs
4032
4033 >>> top_level_response = webservice.get(
4034 ... "/", api_version="3.0").jsonBody()
4035- >>> print top_level_response['key_value_pairs_collection_link']
4036+ >>> print(top_level_response['key_value_pairs_collection_link'])
4037 http://multiversion.dev/3.0/pairs
4038
4039 Like all web services, the multiversion service also serves a
4040@@ -46,7 +46,7 @@
4041
4042 >>> top_level_response = webservice.get(
4043 ... "/", api_version="trunk").jsonBody()
4044- >>> print top_level_response['key_value_pairs_collection_link']
4045+ >>> print(top_level_response['key_value_pairs_collection_link'])
4046 http://multiversion.dev/trunk/pairs
4047
4048 All versions of the web service can be accessed through Ajax.
4049@@ -55,16 +55,16 @@
4050 >>> ajax = WebServiceAjaxCaller(domain='multiversion.dev')
4051
4052 >>> body = ajax.get('/', api_version="1.0").jsonBody()
4053- >>> print body['resource_type_link']
4054+ >>> print(body['resource_type_link'])
4055 http://multiversion.dev/1.0/#service-root
4056
4057 >>> body = ajax.get('/', api_version="trunk").jsonBody()
4058- >>> print body['resource_type_link']
4059+ >>> print(body['resource_type_link'])
4060 http://multiversion.dev/trunk/#service-root
4061
4062 An attempt to access a nonexistent version yields a 404 error.
4063
4064- >>> print webservice.get('/', api_version="no_such_version")
4065+ >>> print(webservice.get('/', api_version="no_such_version"))
4066 HTTP/1.1 404 Not Found
4067 ...
4068
4069@@ -79,7 +79,7 @@
4070 >>> def show_pairs(version):
4071 ... body = webservice.get('/pairs', api_version=version).jsonBody()
4072 ... for entry in sorted(body['entries'], key=itemgetter('key')):
4073- ... print "%s: %s" % (entry['key'], entry['value'])
4074+ ... print("%s: %s" % (entry['key'], entry['value']))
4075
4076 >>> show_pairs('beta')
4077 1: 2
4078@@ -140,13 +140,13 @@
4079
4080 >>> get_comment('1.0')
4081 u''
4082- >>> print change_comment('I changed 1.0', '1.0')
4083+ >>> print(change_comment('I changed 1.0', '1.0'))
4084 I changed 1.0 (modified by mutator #1)
4085
4086- >>> print change_comment('I changed 2.0', '2.0')
4087+ >>> print(change_comment('I changed 2.0', '2.0'))
4088 I changed 2.0 (modified by mutator #1)
4089
4090- >>> print change_comment('I changed 3.0', '3.0')
4091+ >>> print(change_comment('I changed 3.0', '3.0'))
4092 I changed 3.0 (modified by mutator #2)
4093
4094 You can try to modify the 'comment' field from a version that doesn't
4095@@ -154,7 +154,7 @@
4096
4097 >>> change_comment('I changed beta', 'beta', False)
4098
4099- >>> print get_comment('1.0')
4100+ >>> print(get_comment('1.0'))
4101 I changed 3.0 (modified by mutator #2)
4102
4103 A field called 'deleted' is published starting in version '3.0'. A
4104@@ -165,7 +165,7 @@
4105 ... entry_body = webservice.get(
4106 ... '/pairs/foo', api_version=version).jsonBody()
4107 ... for key in sorted(entry_body.keys()):
4108- ... print key
4109+ ... print(key)
4110
4111 >>> show_fields('beta')
4112 a_comment
4113@@ -244,11 +244,11 @@
4114 If an entry field is not published in a certain version, the
4115 corresponding field resource does not exist for that version.
4116
4117- >>> print webservice.get('/pairs/foo/deleted', api_version='beta').body
4118+ >>> print(webservice.get('/pairs/foo/deleted', api_version='beta').body)
4119 Object: <...>, name: u'deleted'
4120
4121- >>> print webservice.get(
4122- ... '/pairs/foo/deleted', api_version='3.0').jsonBody()
4123+ >>> print(webservice.get(
4124+ ... '/pairs/foo/deleted', api_version='3.0').jsonBody())
4125 False
4126
4127 Named operations
4128@@ -267,12 +267,12 @@
4129 The named operation is not published at all in the 'beta' version of
4130 the web service.
4131
4132- >>> print show_value("beta", 'byValue')
4133+ >>> print(show_value("beta", 'byValue'))
4134 Traceback (most recent call last):
4135 ...
4136 ValueError: No such operation: byValue
4137
4138- >>> print show_value("beta", 'by_value')
4139+ >>> print(show_value("beta", 'by_value'))
4140 Traceback (most recent call last):
4141 ...
4142 ValueError: No such operation: by_value
4143@@ -280,12 +280,12 @@
4144 In the '1.0' and '2.0' versions, the named operation is published as
4145 'byValue'. 'by_value' does not work.
4146
4147- >>> print show_value("1.0", 'byValue')
4148+ >>> print(show_value("1.0", 'byValue'))
4149 foo
4150
4151- >>> print show_value("2.0", 'byValue')
4152+ >>> print(show_value("2.0", 'byValue'))
4153 foo
4154- >>> print show_value("2.0", 'by_value')
4155+ >>> print(show_value("2.0", 'by_value'))
4156 Traceback (most recent call last):
4157 ...
4158 ValueError: No such operation: by_value
4159@@ -293,10 +293,10 @@
4160 In the '3.0' version, the named operation is published as
4161 'by_value'. 'byValue' does not work.
4162
4163- >>> print show_value("3.0", "by_value")
4164+ >>> print(show_value("3.0", "by_value"))
4165 foo
4166
4167- >>> print show_value("3.0", 'byValue')
4168+ >>> print(show_value("3.0", 'byValue'))
4169 Traceback (most recent call last):
4170 ...
4171 ValueError: No such operation: byValue
4172@@ -304,12 +304,12 @@
4173 In the 'trunk' version, the named operation has been removed. Neither
4174 'byValue' nor 'by_value' work.
4175
4176- >>> print show_value("trunk", 'byValue')
4177+ >>> print(show_value("trunk", 'byValue'))
4178 Traceback (most recent call last):
4179 ...
4180 ValueError: No such operation: byValue
4181
4182- >>> print show_value("trunk", 'by_value')
4183+ >>> print(show_value("trunk", 'by_value'))
4184 Traceback (most recent call last):
4185 ...
4186 ValueError: No such operation: by_value
4187
4188=== modified file 'src/lazr/restful/example/multiversion/tests/operation.txt'
4189--- src/lazr/restful/example/multiversion/tests/operation.txt 2018-09-28 15:39:53 +0000
4190+++ src/lazr/restful/example/multiversion/tests/operation.txt 2020-02-04 11:56:15 +0000
4191@@ -21,7 +21,7 @@
4192 >>> from zope.component import getUtility
4193 >>> from lazr.restful.interfaces import IWebServiceConfiguration
4194 >>> config = getUtility(IWebServiceConfiguration)
4195- >>> print config.first_version_with_total_size_link
4196+ >>> print(config.first_version_with_total_size_link)
4197 2.0
4198
4199 When the 'byValue' operation is invoked in version 1.0, it always returns a
4200@@ -31,30 +31,30 @@
4201 ... url = '/pairs?ws.op=%s&value=%s&ws.size=%s' % (op, value, size)
4202 ... return webservice.get(url, api_version=version).jsonBody()
4203
4204- >>> print sorted(get_collection('1.0').keys())
4205+ >>> print(sorted(get_collection('1.0').keys()))
4206 [u'entries', u'next_collection_link', u'start', u'total_size']
4207
4208 The operation itself doesn't change between 1.0 and 2.0, but in
4209 version 2.0, the operation starts returning total_size_link.
4210
4211- >>> print sorted(get_collection('2.0').keys())
4212+ >>> print(sorted(get_collection('2.0').keys()))
4213 [u'entries', u'next_collection_link', u'start', u'total_size_link']
4214
4215 The same happens in 3.0.
4216
4217- >>> print sorted(get_collection('3.0', 'by_value').keys())
4218+ >>> print(sorted(get_collection('3.0', 'by_value').keys()))
4219 [u'entries', u'next_collection_link', u'start', u'total_size_link']
4220
4221 However, if the total size is easy to calculate (for instance, because
4222 all the results fit on one page), a total_size is returned instead of
4223 total_size_link.
4224
4225- >>> print sorted(get_collection('3.0', 'by_value', size=100).keys())
4226+ >>> print(sorted(get_collection('3.0', 'by_value', size=100).keys()))
4227 [u'entries', u'start', u'total_size']
4228
4229 >>> for key, value in sorted(
4230 ... get_collection('3.0', 'by_value', 'no-such-value').items()):
4231- ... print '%s: %s' % (key, value)
4232+ ... print('%s: %s' % (key, value))
4233 entries: []
4234 start: 0
4235 total_size: 0
4236@@ -69,7 +69,7 @@
4237 In the example web service, mutator methods are published as named
4238 operations in the 'beta' and '1.0' versions.
4239
4240- >>> print config.last_version_with_mutator_named_operations
4241+ >>> print(config.last_version_with_mutator_named_operations)
4242 1.0
4243
4244 If you look at the definition of IKeyValuePair in
4245@@ -93,11 +93,11 @@
4246
4247 In version 'beta', the 'a_comment' field has no mutator at all.
4248
4249- >>> print call_mutator("beta")
4250+ >>> print(call_mutator("beta"))
4251 HTTP/1.1 405 Method Not Allowed
4252 ...
4253
4254- >>> print call_mutator("beta", op="comment_mutator_2")
4255+ >>> print(call_mutator("beta", op="comment_mutator_2"))
4256 HTTP/1.1 405 Method Not Allowed
4257 ...
4258
4259@@ -105,14 +105,14 @@
4260 'a_comment'. Because mutators are published as named operation in
4261 version '1.0', we can also invoke the mutator method directly.
4262
4263- >>> print call_mutator("1.0", "comment_mutator_1")
4264+ >>> print(call_mutator("1.0", "comment_mutator_1"))
4265 HTTP/1.1 200 Ok
4266 ...
4267
4268 'comment_mutator_2' still doesn't work, because it's not the mutator
4269 for 'a_comment' in version '1.0'.
4270
4271- >>> print call_mutator("1.0", "comment_mutator_2")
4272+ >>> print(call_mutator("1.0", "comment_mutator_2"))
4273 HTTP/1.1 400 Bad Request
4274 ...
4275
4276@@ -125,7 +125,7 @@
4277 for 'a_comment', but mutators are no longer published as named
4278 operations, so we can no longer invoke the mutator method directly.
4279
4280- >>> print call_mutator("2.0")
4281+ >>> print(call_mutator("2.0"))
4282 HTTP/1.1 405 Method Not Allowed
4283 ...
4284
4285@@ -137,6 +137,6 @@
4286 for 'a_comment'. But since version '3.0' is after version '1.0', that
4287 method is not published as a named operation.
4288
4289- >>> print call_mutator("3.0", "comment_mutator_2")
4290+ >>> print(call_mutator("3.0", "comment_mutator_2"))
4291 HTTP/1.1 405 Method Not Allowed
4292 ...
4293
4294=== modified file 'src/lazr/restful/example/multiversion/tests/test_integration.py'
4295--- src/lazr/restful/example/multiversion/tests/test_integration.py 2018-09-28 15:34:25 +0000
4296+++ src/lazr/restful/example/multiversion/tests/test_integration.py 2020-02-04 11:56:15 +0000
4297@@ -2,6 +2,8 @@
4298
4299 """Test harness for doctests for lazr.restful multiversion example service."""
4300
4301+from __future__ import absolute_import, print_function
4302+
4303 __metaclass__ = type
4304 __all__ = []
4305
4306@@ -48,7 +50,12 @@
4307 [name
4308 for name in os.listdir(os.path.dirname(__file__))
4309 if name.endswith('.txt')])
4310- suite = doctest.DocFileSuite(optionflags=DOCTEST_FLAGS, *doctest_files)
4311+ globs = {
4312+ 'absolute_import': absolute_import,
4313+ 'print_function': print_function,
4314+ }
4315+ suite = doctest.DocFileSuite(
4316+ *doctest_files, optionflags=DOCTEST_FLAGS, globs=globs)
4317 suite.layer = WSGILayer
4318 tests.addTest(suite)
4319 return tests
4320
4321=== modified file 'src/lazr/restful/example/multiversion/tests/wadl.txt'
4322--- src/lazr/restful/example/multiversion/tests/wadl.txt 2010-08-05 14:08:20 +0000
4323+++ src/lazr/restful/example/multiversion/tests/wadl.txt 2020-02-04 11:56:15 +0000
4324@@ -40,10 +40,10 @@
4325 is not present at all.
4326
4327 >>> contents = wadl_contents_for_version('beta')
4328- >>> print contents['version_doc'].attrib['title']
4329+ >>> print(contents['version_doc'].attrib['title'])
4330 About version beta
4331
4332- >>> print contents['base'].attrib['base']
4333+ >>> print(contents['base'].attrib['base'])
4334 http://multiversion.dev/beta/
4335
4336 >>> pair_collection = contents['pair_collection']
4337@@ -62,9 +62,9 @@
4338 In '2.0', the by_value method is called 'byValue'.
4339
4340 >>> contents = wadl_contents_for_version('2.0')
4341- >>> print contents['version_doc'].attrib['title']
4342+ >>> print(contents['version_doc'].attrib['title'])
4343 About version 2.0
4344- >>> print contents['base'].attrib['base']
4345+ >>> print(contents['base'].attrib['base'])
4346 http://multiversion.dev/2.0/
4347
4348 >>> pair_collection = contents['pair_collection']
4349@@ -74,9 +74,9 @@
4350 In '3.0', the method changes its name to 'by_value'.
4351
4352 >>> contents = wadl_contents_for_version('3.0')
4353- >>> print contents['version_doc'].attrib['title']
4354+ >>> print(contents['version_doc'].attrib['title'])
4355 About version 3.0
4356- >>> print contents['base'].attrib['base']
4357+ >>> print(contents['base'].attrib['base'])
4358 http://multiversion.dev/3.0/
4359
4360 >>> pair_collection = contents['pair_collection']
4361@@ -86,7 +86,7 @@
4362 In 'trunk', the method disappears.
4363
4364 >>> contents = wadl_contents_for_version('trunk')
4365- >>> print contents['base'].attrib['base']
4366+ >>> print(contents['base'].attrib['base'])
4367 http://multiversion.dev/trunk/
4368
4369 >>> pair_collection = contents['pair_collection']
4370
4371=== modified file 'src/lazr/restful/example/wsgi/resources.py'
4372--- src/lazr/restful/example/wsgi/resources.py 2016-02-17 01:07:21 +0000
4373+++ src/lazr/restful/example/wsgi/resources.py 2020-02-04 11:56:15 +0000
4374@@ -1,3 +1,5 @@
4375+from __future__ import absolute_import, print_function
4376+
4377 __metaclass__ = type
4378
4379 __all__ = ['IKeyValuePair',
4380
4381=== modified file 'src/lazr/restful/example/wsgi/root.py'
4382--- src/lazr/restful/example/wsgi/root.py 2010-02-25 17:07:16 +0000
4383+++ src/lazr/restful/example/wsgi/root.py 2020-02-04 11:56:15 +0000
4384@@ -1,5 +1,7 @@
4385 """The RESTful service root."""
4386
4387+from __future__ import absolute_import, print_function
4388+
4389 __metaclass__ = type
4390 __all__ = [
4391 'BelowRootAbsoluteURL',
4392
4393=== modified file 'src/lazr/restful/example/wsgi/run.py'
4394--- src/lazr/restful/example/wsgi/run.py 2009-09-03 19:42:04 +0000
4395+++ src/lazr/restful/example/wsgi/run.py 2020-02-04 11:56:15 +0000
4396@@ -1,4 +1,7 @@
4397 #!/usr/bin/python
4398+
4399+from __future__ import absolute_import, print_function
4400+
4401 from lazr.restful.wsgi import WSGIApplication
4402
4403 if __name__ == '__main__':
4404
4405=== modified file 'src/lazr/restful/example/wsgi/tests/introduction.txt'
4406--- src/lazr/restful/example/wsgi/tests/introduction.txt 2011-01-21 18:09:15 +0000
4407+++ src/lazr/restful/example/wsgi/tests/introduction.txt 2020-02-04 11:56:15 +0000
4408@@ -19,7 +19,7 @@
4409 >>> links = sorted([entry['self_link']
4410 ... for entry in collection_resource['entries']])
4411 >>> for link in links:
4412- ... print link
4413+ ... print(link)
4414 http://wsgidemo.dev/1.0/1
4415 http://wsgidemo.dev/1.0/foo
4416
4417@@ -32,5 +32,5 @@
4418
4419 You can get a field resource.
4420
4421- >>> print webservice.get("/pairs/foo/value").jsonBody()
4422+ >>> print(webservice.get("/pairs/foo/value").jsonBody())
4423 bar
4424
4425=== modified file 'src/lazr/restful/example/wsgi/tests/test_integration.py'
4426--- src/lazr/restful/example/wsgi/tests/test_integration.py 2018-09-28 15:34:25 +0000
4427+++ src/lazr/restful/example/wsgi/tests/test_integration.py 2020-02-04 11:56:15 +0000
4428@@ -2,6 +2,8 @@
4429
4430 """Test harness for doctests for lazr.restful example WSGI service."""
4431
4432+from __future__ import absolute_import, print_function
4433+
4434 __metaclass__ = type
4435 __all__ = []
4436
4437@@ -45,7 +47,12 @@
4438 [name
4439 for name in os.listdir(os.path.dirname(__file__))
4440 if name.endswith('.txt')])
4441- suite = doctest.DocFileSuite(optionflags=DOCTEST_FLAGS, *doctest_files)
4442+ globs = {
4443+ 'absolute_import': absolute_import,
4444+ 'print_function': print_function,
4445+ }
4446+ suite = doctest.DocFileSuite(
4447+ *doctest_files, optionflags=DOCTEST_FLAGS, globs=globs)
4448 suite.layer = WSGILayer
4449 tests.addTest(suite)
4450 return tests
4451
4452=== modified file 'src/lazr/restful/fields.py'
4453--- src/lazr/restful/fields.py 2016-02-17 01:07:21 +0000
4454+++ src/lazr/restful/fields.py 2020-02-04 11:56:15 +0000
4455@@ -2,6 +2,8 @@
4456
4457 """LAZR zope.schema.IField implementation."""
4458
4459+from __future__ import absolute_import, print_function
4460+
4461 __metaclass__ = type
4462 __all__ = [
4463 'CollectionField',
4464
4465=== modified file 'src/lazr/restful/interface.py'
4466--- src/lazr/restful/interface.py 2009-03-26 17:25:22 +0000
4467+++ src/lazr/restful/interface.py 2020-02-04 11:56:15 +0000
4468@@ -2,6 +2,8 @@
4469
4470 """Helpers for working with Zope interface."""
4471
4472+from __future__ import absolute_import, print_function
4473+
4474 __metaclass__ = type
4475 __all__ = [
4476 'copy_attribute',
4477
4478=== modified file 'src/lazr/restful/interfaces/__init__.py'
4479--- src/lazr/restful/interfaces/__init__.py 2009-03-26 17:25:22 +0000
4480+++ src/lazr/restful/interfaces/__init__.py 2020-02-04 11:56:15 +0000
4481@@ -17,6 +17,8 @@
4482
4483 # pylint: disable-msg=W0401
4484
4485+from __future__ import absolute_import, print_function
4486+
4487 __version__ = 1.0
4488
4489 # Re-export in such a way that __version__ can still be imported if
4490
4491=== modified file 'src/lazr/restful/interfaces/_fields.py'
4492--- src/lazr/restful/interfaces/_fields.py 2011-01-19 22:29:32 +0000
4493+++ src/lazr/restful/interfaces/_fields.py 2020-02-04 11:56:15 +0000
4494@@ -16,6 +16,8 @@
4495
4496 """Interfaces for LAZR zope.schema fields."""
4497
4498+from __future__ import absolute_import, print_function
4499+
4500 __metaclass__ = type
4501 __all__ = [
4502 'ICollectionField',
4503
4504=== modified file 'src/lazr/restful/interfaces/_rest.py'
4505--- src/lazr/restful/interfaces/_rest.py 2011-03-31 01:13:59 +0000
4506+++ src/lazr/restful/interfaces/_rest.py 2020-02-04 11:56:15 +0000
4507@@ -18,6 +18,8 @@
4508 # Pylint doesn't grok zope interfaces.
4509 # pylint: disable-msg=E0211,E0213
4510
4511+from __future__ import absolute_import, print_function
4512+
4513 __metaclass__ = type
4514 __all__ = [
4515 'IByteStorage',
4516
4517=== modified file 'src/lazr/restful/jsoncache.py'
4518--- src/lazr/restful/jsoncache.py 2016-02-17 01:07:21 +0000
4519+++ src/lazr/restful/jsoncache.py 2020-02-04 11:56:15 +0000
4520@@ -2,6 +2,8 @@
4521 #
4522 """A class for storing resources where they can be seen by a template."""
4523
4524+from __future__ import absolute_import, print_function
4525+
4526 __metaclass__ = type
4527
4528 __all__ = [
4529
4530=== modified file 'src/lazr/restful/marshallers.py'
4531--- src/lazr/restful/marshallers.py 2018-11-15 15:29:42 +0000
4532+++ src/lazr/restful/marshallers.py 2020-02-04 11:56:15 +0000
4533@@ -2,6 +2,8 @@
4534
4535 """Marshallers for fields used in HTTP resources."""
4536
4537+from __future__ import absolute_import, print_function
4538+
4539 __metaclass__ = type
4540 __all__ = [
4541 'AbstractCollectionFieldMarshaller',
4542
4543=== modified file 'src/lazr/restful/metazcml.py'
4544--- src/lazr/restful/metazcml.py 2019-11-04 13:51:46 +0000
4545+++ src/lazr/restful/metazcml.py 2020-02-04 11:56:15 +0000
4546@@ -2,6 +2,8 @@
4547
4548 """ZCML registration directives for the LAZR webservice framework."""
4549
4550+from __future__ import absolute_import, print_function
4551+
4552 __metaclass__ = type
4553 __all__ = []
4554
4555
4556=== modified file 'src/lazr/restful/publisher.py'
4557--- src/lazr/restful/publisher.py 2019-11-04 17:35:37 +0000
4558+++ src/lazr/restful/publisher.py 2020-02-04 11:56:15 +0000
4559@@ -6,6 +6,8 @@
4560 with the Zope publisher.
4561 """
4562
4563+from __future__ import absolute_import, print_function
4564+
4565 __metaclass__ = type
4566 __all__ = [
4567 'browser_request_to_web_service_request',
4568
4569=== modified file 'src/lazr/restful/security.py'
4570--- src/lazr/restful/security.py 2009-03-26 17:25:22 +0000
4571+++ src/lazr/restful/security.py 2020-02-04 11:56:15 +0000
4572@@ -2,6 +2,8 @@
4573
4574 """Utilities for dealing with zope security."""
4575
4576+from __future__ import absolute_import, print_function
4577+
4578 __metaclass__ = type
4579 __all__ = [
4580 'protect_schema',
4581
4582=== modified file 'src/lazr/restful/simple.py'
4583--- src/lazr/restful/simple.py 2016-02-17 01:07:21 +0000
4584+++ src/lazr/restful/simple.py 2020-02-04 11:56:15 +0000
4585@@ -1,5 +1,7 @@
4586 """Simple implementations of various Zope and lazr.restful interfaces."""
4587
4588+from __future__ import absolute_import, print_function
4589+
4590 __metaclass__ = type
4591 __all__ = [
4592 'BaseRepresentationCache',
4593
4594=== modified file 'src/lazr/restful/tales.py'
4595--- src/lazr/restful/tales.py 2018-02-21 14:46:13 +0000
4596+++ src/lazr/restful/tales.py 2020-02-04 11:56:15 +0000
4597@@ -2,6 +2,8 @@
4598 #
4599 """Implementation of the ws: namespace in TALES."""
4600
4601+from __future__ import absolute_import, print_function
4602+
4603 __metaclass__ = type
4604
4605 all = ['entry_adapter_for_schema']
4606
4607=== modified file 'src/lazr/restful/testing/event.py'
4608--- src/lazr/restful/testing/event.py 2009-04-02 15:44:00 +0000
4609+++ src/lazr/restful/testing/event.py 2020-02-04 11:56:15 +0000
4610@@ -2,6 +2,8 @@
4611
4612 """Helper class for checking the event notifications."""
4613
4614+from __future__ import absolute_import, print_function
4615+
4616 __metaclass__ = type
4617
4618 import zope.component
4619
4620=== modified file 'src/lazr/restful/testing/helpers.py'
4621--- src/lazr/restful/testing/helpers.py 2016-02-17 01:07:21 +0000
4622+++ src/lazr/restful/testing/helpers.py 2020-02-04 11:56:15 +0000
4623@@ -1,3 +1,5 @@
4624+from __future__ import absolute_import, print_function
4625+
4626 import sys
4627 from types import ModuleType
4628
4629
4630=== modified file 'src/lazr/restful/testing/tales.py'
4631--- src/lazr/restful/testing/tales.py 2019-11-12 14:26:41 +0000
4632+++ src/lazr/restful/testing/tales.py 2020-02-04 11:56:15 +0000
4633@@ -2,6 +2,8 @@
4634
4635 """Helper functions for testing TALES expressions."""
4636
4637+from __future__ import absolute_import, print_function
4638+
4639 __metaclass__ = type
4640
4641 __all__ = [
4642
4643=== modified file 'src/lazr/restful/testing/webservice.py'
4644--- src/lazr/restful/testing/webservice.py 2016-02-17 01:07:21 +0000
4645+++ src/lazr/restful/testing/webservice.py 2020-02-04 11:56:15 +0000
4646@@ -2,6 +2,8 @@
4647
4648 """Testing helpers for webservice unit tests."""
4649
4650+from __future__ import absolute_import, print_function
4651+
4652 __metaclass__ = type
4653 __all__ = [
4654 'create_web_service_request',
4655@@ -176,7 +178,7 @@
4656 """
4657 for key, value in sorted(json_body.items()):
4658 if key != 'http_etag':
4659- print '%s: %r' % (key, value)
4660+ print('%s: %r' % (key, value))
4661
4662
4663 def pprint_collection(json_body):
4664@@ -185,11 +187,11 @@
4665 if key == 'total_size_link':
4666 continue
4667 if key != 'entries':
4668- print '%s: %r' % (key, value)
4669- print '---'
4670+ print('%s: %r' % (key, value))
4671+ print('---')
4672 for entry in json_body['entries']:
4673 pprint_entry(entry)
4674- print '---'
4675+ print('---')
4676
4677
4678 class WebServiceTestPublication(Publication):
4679
4680=== modified file 'src/lazr/restful/tests/test_declarations.py'
4681--- src/lazr/restful/tests/test_declarations.py 2019-11-04 17:35:37 +0000
4682+++ src/lazr/restful/tests/test_declarations.py 2020-02-04 11:56:15 +0000
4683@@ -2,6 +2,8 @@
4684
4685 """Unit tests for the conversion of interfaces into a web service."""
4686
4687+from __future__ import absolute_import, print_function
4688+
4689 import testtools
4690 from zope.component import (
4691 adapter,
4692
4693=== modified file 'src/lazr/restful/tests/test_docs.py'
4694--- src/lazr/restful/tests/test_docs.py 2019-11-04 09:54:43 +0000
4695+++ src/lazr/restful/tests/test_docs.py 2020-02-04 11:56:15 +0000
4696@@ -17,6 +17,8 @@
4697
4698 # pylint: disable=E0611,W0142
4699
4700+from __future__ import absolute_import, print_function
4701+
4702 __metaclass__ = type
4703 __all__ = []
4704
4705@@ -50,7 +52,11 @@
4706 os.path.abspath(
4707 resource_filename('lazr.restful', 'docs/%s' % name)))
4708 atexit.register(cleanup_resources)
4709+ globs = {
4710+ 'absolute_import': absolute_import,
4711+ 'print_function': print_function,
4712+ }
4713 tests.addTest(doctest.DocFileSuite(
4714 *doctest_files, module_relative=False, optionflags=DOCTEST_FLAGS,
4715- tearDown=tearDown))
4716+ tearDown=tearDown, globs=globs))
4717 return tests
4718
4719=== modified file 'src/lazr/restful/tests/test_error.py'
4720--- src/lazr/restful/tests/test_error.py 2018-09-28 15:34:25 +0000
4721+++ src/lazr/restful/tests/test_error.py 2020-02-04 11:56:15 +0000
4722@@ -2,6 +2,8 @@
4723
4724 """Tests of lazr.restful navigation."""
4725
4726+from __future__ import absolute_import, print_function
4727+
4728 __metaclass__ = type
4729
4730 from pkg_resources import resource_filename
4731
4732=== modified file 'src/lazr/restful/tests/test_etag.py'
4733--- src/lazr/restful/tests/test_etag.py 2016-02-17 00:49:58 +0000
4734+++ src/lazr/restful/tests/test_etag.py 2020-02-04 11:56:15 +0000
4735@@ -1,6 +1,8 @@
4736 # Copyright 2008 Canonical Ltd. All rights reserved.
4737 """Tests for ETag generation."""
4738
4739+from __future__ import absolute_import, print_function
4740+
4741 __metaclass__ = type
4742
4743 import unittest
4744
4745=== modified file 'src/lazr/restful/tests/test_navigation.py'
4746--- src/lazr/restful/tests/test_navigation.py 2018-09-28 15:34:25 +0000
4747+++ src/lazr/restful/tests/test_navigation.py 2020-02-04 11:56:15 +0000
4748@@ -2,6 +2,8 @@
4749
4750 """Tests of lazr.restful navigation."""
4751
4752+from __future__ import absolute_import, print_function
4753+
4754 __metaclass__ = type
4755
4756 import unittest
4757
4758=== modified file 'src/lazr/restful/tests/test_utils.py'
4759--- src/lazr/restful/tests/test_utils.py 2011-03-17 13:45:53 +0000
4760+++ src/lazr/restful/tests/test_utils.py 2020-02-04 11:56:15 +0000
4761@@ -2,6 +2,8 @@
4762
4763 """Test for lazr.restful.utils."""
4764
4765+from __future__ import absolute_import, print_function
4766+
4767 __metaclass__ = type
4768
4769 import random
4770
4771=== modified file 'src/lazr/restful/tests/test_webservice.py'
4772--- src/lazr/restful/tests/test_webservice.py 2018-09-28 15:46:57 +0000
4773+++ src/lazr/restful/tests/test_webservice.py 2020-02-04 11:56:15 +0000
4774@@ -2,6 +2,8 @@
4775
4776 """Test for the WADL generation."""
4777
4778+from __future__ import absolute_import, print_function
4779+
4780 __metaclass__ = type
4781
4782 from contextlib import contextmanager
4783
4784=== modified file 'src/lazr/restful/utils.py'
4785--- src/lazr/restful/utils.py 2011-03-21 14:00:50 +0000
4786+++ src/lazr/restful/utils.py 2020-02-04 11:56:15 +0000
4787@@ -2,6 +2,8 @@
4788
4789 """Various utility functions."""
4790
4791+from __future__ import absolute_import, print_function
4792+
4793 __metaclass__ = type
4794 __all__ = [
4795 'camelcase_to_underscore_separated',
4796
4797=== modified file 'src/lazr/restful/wsgi.py'
4798--- src/lazr/restful/wsgi.py 2015-04-08 20:11:29 +0000
4799+++ src/lazr/restful/wsgi.py 2020-02-04 11:56:15 +0000
4800@@ -1,5 +1,7 @@
4801 """A WSGI application for a lazr.restful web service."""
4802
4803+from __future__ import absolute_import, print_function
4804+
4805 __metaclass__ = type
4806 __all__ = [
4807 'BaseWSGIWebServiceConfiguration',

Subscribers

People subscribed via source and target branches