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