Merge lp:~cjwatson/lazr.restful/py3-unicode into lp:lazr.restful
- py3-unicode
- Merge into trunk
Proposed by
Colin Watson
Status: | Merged |
---|---|
Merged at revision: | 253 |
Proposed branch: | lp:~cjwatson/lazr.restful/py3-unicode |
Merge into: | lp:lazr.restful |
Diff against target: |
396 lines (+52/-40) 9 files modified
src/lazr/restful/_operation.py (+3/-1) src/lazr/restful/_resource.py (+13/-13) src/lazr/restful/declarations.py (+4/-2) src/lazr/restful/docs/webservice.rst (+3/-2) src/lazr/restful/marshallers.py (+13/-11) src/lazr/restful/testing/helpers.py (+3/-1) src/lazr/restful/testing/webservice.py (+6/-5) src/lazr/restful/tests/test_webservice.py (+5/-4) src/lazr/restful/utils.py (+2/-1) |
To merge this branch: | bzr merge lp:~cjwatson/lazr.restful/py3-unicode |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ioana Lasc (community) | Approve | ||
Review via email: mp+387891@code.launchpad.net |
Commit message
Port simple uses of str/unicode/
Description of the change
Most cases are fairly obvious, but we need to pay some attention to whether str is intended to be a byte string or a native string. basestring normally means "native string or text" (i.e. six.string_types), but in a few places it means "bytes or text" instead: in particular, the return value from EntryResource.
To post a comment you must log in.
Revision history for this message
Ioana Lasc (ilasc) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/lazr/restful/_operation.py' | |||
2 | --- src/lazr/restful/_operation.py 2020-02-04 11:52:59 +0000 | |||
3 | +++ src/lazr/restful/_operation.py 2020-07-22 22:45:07 +0000 | |||
4 | @@ -5,6 +5,7 @@ | |||
5 | 5 | from __future__ import absolute_import, print_function | 5 | from __future__ import absolute_import, print_function |
6 | 6 | 6 | ||
7 | 7 | import simplejson | 7 | import simplejson |
8 | 8 | import six | ||
9 | 8 | 9 | ||
10 | 9 | from zope.component import getMultiAdapter, getUtility, queryMultiAdapter | 10 | from zope.component import getMultiAdapter, getUtility, queryMultiAdapter |
11 | 10 | from zope.event import notify | 11 | from zope.event import notify |
12 | @@ -145,7 +146,8 @@ | |||
13 | 145 | # has its response batched. | 146 | # has its response batched. |
14 | 146 | return True | 147 | return True |
15 | 147 | 148 | ||
17 | 148 | if zope_isinstance(result, (basestring, dict, set, list, tuple)): | 149 | if zope_isinstance( |
18 | 150 | result, (bytes, six.text_type, dict, set, list, tuple)): | ||
19 | 149 | # Ordinary Python data structures generally are not | 151 | # Ordinary Python data structures generally are not |
20 | 150 | # batched. | 152 | # batched. |
21 | 151 | return False | 153 | return False |
22 | 152 | 154 | ||
23 | === modified file 'src/lazr/restful/_resource.py' | |||
24 | --- src/lazr/restful/_resource.py 2020-06-30 15:52:03 +0000 | |||
25 | +++ src/lazr/restful/_resource.py 2020-07-22 22:45:07 +0000 | |||
26 | @@ -151,12 +151,12 @@ | |||
27 | 151 | 151 | ||
28 | 152 | def decode_value(value): | 152 | def decode_value(value): |
29 | 153 | """Return a unicode value curresponding to `value`.""" | 153 | """Return a unicode value curresponding to `value`.""" |
31 | 154 | if isinstance(value, unicode): | 154 | if isinstance(value, six.text_type): |
32 | 155 | return value | 155 | return value |
34 | 156 | elif isinstance(value, str): | 156 | elif isinstance(value, bytes): |
35 | 157 | return value.decode("utf-8") | 157 | return value.decode("utf-8") |
36 | 158 | else: | 158 | else: |
38 | 159 | return unicode(value) | 159 | return six.text_type(value) |
39 | 160 | 160 | ||
40 | 161 | 161 | ||
41 | 162 | def encode_value(value): | 162 | def encode_value(value): |
42 | @@ -164,17 +164,17 @@ | |||
43 | 164 | 164 | ||
44 | 165 | Non-unicode strings are assumed to be UTF-8 already. | 165 | Non-unicode strings are assumed to be UTF-8 already. |
45 | 166 | """ | 166 | """ |
47 | 167 | if isinstance(value, unicode): | 167 | if isinstance(value, six.text_type): |
48 | 168 | return value.encode("utf-8") | 168 | return value.encode("utf-8") |
50 | 169 | elif isinstance(value, str): | 169 | elif isinstance(value, bytes): |
51 | 170 | return value | 170 | return value |
52 | 171 | else: | 171 | else: |
54 | 172 | return str(value) | 172 | return bytes(value) |
55 | 173 | 173 | ||
56 | 174 | 174 | ||
57 | 175 | def _default_html_renderer(value): | 175 | def _default_html_renderer(value): |
58 | 176 | """The default technique for rendering a value as an HTML snippet.""" | 176 | """The default technique for rendering a value as an HTML snippet.""" |
60 | 177 | return cgi.escape(unicode(value)) | 177 | return cgi.escape(six.text_type(value)) |
61 | 178 | 178 | ||
62 | 179 | 179 | ||
63 | 180 | @adapter(Interface, IField, IWebServiceClientRequest) | 180 | @adapter(Interface, IField, IWebServiceClientRequest) |
64 | @@ -701,7 +701,7 @@ | |||
65 | 701 | :return: The result of the operation: either a string or an | 701 | :return: The result of the operation: either a string or an |
66 | 702 | object that needs to be serialized to JSON. | 702 | object that needs to be serialized to JSON. |
67 | 703 | """ | 703 | """ |
69 | 704 | if not isinstance(operation_name, basestring): | 704 | if not isinstance(operation_name, six.string_types): |
70 | 705 | self.request.response.setStatus(400) | 705 | self.request.response.setStatus(400) |
71 | 706 | return "Expected a single operation: %r" % (operation_name,) | 706 | return "Expected a single operation: %r" % (operation_name,) |
72 | 707 | 707 | ||
73 | @@ -727,7 +727,7 @@ | |||
74 | 727 | :return: The result of the operation: either a string or an | 727 | :return: The result of the operation: either a string or an |
75 | 728 | object that needs to be serialized to JSON. | 728 | object that needs to be serialized to JSON. |
76 | 729 | """ | 729 | """ |
78 | 730 | if not isinstance(operation_name, basestring): | 730 | if not isinstance(operation_name, six.string_types): |
79 | 731 | self.request.response.setStatus(400) | 731 | self.request.response.setStatus(400) |
80 | 732 | return "Expected a single operation: %r" % (operation_name,) | 732 | return "Expected a single operation: %r" % (operation_name,) |
81 | 733 | 733 | ||
82 | @@ -1163,7 +1163,7 @@ | |||
83 | 1163 | # instead of whatever object the raise site | 1163 | # instead of whatever object the raise site |
84 | 1164 | # thought would be a good idea. | 1164 | # thought would be a good idea. |
85 | 1165 | if (len(e.args) > 0 and | 1165 | if (len(e.args) > 0 and |
87 | 1166 | isinstance(e.args[0], basestring)): | 1166 | isinstance(e.args[0], six.string_types)): |
88 | 1167 | error = e.args[0] | 1167 | error = e.args[0] |
89 | 1168 | else: | 1168 | else: |
90 | 1169 | error = "Constraint not satisfied." | 1169 | error = "Constraint not satisfied." |
91 | @@ -1311,7 +1311,7 @@ | |||
92 | 1311 | # generating the representation might itself change across | 1311 | # generating the representation might itself change across |
93 | 1312 | # versions. | 1312 | # versions. |
94 | 1313 | revno = getUtility(IWebServiceConfiguration).code_revision | 1313 | revno = getUtility(IWebServiceConfiguration).code_revision |
96 | 1314 | return [core.encode('utf-8') for core in [revno, unicode(value)]] | 1314 | return [core.encode('utf-8') for core in [revno, six.text_type(value)]] |
97 | 1315 | 1315 | ||
98 | 1316 | def _representation(self, media_type): | 1316 | def _representation(self, media_type): |
99 | 1317 | """Create a representation of the field value.""" | 1317 | """Create a representation of the field value.""" |
100 | @@ -1547,7 +1547,7 @@ | |||
101 | 1547 | operation_name = self.request.form.pop('ws.op', None) | 1547 | operation_name = self.request.form.pop('ws.op', None) |
102 | 1548 | if operation_name is not None: | 1548 | if operation_name is not None: |
103 | 1549 | result = self.handleCustomGET(operation_name) | 1549 | result = self.handleCustomGET(operation_name) |
105 | 1550 | if isinstance(result, basestring): | 1550 | if isinstance(result, (bytes, six.text_type)): |
106 | 1551 | # The custom operation took care of everything and | 1551 | # The custom operation took care of everything and |
107 | 1552 | # just needs this string served to the client. | 1552 | # just needs this string served to the client. |
108 | 1553 | return result | 1553 | return result |
109 | @@ -1788,7 +1788,7 @@ | |||
110 | 1788 | operation_name = self.request.form.pop('ws.op', None) | 1788 | operation_name = self.request.form.pop('ws.op', None) |
111 | 1789 | if operation_name is not None: | 1789 | if operation_name is not None: |
112 | 1790 | result = self.handleCustomGET(operation_name) | 1790 | result = self.handleCustomGET(operation_name) |
114 | 1791 | if isinstance(result, str) or isinstance(result, unicode): | 1791 | if isinstance(result, (bytes, six.text_type)): |
115 | 1792 | # The custom operation took care of everything and | 1792 | # The custom operation took care of everything and |
116 | 1793 | # just needs this string served to the client. | 1793 | # just needs this string served to the client. |
117 | 1794 | return result | 1794 | return result |
118 | 1795 | 1795 | ||
119 | === modified file 'src/lazr/restful/declarations.py' | |||
120 | --- src/lazr/restful/declarations.py 2020-02-05 10:46:46 +0000 | |||
121 | +++ src/lazr/restful/declarations.py 2020-07-22 22:45:07 +0000 | |||
122 | @@ -47,6 +47,7 @@ | |||
123 | 47 | import itertools | 47 | import itertools |
124 | 48 | import sys | 48 | import sys |
125 | 49 | 49 | ||
126 | 50 | import six | ||
127 | 50 | from zope.component import getUtility, getGlobalSiteManager | 51 | from zope.component import getUtility, getGlobalSiteManager |
128 | 51 | from zope.interface import classImplements | 52 | from zope.interface import classImplements |
129 | 52 | from zope.interface.advice import addClassAdvisor | 53 | from zope.interface.advice import addClassAdvisor |
130 | @@ -738,7 +739,8 @@ | |||
131 | 738 | # zope schema are expected to be unicode, whereas it's | 739 | # zope schema are expected to be unicode, whereas it's |
132 | 739 | # really possible that the method's default is a simple | 740 | # really possible that the method's default is a simple |
133 | 740 | # string. | 741 | # string. |
135 | 741 | if isinstance(default, str) and IText.providedBy(param_def): | 742 | if (six.PY2 and |
136 | 743 | isinstance(default, str) and IText.providedBy(param_def)): | ||
137 | 742 | default = unicode(default) | 744 | default = unicode(default) |
138 | 743 | param_def.default = default | 745 | param_def.default = default |
139 | 744 | param_def.required = False | 746 | param_def.required = False |
140 | @@ -1805,5 +1807,5 @@ | |||
141 | 1805 | # runtime. Use a generic string that won't conflict with a | 1807 | # runtime. Use a generic string that won't conflict with a |
142 | 1806 | # real version string. | 1808 | # real version string. |
143 | 1807 | version = "__Earliest" | 1809 | version = "__Earliest" |
145 | 1808 | name = "%s_%s" % (base_name, version.encode('utf8')) | 1810 | name = "%s_%s" % (base_name, six.ensure_str(version)) |
146 | 1809 | return make_identifier_safe(name) | 1811 | return make_identifier_safe(name) |
147 | 1810 | 1812 | ||
148 | === modified file 'src/lazr/restful/docs/webservice.rst' | |||
149 | --- src/lazr/restful/docs/webservice.rst 2020-02-04 13:17:32 +0000 | |||
150 | +++ src/lazr/restful/docs/webservice.rst 2020-07-22 22:45:07 +0000 | |||
151 | @@ -1092,8 +1092,9 @@ | |||
152 | 1092 | 'home page' for the web service. | 1092 | 'home page' for the web service. |
153 | 1093 | 1093 | ||
154 | 1094 | >>> import simplejson | 1094 | >>> import simplejson |
155 | 1095 | >>> import six | ||
156 | 1095 | >>> response = app(request) | 1096 | >>> response = app(request) |
158 | 1096 | >>> representation = simplejson.loads(unicode(response)) | 1097 | >>> representation = simplejson.loads(six.text_type(response)) |
159 | 1097 | 1098 | ||
160 | 1098 | >>> representation["authors_collection_link"] | 1099 | >>> representation["authors_collection_link"] |
161 | 1099 | u'http://api.cookbooks.dev/beta/authors' | 1100 | u'http://api.cookbooks.dev/beta/authors' |
162 | @@ -1168,7 +1169,7 @@ | |||
163 | 1168 | 1169 | ||
164 | 1169 | >>> def load_json(s): | 1170 | >>> def load_json(s): |
165 | 1170 | ... """Convert a JSON string to Unicode and then load it.""" | 1171 | ... """Convert a JSON string to Unicode and then load it.""" |
167 | 1171 | ... return simplejson.loads(unicode(s)) | 1172 | ... return simplejson.loads(six.text_type(s)) |
168 | 1172 | 1173 | ||
169 | 1173 | >>> representation = load_json(collection()) | 1174 | >>> representation = load_json(collection()) |
170 | 1174 | >>> representation['resource_type_link'] | 1175 | >>> representation['resource_type_link'] |
171 | 1175 | 1176 | ||
172 | === modified file 'src/lazr/restful/marshallers.py' | |||
173 | --- src/lazr/restful/marshallers.py 2020-06-30 15:52:03 +0000 | |||
174 | +++ src/lazr/restful/marshallers.py 2020-07-22 22:45:07 +0000 | |||
175 | @@ -29,6 +29,7 @@ | |||
176 | 29 | from StringIO import StringIO | 29 | from StringIO import StringIO |
177 | 30 | 30 | ||
178 | 31 | import simplejson | 31 | import simplejson |
179 | 32 | import six | ||
180 | 32 | from six.moves.urllib.parse import unquote | 33 | from six.moves.urllib.parse import unquote |
181 | 33 | 34 | ||
182 | 34 | from zope.datetime import ( | 35 | from zope.datetime import ( |
183 | @@ -89,7 +90,7 @@ | |||
184 | 89 | request_host = full_request_host | 90 | request_host = full_request_host |
185 | 90 | request_port = default_port | 91 | request_port = default_port |
186 | 91 | 92 | ||
188 | 92 | if not isinstance(url, basestring): | 93 | if not isinstance(url, six.string_types): |
189 | 93 | raise ValueError(u"got '%s', expected string: %r" % ( | 94 | raise ValueError(u"got '%s', expected string: %r" % ( |
190 | 94 | type(url).__name__, url)) | 95 | type(url).__name__, url)) |
191 | 95 | if url.startswith('/'): | 96 | if url.startswith('/'): |
192 | @@ -178,10 +179,10 @@ | |||
193 | 178 | if value != '': | 179 | if value != '': |
194 | 179 | try: | 180 | try: |
195 | 180 | v = value | 181 | v = value |
197 | 181 | if isinstance(v, str): | 182 | if isinstance(v, bytes): |
198 | 182 | v = v.decode('utf8') # assume utf8 | 183 | v = v.decode('utf8') # assume utf8 |
201 | 183 | elif not isinstance(v, unicode): | 184 | elif not isinstance(v, six.text_type): |
202 | 184 | v = unicode(v) | 185 | v = six.text_type(v) |
203 | 185 | value = simplejson.loads(v) | 186 | value = simplejson.loads(v) |
204 | 186 | except (ValueError, TypeError): | 187 | except (ValueError, TypeError): |
205 | 187 | # Pass the value as is. This saves client from having to encode | 188 | # Pass the value as is. This saves client from having to encode |
206 | @@ -267,7 +268,7 @@ | |||
207 | 267 | class BytesFieldMarshaller(SimpleFieldMarshaller): | 268 | class BytesFieldMarshaller(SimpleFieldMarshaller): |
208 | 268 | """FieldMarshaller for IBytes field.""" | 269 | """FieldMarshaller for IBytes field.""" |
209 | 269 | 270 | ||
211 | 270 | _type = str | 271 | _type = bytes |
212 | 271 | _type_error_message = 'not a string: %r' | 272 | _type_error_message = 'not a string: %r' |
213 | 272 | 273 | ||
214 | 273 | @property | 274 | @property |
215 | @@ -295,8 +296,8 @@ | |||
216 | 295 | if safe_hasattr(value, 'seek'): | 296 | if safe_hasattr(value, 'seek'): |
217 | 296 | value.seek(0) | 297 | value.seek(0) |
218 | 297 | value = value.read() | 298 | value = value.read() |
221 | 298 | elif not isinstance(value, basestring): | 299 | elif not isinstance(value, (bytes, six.text_type)): |
222 | 299 | value = str(value) | 300 | value = bytes(value) |
223 | 300 | else: | 301 | else: |
224 | 301 | # Leave string conversion to _marshall_from_json_data. | 302 | # Leave string conversion to _marshall_from_json_data. |
225 | 302 | pass | 303 | pass |
226 | @@ -307,7 +308,7 @@ | |||
227 | 307 | 308 | ||
228 | 308 | Convert all strings to byte strings. | 309 | Convert all strings to byte strings. |
229 | 309 | """ | 310 | """ |
231 | 310 | if isinstance(value, unicode): | 311 | if isinstance(value, six.text_type): |
232 | 311 | value = value.encode('utf-8') | 312 | value = value.encode('utf-8') |
233 | 312 | return super( | 313 | return super( |
234 | 313 | BytesFieldMarshaller, self)._marshall_from_json_data(value) | 314 | BytesFieldMarshaller, self)._marshall_from_json_data(value) |
235 | @@ -316,7 +317,7 @@ | |||
236 | 316 | class TextFieldMarshaller(SimpleFieldMarshaller): | 317 | class TextFieldMarshaller(SimpleFieldMarshaller): |
237 | 317 | """FieldMarshaller for IText fields.""" | 318 | """FieldMarshaller for IText fields.""" |
238 | 318 | 319 | ||
240 | 319 | _type = unicode | 320 | _type = six.text_type |
241 | 320 | _type_error_message = 'not a unicode string: %r' | 321 | _type_error_message = 'not a unicode string: %r' |
242 | 321 | 322 | ||
243 | 322 | def _marshall_from_request(self, value): | 323 | def _marshall_from_request(self, value): |
244 | @@ -324,7 +325,7 @@ | |||
245 | 324 | 325 | ||
246 | 325 | Converts the value to unicode. | 326 | Converts the value to unicode. |
247 | 326 | """ | 327 | """ |
249 | 327 | value = unicode(value) | 328 | value = six.text_type(value) |
250 | 328 | return super(TextFieldMarshaller, self)._marshall_from_request(value) | 329 | return super(TextFieldMarshaller, self)._marshall_from_request(value) |
251 | 329 | 330 | ||
252 | 330 | 331 | ||
253 | @@ -366,7 +367,8 @@ | |||
254 | 366 | Looks up the value as a token in the vocabulary. | 367 | Looks up the value as a token in the vocabulary. |
255 | 367 | """ | 368 | """ |
256 | 368 | try: | 369 | try: |
258 | 369 | return self.field.vocabulary.getTermByToken(str(value)).value | 370 | return self.field.vocabulary.getTermByToken( |
259 | 371 | six.text_type(value)).value | ||
260 | 370 | except LookupError: | 372 | except LookupError: |
261 | 371 | raise ValueError(u"%r isn't a valid token" % value) | 373 | raise ValueError(u"%r isn't a valid token" % value) |
262 | 372 | 374 | ||
263 | 373 | 375 | ||
264 | === modified file 'src/lazr/restful/testing/helpers.py' | |||
265 | --- src/lazr/restful/testing/helpers.py 2020-02-04 11:52:59 +0000 | |||
266 | +++ src/lazr/restful/testing/helpers.py 2020-07-22 22:45:07 +0000 | |||
267 | @@ -50,7 +50,9 @@ | |||
268 | 50 | 50 | ||
269 | 51 | :param response: an httplib HTTPResponse object. | 51 | :param response: an httplib HTTPResponse object. |
270 | 52 | """ | 52 | """ |
272 | 53 | response_unicode = str(response).decode("utf-8") | 53 | response_unicode = str(response) |
273 | 54 | if isinstance(response_unicode, bytes): # Python 2 | ||
274 | 55 | response_unicode = response_unicode.decode("utf-8") | ||
275 | 54 | return encode_unicode(response_unicode) | 56 | return encode_unicode(response_unicode) |
276 | 55 | 57 | ||
277 | 56 | 58 | ||
278 | 57 | 59 | ||
279 | === modified file 'src/lazr/restful/testing/webservice.py' | |||
280 | --- src/lazr/restful/testing/webservice.py 2020-02-04 21:53:16 +0000 | |||
281 | +++ src/lazr/restful/testing/webservice.py 2020-07-22 22:45:07 +0000 | |||
282 | @@ -28,6 +28,7 @@ | |||
283 | 28 | 28 | ||
284 | 29 | import wsgi_intercept | 29 | import wsgi_intercept |
285 | 30 | 30 | ||
286 | 31 | import six | ||
287 | 31 | from six.moves.urllib.parse import ( | 32 | from six.moves.urllib.parse import ( |
288 | 32 | quote, | 33 | quote, |
289 | 33 | urlencode, | 34 | urlencode, |
290 | @@ -122,7 +123,7 @@ | |||
291 | 122 | if result is None: | 123 | if result is None: |
292 | 123 | result = '' | 124 | result = '' |
293 | 124 | 125 | ||
295 | 125 | if not isinstance(result, basestring): | 126 | if not isinstance(result, six.string_types): |
296 | 126 | raise ValueError('only strings and None results are handled') | 127 | raise ValueError('only strings and None results are handled') |
297 | 127 | 128 | ||
298 | 128 | self.result = result | 129 | self.result = result |
299 | @@ -209,7 +210,7 @@ | |||
300 | 209 | """ | 210 | """ |
301 | 210 | 211 | ||
302 | 211 | def __init__(self, global_config, publication, **options): | 212 | def __init__(self, global_config, publication, **options): |
304 | 212 | if isinstance(publication, basestring): | 213 | if isinstance(publication, six.string_types): |
305 | 213 | Application.__init__(self, global_config, publication, **options) | 214 | Application.__init__(self, global_config, publication, **options) |
306 | 214 | else: | 215 | else: |
307 | 215 | self.publication = publication(global_config, **options) | 216 | self.publication = publication(global_config, **options) |
308 | @@ -334,7 +335,7 @@ | |||
309 | 334 | # To be properly marshalled all values must be strings or converted to | 335 | # To be properly marshalled all values must be strings or converted to |
310 | 335 | # JSON. | 336 | # JSON. |
311 | 336 | for key, value in args.items(): | 337 | for key, value in args.items(): |
313 | 337 | if not isinstance(value, basestring): | 338 | if not isinstance(value, six.string_types): |
314 | 338 | args[key] = simplejson.dumps(value) | 339 | args[key] = simplejson.dumps(value) |
315 | 339 | return urlencode(args) | 340 | return urlencode(args) |
316 | 340 | 341 | ||
317 | @@ -363,7 +364,7 @@ | |||
318 | 363 | 364 | ||
319 | 364 | This may mean turning the value into a JSON string. | 365 | This may mean turning the value into a JSON string. |
320 | 365 | """ | 366 | """ |
322 | 366 | if not isinstance(value, basestring): | 367 | if not isinstance(value, six.string_types): |
323 | 367 | value = simplejson.dumps(value) | 368 | value = simplejson.dumps(value) |
324 | 368 | return quote(value) | 369 | return quote(value) |
325 | 369 | 370 | ||
326 | @@ -408,7 +409,7 @@ | |||
327 | 408 | def jsonBody(self): | 409 | def jsonBody(self): |
328 | 409 | """Return the body of the web service request as a JSON document.""" | 410 | """Return the body of the web service request as a JSON document.""" |
329 | 410 | try: | 411 | try: |
331 | 411 | json = simplejson.loads(unicode(self.body)) | 412 | json = simplejson.loads(six.ensure_text(self.body)) |
332 | 412 | if isinstance(json, list): | 413 | if isinstance(json, list): |
333 | 413 | json = sorted(json) | 414 | json = sorted(json) |
334 | 414 | return json | 415 | return json |
335 | 415 | 416 | ||
336 | === modified file 'src/lazr/restful/tests/test_webservice.py' | |||
337 | --- src/lazr/restful/tests/test_webservice.py 2020-02-19 16:09:10 +0000 | |||
338 | +++ src/lazr/restful/tests/test_webservice.py 2020-07-22 22:45:07 +0000 | |||
339 | @@ -18,6 +18,7 @@ | |||
340 | 18 | import simplejson | 18 | import simplejson |
341 | 19 | import unittest | 19 | import unittest |
342 | 20 | 20 | ||
343 | 21 | import six | ||
344 | 21 | from zope.component import ( | 22 | from zope.component import ( |
345 | 22 | eventtesting, | 23 | eventtesting, |
346 | 23 | getGlobalSiteManager, | 24 | getGlobalSiteManager, |
347 | @@ -536,8 +537,8 @@ | |||
348 | 536 | def resource(self, value_1="value 1", value_2="value 2"): | 537 | def resource(self, value_1="value 1", value_2="value 2"): |
349 | 537 | """Simplify the entry_resource call.""" | 538 | """Simplify the entry_resource call.""" |
350 | 538 | with self.entry_resource( | 539 | with self.entry_resource( |
353 | 539 | IHasTwoFields, HasTwoFields, | 540 | IHasTwoFields, HasTwoFields, |
354 | 540 | unicode(value_1), unicode(value_2)) as resource: | 541 | six.text_type(value_1), six.text_type(value_2)) as resource: |
355 | 541 | yield resource | 542 | yield resource |
356 | 542 | 543 | ||
357 | 543 | def test_web_layer_json_representation_omits_lp_html(self): | 544 | def test_web_layer_json_representation_omits_lp_html(self): |
358 | @@ -598,7 +599,7 @@ | |||
359 | 598 | json = None | 599 | json = None |
360 | 599 | with self.resource() as resource: | 600 | with self.resource() as resource: |
361 | 600 | json_plus_xhtml = resource.JSON_PLUS_XHTML_TYPE | 601 | json_plus_xhtml = resource.JSON_PLUS_XHTML_TYPE |
363 | 601 | json = simplejson.loads(unicode( | 602 | json = simplejson.loads(six.text_type( |
364 | 602 | resource._representation(json_plus_xhtml))) | 603 | resource._representation(json_plus_xhtml))) |
365 | 603 | resource.applyChanges(json, json_plus_xhtml) | 604 | resource.applyChanges(json, json_plus_xhtml) |
366 | 604 | self.assertEqual(resource.request.response.getStatus(), 209) | 605 | self.assertEqual(resource.request.response.getStatus(), 209) |
367 | @@ -607,7 +608,7 @@ | |||
368 | 607 | self.register_html_field_renderer() | 608 | self.register_html_field_renderer() |
369 | 608 | json = None | 609 | json = None |
370 | 609 | with self.resource() as resource: | 610 | with self.resource() as resource: |
372 | 610 | json = simplejson.loads(unicode( | 611 | json = simplejson.loads(six.text_type( |
373 | 611 | resource._representation(resource.JSON_PLUS_XHTML_TYPE))) | 612 | resource._representation(resource.JSON_PLUS_XHTML_TYPE))) |
374 | 612 | resource.applyChanges(json, resource.JSON_TYPE) | 613 | resource.applyChanges(json, resource.JSON_TYPE) |
375 | 613 | self.assertEqual(resource.request.response.getStatus(), 400) | 614 | self.assertEqual(resource.request.response.getStatus(), 400) |
376 | 614 | 615 | ||
377 | === modified file 'src/lazr/restful/utils.py' | |||
378 | --- src/lazr/restful/utils.py 2020-02-04 11:52:59 +0000 | |||
379 | +++ src/lazr/restful/utils.py 2020-07-22 22:45:07 +0000 | |||
380 | @@ -31,6 +31,7 @@ | |||
381 | 31 | import subprocess | 31 | import subprocess |
382 | 32 | 32 | ||
383 | 33 | from simplejson import encoder | 33 | from simplejson import encoder |
384 | 34 | import six | ||
385 | 34 | 35 | ||
386 | 35 | from zope.component import getUtility | 36 | from zope.component import getUtility |
387 | 36 | from zope.schema import getFieldsInOrder | 37 | from zope.schema import getFieldsInOrder |
388 | @@ -359,7 +360,7 @@ | |||
389 | 359 | 360 | ||
390 | 360 | def smartquote(str): | 361 | def smartquote(str): |
391 | 361 | """Return a copy of the string, with typographical quote marks applied.""" | 362 | """Return a copy of the string, with typographical quote marks applied.""" |
393 | 362 | str = unicode(str) | 363 | str = six.text_type(str) |
394 | 363 | str = re.compile(u'(^| )(")([^" ])').sub(u'\\1\u201c\\3', str) | 364 | str = re.compile(u'(^| )(")([^" ])').sub(u'\\1\u201c\\3', str) |
395 | 364 | str = re.compile(u'([^ "])(")($|[\s.,;:!?])').sub(u'\\1\u201d\\3', str) | 365 | str = re.compile(u'([^ "])(")($|[\s.,;:!?])').sub(u'\\1\u201d\\3', str) |
396 | 365 | return str | 366 | return str |