Merge ~cjwatson/lazr.restful:pyupgrade-py3 into lazr.restful:main

Proposed by Colin Watson
Status: Merged
Merged at revision: 6f588c2bd39e71694dd66d6f76a7c11a0826b2ce
Proposed branch: ~cjwatson/lazr.restful:pyupgrade-py3
Merge into: lazr.restful:main
Diff against target: 3006 lines (+305/-532)
53 files modified
.pre-commit-config.yaml (+1/-1)
pyproject.toml (+1/-1)
src/lazr/restful/__init__.py (+0/-2)
src/lazr/restful/_bytestorage.py (+0/-3)
src/lazr/restful/_operation.py (+6/-12)
src/lazr/restful/_resource.py (+29/-39)
src/lazr/restful/debug.py (+0/-3)
src/lazr/restful/declarations.py (+10/-19)
src/lazr/restful/directives/__init__.py (+0/-3)
src/lazr/restful/docs/conf.py (+7/-9)
src/lazr/restful/error.py (+0/-3)
src/lazr/restful/example/base/filemanager.py (+0/-3)
src/lazr/restful/example/base/interfaces.py (+28/-33)
src/lazr/restful/example/base/root.py (+10/-13)
src/lazr/restful/example/base/security.py (+0/-3)
src/lazr/restful/example/base/subscribers.py (+0/-3)
src/lazr/restful/example/base/tests/test_integration.py (+1/-9)
src/lazr/restful/example/base/traversal.py (+1/-6)
src/lazr/restful/example/base_extended/comments.py (+1/-3)
src/lazr/restful/example/base_extended/tests/test_integration.py (+1/-8)
src/lazr/restful/example/multiversion/resources.py (+5/-9)
src/lazr/restful/example/multiversion/root.py (+0/-3)
src/lazr/restful/example/multiversion/tests/test_integration.py (+1/-8)
src/lazr/restful/example/wsgi/resources.py (+3/-7)
src/lazr/restful/example/wsgi/root.py (+0/-3)
src/lazr/restful/example/wsgi/run.py (+0/-2)
src/lazr/restful/example/wsgi/tests/test_integration.py (+1/-8)
src/lazr/restful/fields.py (+2/-5)
src/lazr/restful/frameworks/django.py (+2/-3)
src/lazr/restful/interface.py (+0/-3)
src/lazr/restful/interfaces/__init__.py (+0/-2)
src/lazr/restful/interfaces/_fields.py (+0/-3)
src/lazr/restful/interfaces/_rest.py (+39/-42)
src/lazr/restful/jsoncache.py (+0/-4)
src/lazr/restful/marshallers.py (+27/-45)
src/lazr/restful/metazcml.py (+1/-4)
src/lazr/restful/publisher.py (+4/-11)
src/lazr/restful/security.py (+0/-3)
src/lazr/restful/simple.py (+4/-10)
src/lazr/restful/tales.py (+5/-11)
src/lazr/restful/testing/event.py (+0/-4)
src/lazr/restful/testing/helpers.py (+0/-2)
src/lazr/restful/testing/tales.py (+0/-4)
src/lazr/restful/testing/webservice.py (+14/-18)
src/lazr/restful/tests/test_declarations.py (+40/-42)
src/lazr/restful/tests/test_docs.py (+1/-9)
src/lazr/restful/tests/test_error.py (+3/-7)
src/lazr/restful/tests/test_etag.py (+6/-10)
src/lazr/restful/tests/test_navigation.py (+6/-10)
src/lazr/restful/tests/test_utils.py (+1/-5)
src/lazr/restful/tests/test_webservice.py (+37/-46)
src/lazr/restful/utils.py (+7/-10)
src/lazr/restful/wsgi.py (+0/-3)
Reviewer Review Type Date Requested Status
Jürgen Gmach Approve
Review via email: mp+413604@code.launchpad.net

Commit message

Apply pyupgrade --py3-plus

To post a comment you must log in.
Revision history for this message
Jürgen Gmach (jugmac00) wrote :

LGTM with a minor issue, see comment

review: Approve
Revision history for this message
Colin Watson (cjwatson) :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
2index 6f75344..6b363b1 100644
3--- a/.pre-commit-config.yaml
4+++ b/.pre-commit-config.yaml
5@@ -23,7 +23,7 @@ repos:
6 rev: v2.29.0
7 hooks:
8 - id: pyupgrade
9- args: [--keep-percent-format]
10+ args: [--keep-percent-format, --py3-plus]
11 - repo: https://github.com/psf/black
12 rev: 21.10b0
13 hooks:
14diff --git a/pyproject.toml b/pyproject.toml
15index 486bbe6..1f331da 100644
16--- a/pyproject.toml
17+++ b/pyproject.toml
18@@ -1,3 +1,3 @@
19 [tool.black]
20 line-length = 79
21-target-version = ['py27']
22+target-version = ['py35']
23diff --git a/src/lazr/restful/__init__.py b/src/lazr/restful/__init__.py
24index 25235cd..c8e3f40 100644
25--- a/src/lazr/restful/__init__.py
26+++ b/src/lazr/restful/__init__.py
27@@ -17,8 +17,6 @@
28
29 # pylint: disable-msg=W0401
30
31-from __future__ import absolute_import, print_function
32-
33 try:
34 import importlib.metadata as importlib_metadata
35 except ImportError:
36diff --git a/src/lazr/restful/_bytestorage.py b/src/lazr/restful/_bytestorage.py
37index 7d6c6a0..b25369c 100644
38--- a/src/lazr/restful/_bytestorage.py
39+++ b/src/lazr/restful/_bytestorage.py
40@@ -16,9 +16,6 @@
41
42 """Classes for a resource that implements a binary file repository."""
43
44-from __future__ import absolute_import, print_function
45-
46-__metaclass__ = type
47 __all__ = [
48 "ByteStorageResource",
49 ]
50diff --git a/src/lazr/restful/_operation.py b/src/lazr/restful/_operation.py
51index af48e48..7cab8ea 100644
52--- a/src/lazr/restful/_operation.py
53+++ b/src/lazr/restful/_operation.py
54@@ -2,10 +2,7 @@
55
56 """Base classes for one-off HTTP operations."""
57
58-from __future__ import absolute_import, print_function
59-
60 import simplejson
61-import six
62
63 from zope.component import getMultiAdapter, getUtility, queryMultiAdapter
64 from zope.event import notify
65@@ -40,7 +37,6 @@ from lazr.restful._resource import (
66 )
67
68
69-__metaclass__ = type
70 __all__ = [
71 "IObjectLink",
72 "ObjectLink",
73@@ -163,9 +159,7 @@ class ResourceOperation(BatchingResourceMixin):
74 # has its response batched.
75 return True
76
77- if zope_isinstance(
78- result, (bytes, six.text_type, dict, set, list, tuple)
79- ):
80+ if zope_isinstance(result, (bytes, str, dict, set, list, tuple)):
81 # Ordinary Python data structures generally are not
82 # batched.
83 return False
84@@ -216,14 +210,14 @@ class ResourceOperation(BatchingResourceMixin):
85 self.request.form.get(name)
86 )
87 except ValueError as e:
88- errors.append(u"%s: %s" % (name, e))
89+ errors.append("%s: %s" % (name, e))
90 continue
91 try:
92 field.validate(value)
93 except RequiredMissing:
94- errors.append(u"%s: Required input is missing." % name)
95+ errors.append("%s: Required input is missing." % name)
96 except ValidationError as e:
97- errors.append(u"%s: %s" % (name, e))
98+ errors.append("%s: %s" % (name, e))
99 else:
100 validated_values[name] = value
101 return (validated_values, errors)
102@@ -252,7 +246,7 @@ class IObjectLink(IField):
103 """Field containing a link to an object."""
104
105 schema = Attribute(
106- "schema", u"The Interface of the Object on the other end of the link."
107+ "schema", "The Interface of the Object on the other end of the link."
108 )
109
110
111@@ -265,4 +259,4 @@ class ObjectLink(Field):
112 raise WrongType
113
114 self.schema = schema
115- super(ObjectLink, self).__init__(**kw)
116+ super().__init__(**kw)
117diff --git a/src/lazr/restful/_resource.py b/src/lazr/restful/_resource.py
118index f01326d..45f717e 100644
119--- a/src/lazr/restful/_resource.py
120+++ b/src/lazr/restful/_resource.py
121@@ -2,10 +2,6 @@
122
123 """Base classes for HTTP resources."""
124
125-from __future__ import absolute_import, division, print_function
126-
127-__metaclass__ = type
128-
129 __all__ = [
130 "BatchingResourceMixin",
131 "Collection",
132@@ -55,7 +51,6 @@ try:
133 except ImportError:
134 from cgi import escape
135
136-import six
137 from zope.component import (
138 adapter,
139 getAdapters,
140@@ -162,7 +157,7 @@ init_status_codes()
141
142 def decode_value(value):
143 """Return a unicode value curresponding to `value`."""
144- if isinstance(value, six.text_type):
145+ if isinstance(value, str):
146 return value
147 elif isinstance(value, bytes):
148 return value.decode("utf-8")
149@@ -172,7 +167,7 @@ def decode_value(value):
150
151 def _default_html_renderer(value):
152 """The default technique for rendering a value as an HTML snippet."""
153- return escape(six.text_type(value), quote=False)
154+ return escape(str(value), quote=False)
155
156
157 @adapter(Interface, IField, IWebServiceClientRequest)
158@@ -212,7 +207,7 @@ class ResourceJSONEncoder(simplejson.encoder.JSONEncoderForHTML):
159
160 def __init__(self, *args, **kwargs):
161 self.media_type = kwargs.pop("media_type", HTTPResource.JSON_TYPE)
162- super(ResourceJSONEncoder, self).__init__(*args, **kwargs)
163+ super().__init__(*args, **kwargs)
164
165 def default(self, obj):
166 """Convert the given object to a simple data structure."""
167@@ -711,7 +706,7 @@ class CustomOperationResourceMixin:
168 # with multiple inheritance. That requires defining __init__
169 # to call the next constructor in the chain, which means using
170 # super() even though this class itself has no superclass.
171- super(CustomOperationResourceMixin, self).__init__(context, request)
172+ super().__init__(context, request)
173
174 def handleCustomGET(self, operation_name):
175 """Execute a custom search-type operation triggered through GET.
176@@ -722,7 +717,7 @@ class CustomOperationResourceMixin:
177 :return: The result of the operation: either a string or an
178 object that needs to be serialized to JSON.
179 """
180- if not isinstance(operation_name, six.string_types):
181+ if not isinstance(operation_name, str):
182 self.request.response.setStatus(400)
183 return "Expected a single operation: %r" % (operation_name,)
184
185@@ -750,7 +745,7 @@ class CustomOperationResourceMixin:
186 :return: The result of the operation: either a string or an
187 object that needs to be serialized to JSON.
188 """
189- if not isinstance(operation_name, six.string_types):
190+ if not isinstance(operation_name, str):
191 self.request.response.setStatus(400)
192 return "Expected a single operation: %r" % (operation_name,)
193
194@@ -810,7 +805,7 @@ class FieldUnmarshallerMixin:
195 # with multiple inheritance. That requires defining __init__
196 # to call the next constructor in the chain, which means using
197 # super() even though this class itself has no superclass.
198- super(FieldUnmarshallerMixin, self).__init__(context, request)
199+ super().__init__(context, request)
200 self._unmarshalled_field_cache = {}
201
202 def _unmarshallField(self, field_name, field, detail=NORMAL_DETAIL):
203@@ -909,7 +904,7 @@ class ReadOnlyResource(HTTPResource):
204 # This class is designed to be used with mixins. That means
205 # defining __init__ to call the next constructor in the chain,
206 # even though there's no other code in __init__.
207- super(ReadOnlyResource, self).__init__(context, request)
208+ super().__init__(context, request)
209
210 def __call__(self):
211 """Handle a GET or (if implemented) POST request."""
212@@ -936,7 +931,7 @@ class ReadWriteResource(HTTPResource):
213 # This class is designed to be used with mixins. That means
214 # defining __init__ to call the next constructor in the chain,
215 # even though there's no other code in __init__.
216- super(ReadWriteResource, self).__init__(context, request)
217+ super().__init__(context, request)
218
219 def __call__(self):
220 """Handle a GET, PUT, or PATCH request."""
221@@ -980,10 +975,7 @@ class ReadWriteResource(HTTPResource):
222 # hopefully handle it better. Note the careful
223 # reraising that ensures the original traceback is
224 # preserved.
225- if six.PY3:
226- six.raise_from(exception_info[1], None)
227- else:
228- six.reraise(*exception_info)
229+ raise exception_info[1] from None
230 finally:
231 del exception_info
232
233@@ -1035,7 +1027,7 @@ class EntryManipulatingResource(ReadWriteResource):
234 # This class is designed to be used with mixins. That means
235 # defining __init__ to call the next constructor in the chain,
236 # even though there's no other code in __init__.
237- super(EntryManipulatingResource, self).__init__(context, request)
238+ super().__init__(context, request)
239
240 def processAsJSONDocument(self, media_type, representation):
241 """Process an incoming representation as a JSON document."""
242@@ -1066,7 +1058,7 @@ class EntryManipulatingResource(ReadWriteResource):
243 # Some fields aren't part of the schema, so they're handled
244 # separately.
245 modified_read_only_attribute = (
246- u"%s: You tried to modify a " "read-only attribute."
247+ "%s: You tried to modify a " "read-only attribute."
248 )
249 if "self_link" in changeset:
250 if changeset["self_link"] != absoluteURL(
251@@ -1143,7 +1135,7 @@ class EntryManipulatingResource(ReadWriteResource):
252 try:
253 value = marshaller.marshall_from_json_data(original_value)
254 except (ValueError, ValidationError) as e:
255- errors.append(u"%s: %s" % (repr_name, e))
256+ errors.append("%s: %s" % (repr_name, e))
257 continue
258
259 if ICollectionField.providedBy(field):
260@@ -1152,7 +1144,7 @@ class EntryManipulatingResource(ReadWriteResource):
261 # current one.
262 if value != current_value:
263 errors.append(
264- u"%s: You tried to modify a collection "
265+ "%s: You tried to modify a collection "
266 "attribute." % repr_name
267 )
268 continue
269@@ -1170,7 +1162,7 @@ class EntryManipulatingResource(ReadWriteResource):
270 errors.append(modified_read_only_attribute % repr_name)
271 else:
272 errors.append(
273- u"%s: To modify this field you need to send a PUT "
274+ "%s: To modify this field you need to send a PUT "
275 "request to its URI (%s)."
276 % (repr_name, current_value)
277 )
278@@ -1186,7 +1178,7 @@ class EntryManipulatingResource(ReadWriteResource):
279 # class the way IReference fields can.
280 if value is not None and not field.schema.providedBy(value):
281 errors.append(
282- u"%s: Your value points to the "
283+ "%s: Your value points to the "
284 "wrong kind of object" % repr_name
285 )
286 continue
287@@ -1215,22 +1207,20 @@ class EntryManipulatingResource(ReadWriteResource):
288 # the exception; otherwise use a generic message
289 # instead of whatever object the raise site
290 # thought would be a good idea.
291- if len(e.args) > 0 and isinstance(
292- e.args[0], six.string_types
293- ):
294+ if len(e.args) > 0 and isinstance(e.args[0], str):
295 error = e.args[0]
296 else:
297 error = "Constraint not satisfied."
298- errors.append(u"%s: %s" % (repr_name, error))
299+ errors.append("%s: %s" % (repr_name, error))
300 continue
301 except RequiredMissing:
302 error = "Missing required value."
303- errors.append(u"%s: %s" % (repr_name, error))
304+ errors.append("%s: %s" % (repr_name, error))
305 except (ValueError, ValidationError) as e:
306 error = str(e)
307 if error == "":
308 error = "Validation error"
309- errors.append(u"%s: %s" % (repr_name, error))
310+ errors.append("%s: %s" % (repr_name, error))
311 continue
312 validated_changeset.append((field, value))
313 # If there are any fields left in the changeset, they're
314@@ -1238,7 +1228,7 @@ class EntryManipulatingResource(ReadWriteResource):
315 # schema. They're all errors.
316 for invalid_field in changeset.keys():
317 errors.append(
318- u"%s: You tried to modify a nonexistent "
319+ "%s: You tried to modify a nonexistent "
320 "attribute." % invalid_field
321 )
322
323@@ -1331,7 +1321,7 @@ class EntryFieldResource(FieldUnmarshallerMixin, EntryManipulatingResource):
324
325 def __init__(self, context, request):
326 """Initialize with respect to a context and request."""
327- super(EntryFieldResource, self).__init__(context, request)
328+ super().__init__(context, request)
329 self.entry = self.context.entry
330
331 def do_GET(self):
332@@ -1367,7 +1357,7 @@ class EntryFieldResource(FieldUnmarshallerMixin, EntryManipulatingResource):
333 # generating the representation might itself change across
334 # versions.
335 revno = getUtility(IWebServiceConfiguration).code_revision
336- return [core.encode("utf-8") for core in [revno, six.text_type(value)]]
337+ return [core.encode("utf-8") for core in [revno, str(value)]]
338
339 def _representation(self, media_type):
340 """Create a representation of the field value."""
341@@ -1454,13 +1444,13 @@ class EntryResource(
342
343 def __init__(self, context, request):
344 """Associate this resource with a specific object and request."""
345- super(EntryResource, self).__init__(context, request)
346+ super().__init__(context, request)
347 self.entry = getMultiAdapter((context, request), IEntry)
348
349 def handleCustomPOST(self, operation_name):
350 """See `CustomOperationResourceMixin`."""
351 original_url = absoluteURL(self.entry.context, self.request)
352- value = super(EntryResource, self).handleCustomPOST(operation_name)
353+ value = super().handleCustomPOST(operation_name)
354 # We don't know what the custom operation might have done.
355 # Remove this object from the representation cache, just to be
356 # safe.
357@@ -1617,7 +1607,7 @@ class EntryResource(
358 operation_name = self.request.form.pop("ws.op", None)
359 if operation_name is not None:
360 result = self.handleCustomGET(operation_name)
361- if isinstance(result, (bytes, six.text_type)):
362+ if isinstance(result, (bytes, str)):
363 # The custom operation took care of everything and
364 # just needs this string served to the client.
365 return result
366@@ -1860,7 +1850,7 @@ class CollectionResource(
367
368 def __init__(self, context, request):
369 """Associate this resource with a specific object and request."""
370- super(CollectionResource, self).__init__(context, request)
371+ super().__init__(context, request)
372 if ICollection.providedBy(context):
373 self.collection = context
374 else:
375@@ -1872,7 +1862,7 @@ class CollectionResource(
376 operation_name = self.request.form.pop("ws.op", None)
377 if operation_name is not None:
378 result = self.handleCustomGET(operation_name)
379- if isinstance(result, (bytes, six.text_type)):
380+ if isinstance(result, (bytes, str)):
381 # The custom operation took care of everything and
382 # just needs this string served to the client.
383 return result
384@@ -1905,7 +1895,7 @@ class CollectionResource(
385 entries = self.collection.find()
386 if request is None:
387 request = self.request
388- result = super(CollectionResource, self).batch(entries, request)
389+ result = super().batch(entries, request)
390 result += ', "resource_type_link" : ' + simplejson.dumps(self.type_url)
391 return result
392
393diff --git a/src/lazr/restful/debug.py b/src/lazr/restful/debug.py
394index 0567455..ebcf526 100644
395--- a/src/lazr/restful/debug.py
396+++ b/src/lazr/restful/debug.py
397@@ -2,9 +2,6 @@
398
399 """Module docstring goes here."""
400
401-from __future__ import absolute_import, print_function
402-
403-__metaclass__ = type
404 __all__ = ["debug_proxy", "typename"]
405
406
407diff --git a/src/lazr/restful/declarations.py b/src/lazr/restful/declarations.py
408index 4c95bcd..f717592 100644
409--- a/src/lazr/restful/declarations.py
410+++ b/src/lazr/restful/declarations.py
411@@ -2,9 +2,6 @@
412
413 """Declaration helpers to define a web service."""
414
415-from __future__ import absolute_import, print_function
416-
417-__metaclass__ = type
418 __all__ = [
419 "COLLECTION_TYPE",
420 "ENTRY_TYPE",
421@@ -1134,9 +1131,7 @@ class export_factory_operation(_export_operation):
422
423 def annotate_method(self, method, annotations):
424 """See `_method_annotator`."""
425- super(export_factory_operation, self).annotate_method(
426- method, annotations
427- )
428+ super().annotate_method(method, annotations)
429 annotations["creates"] = self.interface
430 annotations["params"] = self.params
431 annotations["return_type"] = ObjectLink(schema=self.interface)
432@@ -1147,7 +1142,7 @@ class cache_for(_method_annotator):
433
434 def __init__(self, duration):
435 """Specify the duration, in seconds, of the caching resource."""
436- if not isinstance(duration, six.integer_types):
437+ if not isinstance(duration, int):
438 raise TypeError(
439 "Caching duration should be an integer type, not %s"
440 % duration.__class__.__name__
441@@ -1174,7 +1169,7 @@ class scoped(_method_annotator):
442
443 def __init__(self, *scopes):
444 for scope in scopes:
445- if not isinstance(scope, six.string_types):
446+ if not isinstance(scope, str):
447 raise TypeError(
448 "Scope should be a string type, not %s"
449 % scope.__class__.__name__
450@@ -1214,9 +1209,7 @@ class export_destructor_operation(_export_operation):
451
452 Every version must have a self-consistent set of annotations.
453 """
454- super(export_destructor_operation, self).annotate_method(
455- method, annotation_stack
456- )
457+ super().annotate_method(method, annotation_stack)
458 # The mutator method must take no arguments, not counting
459 # arguments with values fixed by call_with().
460 for version, annotations in annotation_stack.stack:
461@@ -1555,14 +1548,14 @@ class _ScopeChecker(Passthrough):
462 if self.adaptation is not None:
463 context = self.adaptation(context)
464 _check_request(context, None)
465- return super(_ScopeChecker, self).__get__(inst, cls=cls)
466+ return super().__get__(inst, cls=cls)
467
468 def __set__(self, inst, value):
469 context = getattr(inst, self.contextvar)
470 if self.adaptation is not None:
471 context = self.adaptation(context)
472 _check_request(context, None)
473- return super(_ScopeChecker, self).__set__(inst, value)
474+ return super().__set__(inst, value)
475
476
477 class _AccessorWrapper:
478@@ -1615,7 +1608,7 @@ class PropertyWithAccessor(_AccessorWrapper, _ScopeChecker):
479 def __init__(
480 self, name, context, accessor, accessor_annotations, adaptation
481 ):
482- super(PropertyWithAccessor, self).__init__(name, context, adaptation)
483+ super().__init__(name, context, adaptation)
484 self.accessor = accessor.__name__
485 self.accessor_annotations = accessor_annotations
486
487@@ -1626,7 +1619,7 @@ class PropertyWithMutator(_MutatorWrapper, _ScopeChecker):
488 def __init__(
489 self, name, context, mutator, mutator_annotations, adaptation
490 ):
491- super(PropertyWithMutator, self).__init__(name, context, adaptation)
492+ super().__init__(name, context, adaptation)
493 self.mutator = mutator.__name__
494 self.mutator_annotations = mutator_annotations
495
496@@ -1646,9 +1639,7 @@ class PropertyWithAccessorAndMutator(
497 mutator_annotations,
498 adaptation,
499 ):
500- super(PropertyWithAccessorAndMutator, self).__init__(
501- name, context, adaptation
502- )
503+ super().__init__(name, context, adaptation)
504 self.accessor = accessor.__name__
505 self.accessor_annotations = accessor_annotations
506 self.mutator = mutator.__name__
507@@ -1792,7 +1783,7 @@ class BaseFactoryResourceOperationAdapter(BaseResourceOperationAdapter):
508 response = self.request.response
509 response.setStatus(201)
510 response.setHeader("Location", absoluteURL(result, self.request))
511- return u""
512+ return ""
513
514
515 def generate_operation_adapter(method, version=None):
516diff --git a/src/lazr/restful/directives/__init__.py b/src/lazr/restful/directives/__init__.py
517index 4db78d1..e311f8e 100644
518--- a/src/lazr/restful/directives/__init__.py
519+++ b/src/lazr/restful/directives/__init__.py
520@@ -2,9 +2,6 @@
521
522 """Martian directives used in lazr.restful."""
523
524-from __future__ import absolute_import, print_function
525-
526-__metaclass__ = type
527 __all__ = [
528 "request_class",
529 "publication_class",
530diff --git a/src/lazr/restful/docs/conf.py b/src/lazr/restful/docs/conf.py
531index bd3dea3..f1c692d 100644
532--- a/src/lazr/restful/docs/conf.py
533+++ b/src/lazr/restful/docs/conf.py
534@@ -1,5 +1,3 @@
535-# -*- coding: utf-8 -*-
536-#
537 # lazr.restful documentation build configuration file, created by
538 # sphinx-quickstart on Sun Nov 3 15:00:52 2019.
539 #
540@@ -47,9 +45,9 @@ source_suffix = ".rst"
541 master_doc = "index"
542
543 # General information about the project.
544-project = u"lazr.restful"
545-copyright = u"2004-2019, Canonical Ltd."
546-author = u"LAZR Developers <lazr-developers@lists.launchpad.net>"
547+project = "lazr.restful"
548+copyright = "2004-2019, Canonical Ltd."
549+author = "LAZR Developers <lazr-developers@lists.launchpad.net>"
550
551 # The version info for the project you're documenting, acts as replacement for
552 # |version| and |release|, also used in various other places throughout the
553@@ -140,8 +138,8 @@ latex_documents = [
554 (
555 master_doc,
556 "lazrrestful.tex",
557- u"lazr.restful Documentation",
558- u"LAZR Developers \\textless{}lazr-developers@lists.launchpad.net\\textgreater{}", # noqa: E501
559+ "lazr.restful Documentation",
560+ "LAZR Developers \\textless{}lazr-developers@lists.launchpad.net\\textgreater{}", # noqa: E501
561 "manual",
562 ),
563 ]
564@@ -152,7 +150,7 @@ latex_documents = [
565 # One entry per manual page. List of tuples
566 # (source start file, name, description, authors, manual section).
567 man_pages = [
568- (master_doc, "lazrrestful", u"lazr.restful Documentation", [author], 1)
569+ (master_doc, "lazrrestful", "lazr.restful Documentation", [author], 1)
570 ]
571
572
573@@ -165,7 +163,7 @@ texinfo_documents = [
574 (
575 master_doc,
576 "lazrrestful",
577- u"lazr.restful Documentation",
578+ "lazr.restful Documentation",
579 author,
580 "lazrrestful",
581 "One line description of project.",
582diff --git a/src/lazr/restful/error.py b/src/lazr/restful/error.py
583index 86cef16..a2cf44b 100644
584--- a/src/lazr/restful/error.py
585+++ b/src/lazr/restful/error.py
586@@ -2,9 +2,6 @@
587
588 """Error handling on the webservice."""
589
590-from __future__ import absolute_import, division, print_function
591-
592-__metaclass__ = type
593 __all__ = [
594 "ClientErrorView",
595 "expose",
596diff --git a/src/lazr/restful/example/base/filemanager.py b/src/lazr/restful/example/base/filemanager.py
597index fccb0fc..781bf88 100644
598--- a/src/lazr/restful/example/base/filemanager.py
599+++ b/src/lazr/restful/example/base/filemanager.py
600@@ -2,9 +2,6 @@
601
602 """The file manager for the LAZR example web service."""
603
604-from __future__ import absolute_import, print_function
605-
606-__metaclass__ = type
607 __all__ = ["FileManager", "ManagedFileResource"]
608
609 import datetime
610diff --git a/src/lazr/restful/example/base/interfaces.py b/src/lazr/restful/example/base/interfaces.py
611index b6d7d85..c315cea 100644
612--- a/src/lazr/restful/example/base/interfaces.py
613+++ b/src/lazr/restful/example/base/interfaces.py
614@@ -3,9 +3,6 @@
615
616 """Interface objects for the LAZR example web service."""
617
618-from __future__ import absolute_import, print_function
619-
620-__metaclass__ = type
621 __all__ = [
622 "AlreadyNew",
623 "Cuisine",
624@@ -65,7 +62,7 @@ class WhitespaceStrippingTextLine(TextLine):
625 """Strip whitespace before setting."""
626 if value is not None:
627 value = value.strip()
628- super(WhitespaceStrippingTextLine, self).set(object, value)
629+ super().set(object, value)
630
631
632 class Cuisine(EnumeratedType):
633@@ -75,7 +72,7 @@ class Cuisine(EnumeratedType):
634 VEGETARIAN = Item("Vegetarian", "Vegetarian cooking")
635 AMERICAN = Item("American", "Traditional American cooking")
636 DESSERT = Item("Dessert", "Desserts")
637- FRANCAISE = Item(u"Fran\xe7aise", u"Cuisine fran\xe7aise")
638+ FRANCAISE = Item("Fran\xe7aise", "Cuisine fran\xe7aise")
639
640
641 class IHasGet(Interface):
642@@ -89,10 +86,10 @@ class IHasGet(Interface):
643 class IDish(ILocation):
644 """A dish, annotated for export to the web service."""
645
646- name = exported(TextLine(title=u"Name", required=True))
647+ name = exported(TextLine(title="Name", required=True))
648 recipes = exported(
649 CollectionField(
650- title=u"Recipes in this cookbook",
651+ title="Recipes in this cookbook",
652 value_type=Reference(schema=Interface),
653 )
654 )
655@@ -105,17 +102,17 @@ class IDish(ILocation):
656 class IRecipe(ILocation):
657 """A recipe, annotated for export to the web service."""
658
659- id = exported(Int(title=u"Unique ID", required=True))
660- dish = exported(Reference(title=u"Dish", schema=IDish))
661- cookbook = exported(Reference(title=u"Cookbook", schema=Interface))
662+ id = exported(Int(title="Unique ID", required=True))
663+ dish = exported(Reference(title="Dish", schema=IDish))
664+ cookbook = exported(Reference(title="Cookbook", schema=Interface))
665 instructions = exported(
666- Text(title=u"How to prepare the recipe", required=True)
667+ Text(title="How to prepare the recipe", required=True)
668 )
669 private = exported(
670- Bool(title=u"Whether the public can see this recipe.", default=False)
671+ Bool(title="Whether the public can see this recipe.", default=False)
672 )
673 prepared_image = exported(
674- Bytes(0, 5000, title=u"An image of the prepared dish.", readonly=True)
675+ Bytes(0, 5000, title="An image of the prepared dish.", readonly=True)
676 )
677
678 @export_destructor_operation()
679@@ -127,55 +124,53 @@ class IRecipe(ILocation):
680 class ICookbook(IHasGet, ILocation):
681 """A cookbook, annotated for export to the web service."""
682
683- name = exported(TextLine(title=u"Name", required=True))
684+ name = exported(TextLine(title="Name", required=True))
685 copyright_date = exported(
686 Date(
687- title=u"Copyright Date",
688- description=u"The copyright date for this work.",
689+ title="Copyright Date",
690+ description="The copyright date for this work.",
691 ),
692 readonly=True,
693 )
694 description = exported(
695- WhitespaceStrippingTextLine(title=u"Description", required=False)
696+ WhitespaceStrippingTextLine(title="Description", required=False)
697 )
698 revision_number = exported(
699 Int(
700- title=u"A record of the number of times "
701+ title="A record of the number of times "
702 "this cookbook has been modified."
703 )
704 )
705 confirmed = exported(
706 Bool(
707- title=u"Whether this information has been confirmed", default=False
708+ title="Whether this information has been confirmed", default=False
709 )
710 )
711 cuisine = exported(
712 Choice(
713- vocabulary=Cuisine, title=u"Cuisine", required=False, default=None
714+ vocabulary=Cuisine, title="Cuisine", required=False, default=None
715 )
716 )
717 last_printing = exported(
718 Date(
719- title=u"Last printing",
720- description=u"The date of this work's most recent printing.",
721+ title="Last printing",
722+ description="The date of this work's most recent printing.",
723 )
724 )
725 # Don't try this at home! Float is a bad choice for a 'price'
726 # field because it's imprecise. Decimal is a better choice. But
727 # this is just an example and we need a Float field, so...
728- price = exported(Float(title=u"Retail price of the cookbook"))
729+ price = exported(Float(title="Retail price of the cookbook"))
730 recipes = exported(
731 CollectionField(
732- title=u"Recipes in this cookbook",
733+ title="Recipes in this cookbook",
734 value_type=Reference(schema=IRecipe),
735 )
736 )
737- cover = exported(
738- Bytes(0, 5000, title=u"An image of the cookbook's cover.")
739- )
740+ cover = exported(Bytes(0, 5000, title="An image of the cookbook's cover."))
741
742 @operation_parameters(
743- search=TextLine(title=u"String to search for in recipe name.")
744+ search=TextLine(title="String to search for in recipe name.")
745 )
746 @operation_returns_collection_of(IRecipe)
747 @export_read_operation()
748@@ -183,7 +178,7 @@ class ICookbook(IHasGet, ILocation):
749 """Search for recipes in this cookbook."""
750
751 @operation_parameters(
752- dish=Reference(title=u"Dish to search for.", schema=IDish)
753+ dish=Reference(title="Dish to search for.", schema=IDish)
754 )
755 @operation_returns_entry(IRecipe)
756 @export_read_operation()
757@@ -197,7 +192,7 @@ class ICookbook(IHasGet, ILocation):
758 def removeRecipe(recipe):
759 """Remove one of this cookbook's recipes."""
760
761- @operation_parameters(cover=Bytes(title=u"New cover"))
762+ @operation_parameters(cover=Bytes(title="New cover"))
763 @export_write_operation()
764 def replace_cover(cover):
765 """Replace the cookbook's cover."""
766@@ -231,9 +226,9 @@ class ICookbookSet(IHasGet):
767 """Return the list of cookbooks."""
768
769 @operation_parameters(
770- search=TextLine(title=u"String to search for in recipe name."),
771+ search=TextLine(title="String to search for in recipe name."),
772 vegetarian=Bool(
773- title=u"Whether or not to limit the search to "
774+ title="Whether or not to limit the search to "
775 "vegetarian cookbooks.",
776 default=False,
777 ),
778@@ -245,7 +240,7 @@ class ICookbookSet(IHasGet):
779
780 @operation_parameters(
781 cuisine=Choice(
782- vocabulary=Cuisine, title=u"Cuisine to search for in recipe name."
783+ vocabulary=Cuisine, title="Cuisine to search for in recipe name."
784 )
785 )
786 @operation_returns_collection_of(ICookbook)
787diff --git a/src/lazr/restful/example/base/root.py b/src/lazr/restful/example/base/root.py
788index 424c971..85771b7 100644
789--- a/src/lazr/restful/example/base/root.py
790+++ b/src/lazr/restful/example/base/root.py
791@@ -2,9 +2,6 @@
792
793 """Data model objects for the LAZR example web service."""
794
795-from __future__ import absolute_import, print_function
796-
797-__metaclass__ = type
798 __all__ = [
799 "Cookbook",
800 "CookbookServiceRootResource",
801@@ -382,22 +379,22 @@ def year(year):
802
803
804 C1 = Cookbook(
805- u"Mastering the Art of French Cooking", "", Cuisine.FRANCAISE, year(1961)
806+ "Mastering the Art of French Cooking", "", Cuisine.FRANCAISE, year(1961)
807 )
808-C2 = Cookbook(u"The Joy of Cooking", "", Cuisine.GENERAL, year(1995), price=20)
809+C2 = Cookbook("The Joy of Cooking", "", Cuisine.GENERAL, year(1995), price=20)
810 C3 = Cookbook(
811- u"James Beard's American Cookery", "", Cuisine.AMERICAN, year(1972)
812+ "James Beard's American Cookery", "", Cuisine.AMERICAN, year(1972)
813 )
814-C4 = Cookbook(u"Everyday Greens", "", Cuisine.VEGETARIAN, year(2003))
815-C5 = Cookbook(u"I'm Just Here For The Food", "", Cuisine.GENERAL, year(2002))
816-C6 = Cookbook(u"Cooking Without Recipes", "", Cuisine.GENERAL, year(1959))
817-C7 = Cookbook(u"Construsions un repas", "", Cuisine.FRANCAISE, year(2007))
818+C4 = Cookbook("Everyday Greens", "", Cuisine.VEGETARIAN, year(2003))
819+C5 = Cookbook("I'm Just Here For The Food", "", Cuisine.GENERAL, year(2002))
820+C6 = Cookbook("Cooking Without Recipes", "", Cuisine.GENERAL, year(1959))
821+C7 = Cookbook("Construsions un repas", "", Cuisine.FRANCAISE, year(2007))
822 COOKBOOKS = [C1, C2, C3, C4, C5, C6, C7]
823
824 D1 = Dish("Roast chicken")
825-C1_D1 = Recipe(1, C1, D1, u"You can always judge...")
826-C2_D1 = Recipe(2, C2, D1, u"Draw, singe, stuff, and truss...")
827-C3_D1 = Recipe(3, C3, D1, u"A perfectly roasted chicken is...")
828+C1_D1 = Recipe(1, C1, D1, "You can always judge...")
829+C2_D1 = Recipe(2, C2, D1, "Draw, singe, stuff, and truss...")
830+C3_D1 = Recipe(3, C3, D1, "A perfectly roasted chicken is...")
831
832 D2 = Dish("Baked beans")
833 C2_D2 = Recipe(4, C2, D2, "Preheat oven to...")
834diff --git a/src/lazr/restful/example/base/security.py b/src/lazr/restful/example/base/security.py
835index bbb5165..0f33cb0 100644
836--- a/src/lazr/restful/example/base/security.py
837+++ b/src/lazr/restful/example/base/security.py
838@@ -2,9 +2,6 @@
839
840 """A simple security policy for the LAZR example web service."""
841
842-from __future__ import absolute_import, print_function
843-
844-__metaclass__ = type
845 __all__ = [
846 "CookbookWebServiceSecurityPolicy",
847 ]
848diff --git a/src/lazr/restful/example/base/subscribers.py b/src/lazr/restful/example/base/subscribers.py
849index 68ff062..fa6f973 100644
850--- a/src/lazr/restful/example/base/subscribers.py
851+++ b/src/lazr/restful/example/base/subscribers.py
852@@ -2,9 +2,6 @@
853
854 """Event listeners for the example web service."""
855
856-from __future__ import absolute_import, print_function
857-
858-__metaclass__ = type
859 __all__ = ["update_cookbook_revision_number"]
860
861 import grokcore.component
862diff --git a/src/lazr/restful/example/base/tests/test_integration.py b/src/lazr/restful/example/base/tests/test_integration.py
863index 99b987f..f0bbbb1 100644
864--- a/src/lazr/restful/example/base/tests/test_integration.py
865+++ b/src/lazr/restful/example/base/tests/test_integration.py
866@@ -2,9 +2,6 @@
867
868 """Test harness for LAZR doctests."""
869
870-from __future__ import absolute_import, print_function
871-
872-__metaclass__ = type
873 __all__ = []
874
875 import os
876@@ -58,16 +55,11 @@ def load_tests(loader, tests, pattern):
877 for name in os.listdir(os.path.dirname(__file__))
878 if name.endswith(".txt")
879 )
880- globs = {
881- "absolute_import": absolute_import,
882- "print_function": print_function,
883- }
884 suite = doctest.DocFileSuite(
885 *doctest_files,
886 optionflags=DOCTEST_FLAGS,
887- globs=globs,
888 encoding="UTF-8",
889- checker=checker
890+ checker=checker,
891 )
892 suite.layer = WSGILayer
893 tests.addTest(suite)
894diff --git a/src/lazr/restful/example/base/traversal.py b/src/lazr/restful/example/base/traversal.py
895index 4b06202..4ae07a9 100644
896--- a/src/lazr/restful/example/base/traversal.py
897+++ b/src/lazr/restful/example/base/traversal.py
898@@ -2,9 +2,6 @@
899
900 """Traversal rules for the LAZR example web service."""
901
902-from __future__ import absolute_import, print_function
903-
904-__metaclass__ = type
905 __all__ = [
906 "BelowRootAbsoluteURL",
907 "CookbookSetTraverse",
908@@ -99,6 +96,4 @@ class CookbookSetTraverse(TraverseWithGet):
909 url = absoluteURL(self.context.featured, request) + "{invalid}"
910 return RedirectResource(url, request)
911 else:
912- return super(CookbookSetTraverse, self).publishTraverse(
913- request, name
914- )
915+ return super().publishTraverse(request, name)
916diff --git a/src/lazr/restful/example/base_extended/comments.py b/src/lazr/restful/example/base_extended/comments.py
917index 8db2763..5973204 100644
918--- a/src/lazr/restful/example/base_extended/comments.py
919+++ b/src/lazr/restful/example/base_extended/comments.py
920@@ -1,5 +1,3 @@
921-from __future__ import absolute_import, print_function
922-
923 from zope.component import adapter
924 from zope.interface import implementer, Interface
925 from zope.schema import List, Text
926@@ -15,7 +13,7 @@ from lazr.restful.declarations import (
927 @exported_as_webservice_entry(contributes_to=[IRecipe])
928 class IHasComments(Interface):
929 comments = exported(
930- List(title=u"Comments made by users", value_type=Text())
931+ List(title="Comments made by users", value_type=Text())
932 )
933
934
935diff --git a/src/lazr/restful/example/base_extended/tests/test_integration.py b/src/lazr/restful/example/base_extended/tests/test_integration.py
936index e5b0021..866c905 100644
937--- a/src/lazr/restful/example/base_extended/tests/test_integration.py
938+++ b/src/lazr/restful/example/base_extended/tests/test_integration.py
939@@ -2,9 +2,6 @@
940
941 """Test harness for LAZR doctests."""
942
943-from __future__ import absolute_import, print_function
944-
945-__metaclass__ = type
946 __all__ = []
947
948 import os
949@@ -46,12 +43,8 @@ wsgi_intercept_layer(WSGILayer)
950 def load_tests(loader, tests, pattern):
951 """See `zope.testing.testrunner`."""
952 doctest_files = ["../README.txt"]
953- globs = {
954- "absolute_import": absolute_import,
955- "print_function": print_function,
956- }
957 suite = doctest.DocFileSuite(
958- *doctest_files, optionflags=DOCTEST_FLAGS, globs=globs, checker=checker
959+ *doctest_files, optionflags=DOCTEST_FLAGS, checker=checker
960 )
961 suite.layer = WSGILayer
962 tests.addTest(suite)
963diff --git a/src/lazr/restful/example/multiversion/resources.py b/src/lazr/restful/example/multiversion/resources.py
964index 849d579..cf45690 100644
965--- a/src/lazr/restful/example/multiversion/resources.py
966+++ b/src/lazr/restful/example/multiversion/resources.py
967@@ -1,7 +1,3 @@
968-from __future__ import absolute_import, print_function
969-
970-__metaclass__ = type
971-
972 __all__ = ["IKeyValuePair", "IPairSet", "KeyValuePair", "PairSet"]
973
974 from zope.interface import implementer
975@@ -36,14 +32,14 @@ from lazr.restful.example.wsgi.resources import (
976 # define them separately.
977 @exported_as_webservice_entry()
978 class IKeyValuePair(ILocation):
979- key = exported(Text(title=u"The key"))
980- value = exported(Text(title=u"The value"))
981+ key = exported(Text(title="The key"))
982+ value = exported(Text(title="The value"))
983 a_comment = exported(
984- Text(title=u"A comment on this key-value pair.", readonly=True),
985+ Text(title="A comment on this key-value pair.", readonly=True),
986 ("1.0", dict(exported=True, exported_as="comment")),
987 )
988 deleted = exported(
989- Bool(title=u"Whether this key-value pair has been " "deleted"),
990+ Bool(title="Whether this key-value pair has been " "deleted"),
991 ("3.0", dict(exported=True)),
992 exported=False,
993 )
994@@ -117,7 +113,7 @@ class PairSet(BasicPairSet):
995 @implementer(IKeyValuePair)
996 class KeyValuePair(BasicKeyValuePair):
997 def __init__(self, pairset, key, value):
998- super(KeyValuePair, self).__init__(pairset, key, value)
999+ super().__init__(pairset, key, value)
1000 self.a_comment = ""
1001 self.deleted = False
1002
1003diff --git a/src/lazr/restful/example/multiversion/root.py b/src/lazr/restful/example/multiversion/root.py
1004index 2391d4b..c611cda 100644
1005--- a/src/lazr/restful/example/multiversion/root.py
1006+++ b/src/lazr/restful/example/multiversion/root.py
1007@@ -1,8 +1,5 @@
1008 """The RESTful service root."""
1009
1010-from __future__ import absolute_import, print_function
1011-
1012-__metaclass__ = type
1013 __all__ = [
1014 "BelowRootAbsoluteURL",
1015 "RootAbsoluteURL",
1016diff --git a/src/lazr/restful/example/multiversion/tests/test_integration.py b/src/lazr/restful/example/multiversion/tests/test_integration.py
1017index 92772a4..ee04982 100644
1018--- a/src/lazr/restful/example/multiversion/tests/test_integration.py
1019+++ b/src/lazr/restful/example/multiversion/tests/test_integration.py
1020@@ -2,9 +2,6 @@
1021
1022 """Test harness for doctests for lazr.restful multiversion example service."""
1023
1024-from __future__ import absolute_import, print_function
1025-
1026-__metaclass__ = type
1027 __all__ = []
1028
1029 import os
1030@@ -59,12 +56,8 @@ def load_tests(loader, tests, pattern):
1031 for name in os.listdir(os.path.dirname(__file__))
1032 if name.endswith(".txt")
1033 )
1034- globs = {
1035- "absolute_import": absolute_import,
1036- "print_function": print_function,
1037- }
1038 suite = doctest.DocFileSuite(
1039- *doctest_files, optionflags=DOCTEST_FLAGS, globs=globs, checker=checker
1040+ *doctest_files, optionflags=DOCTEST_FLAGS, checker=checker
1041 )
1042 suite.layer = WSGILayer
1043 tests.addTest(suite)
1044diff --git a/src/lazr/restful/example/wsgi/resources.py b/src/lazr/restful/example/wsgi/resources.py
1045index ad42f66..1ae11fc 100644
1046--- a/src/lazr/restful/example/wsgi/resources.py
1047+++ b/src/lazr/restful/example/wsgi/resources.py
1048@@ -1,7 +1,3 @@
1049-from __future__ import absolute_import, print_function
1050-
1051-__metaclass__ = type
1052-
1053 __all__ = ["IKeyValuePair", "IPairSet", "KeyValuePair", "PairSet"]
1054
1055 from zope.component import getUtility
1056@@ -21,8 +17,8 @@ from lazr.restful.simple import TraverseWithGet
1057
1058 @exported_as_webservice_entry()
1059 class IKeyValuePair(ILocation):
1060- key = exported(Text(title=u"The key"))
1061- value = exported(Text(title=u"The value"))
1062+ key = exported(Text(title="The key"))
1063+ value = exported(Text(title="The value"))
1064
1065
1066 @exported_as_webservice_collection(IKeyValuePair)
1067@@ -36,7 +32,7 @@ class IPairSet(ILocation):
1068
1069
1070 @implementer(IKeyValuePair, ILocation)
1071-class KeyValuePair(object):
1072+class KeyValuePair:
1073 """An object representing a key-value pair"""
1074
1075 def __init__(self, set, key, value):
1076diff --git a/src/lazr/restful/example/wsgi/root.py b/src/lazr/restful/example/wsgi/root.py
1077index efd246d..a870d0b 100644
1078--- a/src/lazr/restful/example/wsgi/root.py
1079+++ b/src/lazr/restful/example/wsgi/root.py
1080@@ -1,8 +1,5 @@
1081 """The RESTful service root."""
1082
1083-from __future__ import absolute_import, print_function
1084-
1085-__metaclass__ = type
1086 __all__ = [
1087 "BelowRootAbsoluteURL",
1088 "RootAbsoluteURL",
1089diff --git a/src/lazr/restful/example/wsgi/run.py b/src/lazr/restful/example/wsgi/run.py
1090index b49b188..ff0dedc 100644
1091--- a/src/lazr/restful/example/wsgi/run.py
1092+++ b/src/lazr/restful/example/wsgi/run.py
1093@@ -1,7 +1,5 @@
1094 #!/usr/bin/python
1095
1096-from __future__ import absolute_import, print_function
1097-
1098 from lazr.restful.wsgi import WSGIApplication
1099
1100 if __name__ == "__main__":
1101diff --git a/src/lazr/restful/example/wsgi/tests/test_integration.py b/src/lazr/restful/example/wsgi/tests/test_integration.py
1102index f8f5583..cc02ba7 100644
1103--- a/src/lazr/restful/example/wsgi/tests/test_integration.py
1104+++ b/src/lazr/restful/example/wsgi/tests/test_integration.py
1105@@ -2,9 +2,6 @@
1106
1107 """Test harness for doctests for lazr.restful example WSGI service."""
1108
1109-from __future__ import absolute_import, print_function
1110-
1111-__metaclass__ = type
1112 __all__ = []
1113
1114 import os
1115@@ -57,12 +54,8 @@ def load_tests(loader, tests, pattern):
1116 for name in os.listdir(os.path.dirname(__file__))
1117 if name.endswith(".txt")
1118 )
1119- globs = {
1120- "absolute_import": absolute_import,
1121- "print_function": print_function,
1122- }
1123 suite = doctest.DocFileSuite(
1124- *doctest_files, optionflags=DOCTEST_FLAGS, globs=globs, checker=checker
1125+ *doctest_files, optionflags=DOCTEST_FLAGS, checker=checker
1126 )
1127 suite.layer = WSGILayer
1128 tests.addTest(suite)
1129diff --git a/src/lazr/restful/fields.py b/src/lazr/restful/fields.py
1130index a9e9756..4699769 100644
1131--- a/src/lazr/restful/fields.py
1132+++ b/src/lazr/restful/fields.py
1133@@ -2,9 +2,6 @@
1134
1135 """LAZR zope.schema.IField implementation."""
1136
1137-from __future__ import absolute_import, print_function
1138-
1139-__metaclass__ = type
1140 __all__ = [
1141 "CollectionField",
1142 "Reference",
1143@@ -39,7 +36,7 @@ class CollectionField(AbstractCollection):
1144 are managed through a dedicated API.
1145 """
1146 kwargs.setdefault("readonly", True)
1147- super(CollectionField, self).__init__(*args, **kwargs)
1148+ super().__init__(*args, **kwargs)
1149
1150
1151 @implementer(IReference)
1152@@ -75,4 +72,4 @@ class ReferenceChoice(Choice):
1153 """
1154 schema = kwargs.pop("schema", IObject)
1155 self.schema = schema
1156- super(ReferenceChoice, self).__init__(*args, **kwargs)
1157+ super().__init__(*args, **kwargs)
1158diff --git a/src/lazr/restful/frameworks/django.py b/src/lazr/restful/frameworks/django.py
1159index a1d09c2..a7ae447 100644
1160--- a/src/lazr/restful/frameworks/django.py
1161+++ b/src/lazr/restful/frameworks/django.py
1162@@ -2,7 +2,6 @@
1163
1164 """Helpers for publishing Django model objects in lazr.restful services."""
1165
1166-__metaclass__ = type
1167 __all__ = [
1168 "DjangoLocation",
1169 "DjangoWebServiceConfiguration",
1170@@ -102,7 +101,7 @@ class DjangoAbsoluteURL(AbsoluteURL):
1171
1172
1173 @implementer(ILocation)
1174-class DjangoLocation(object):
1175+class DjangoLocation:
1176 """Adapts Django model objects to ILocation.
1177
1178 See `IDjangoLocation` for why Django model objects can't implement
1179@@ -125,7 +124,7 @@ grokcore.component.global_adapter(DjangoLocation, IDjangoLocation, ILocation)
1180
1181
1182 @implementer(IFiniteSequence)
1183-class ManagerSequencer(object):
1184+class ManagerSequencer:
1185 """Makes a Django manager object usable with lazr.batchnavigator.
1186
1187 IFiniteSequence requires that we implement __len__, and either
1188diff --git a/src/lazr/restful/interface.py b/src/lazr/restful/interface.py
1189index a69cf98..e63dcf1 100644
1190--- a/src/lazr/restful/interface.py
1191+++ b/src/lazr/restful/interface.py
1192@@ -2,9 +2,6 @@
1193
1194 """Helpers for working with Zope interface."""
1195
1196-from __future__ import absolute_import, print_function
1197-
1198-__metaclass__ = type
1199 __all__ = ["copy_attribute", "copy_field", "use_template"]
1200
1201 import sys
1202diff --git a/src/lazr/restful/interfaces/__init__.py b/src/lazr/restful/interfaces/__init__.py
1203index b0d1c27..8c7ea66 100644
1204--- a/src/lazr/restful/interfaces/__init__.py
1205+++ b/src/lazr/restful/interfaces/__init__.py
1206@@ -17,8 +17,6 @@
1207
1208 # pylint: disable-msg=W0401
1209
1210-from __future__ import absolute_import, print_function
1211-
1212 __version__ = 1.0
1213
1214 # Re-export in such a way that __version__ can still be imported if
1215diff --git a/src/lazr/restful/interfaces/_fields.py b/src/lazr/restful/interfaces/_fields.py
1216index d48a87d..36a15c1 100644
1217--- a/src/lazr/restful/interfaces/_fields.py
1218+++ b/src/lazr/restful/interfaces/_fields.py
1219@@ -16,9 +16,6 @@
1220
1221 """Interfaces for LAZR zope.schema fields."""
1222
1223-from __future__ import absolute_import, print_function
1224-
1225-__metaclass__ = type
1226 __all__ = [
1227 "ICollectionField",
1228 "IReference",
1229diff --git a/src/lazr/restful/interfaces/_rest.py b/src/lazr/restful/interfaces/_rest.py
1230index 9632dc6..8b92c74 100644
1231--- a/src/lazr/restful/interfaces/_rest.py
1232+++ b/src/lazr/restful/interfaces/_rest.py
1233@@ -18,9 +18,6 @@
1234 # Pylint doesn't grok zope interfaces.
1235 # pylint: disable-msg=E0211,E0213
1236
1237-from __future__ import absolute_import, print_function
1238-
1239-__metaclass__ = type
1240 __all__ = [
1241 "IByteStorage",
1242 "IByteStorageResource",
1243@@ -479,8 +476,8 @@ class IWebServiceConfiguration(Interface):
1244 caching_policy = List(
1245 value_type=Int(),
1246 default=[7 * 24 * HOUR, 1 * HOUR],
1247- title=u"The web service caching policy.",
1248- description=u"""A list of two numbers, each to be used in the
1249+ title="The web service caching policy.",
1250+ description="""A list of two numbers, each to be used in the
1251 'max-age' field of the Cache-Control header. The first number is
1252 used when serving the service root for any web service version
1253 except the latest one. The second number is used when serving the
1254@@ -489,32 +486,32 @@ class IWebServiceConfiguration(Interface):
1255 )
1256
1257 enable_server_side_representation_cache = Bool(
1258- title=u"Enable the server-side representation cache.",
1259+ title="Enable the server-side representation cache.",
1260 default=True,
1261- description=u"""If this is false, the server-side representation
1262+ description="""If this is false, the server-side representation
1263 cache will not be used, even if one is registered.""",
1264 )
1265
1266 service_description = TextLine(
1267- title=u"Service description",
1268- description=u"""A human-readable description of the web service.
1269+ title="Service description",
1270+ description="""A human-readable description of the web service.
1271
1272 The description may contain HTML, but if it does, it must be a
1273 valid XHTML fragment.
1274 """,
1275- default=u"",
1276+ default="",
1277 )
1278
1279 view_permission = TextLine(
1280- title=u"View permission",
1281- default=u"zope.View",
1282- description=u"The permission to use when checking object visibility.",
1283+ title="View permission",
1284+ default="zope.View",
1285+ description="The permission to use when checking object visibility.",
1286 )
1287
1288 path_override = TextLine(
1289- title=u"Web service path override",
1290- default=u"api",
1291- description=u"The path component for Ajax clients to use when making "
1292+ title="Web service path override",
1293+ default="api",
1294+ description="The path component for Ajax clients to use when making "
1295 "HTTP requests to the web service from their current virtual host. "
1296 "The use of this path component (/api/foo instead of /foo) will "
1297 "ensure that the request is processed as a web service request "
1298@@ -522,29 +519,29 @@ class IWebServiceConfiguration(Interface):
1299 )
1300
1301 use_https = Bool(
1302- title=u"Web service is secured",
1303+ title="Web service is secured",
1304 default=True,
1305- description=u"Whether or not requests to the web service are secured "
1306+ description="Whether or not requests to the web service are secured "
1307 "through SSL.",
1308 )
1309
1310 hostname = TextLine(
1311- title=u"The hostname to be used in generated URLs.",
1312- description=u"You only need to specify this if you're using the "
1313+ title="The hostname to be used in generated URLs.",
1314+ description="You only need to specify this if you're using the "
1315 "RootResourceAbsoluteURL class from lazr.restful.simple. This is "
1316 "the hostname of the lazr.restful application.",
1317 )
1318
1319 port = Int(
1320- title=u"The TCP port on which the web service is running.",
1321- description=u"Used in generated URLs.",
1322+ title="The TCP port on which the web service is running.",
1323+ description="Used in generated URLs.",
1324 default=0,
1325 )
1326
1327 service_root_uri_prefix = TextLine(
1328- title=u"Any URL prefix necessary for the service root.",
1329- default=u"",
1330- description=u"If your web service is not located at the root of "
1331+ title="Any URL prefix necessary for the service root.",
1332+ default="",
1333+ description="If your web service is not located at the root of "
1334 "its domain (for instance, it's rooted at "
1335 "http://foo.com/web-service/ instead of http://api.foo/com/, "
1336 "put the URL prefix here. (In the example case, the URL prefix "
1337@@ -554,8 +551,8 @@ class IWebServiceConfiguration(Interface):
1338 active_versions = List(
1339 value_type=TextLine(),
1340 default=[],
1341- title=u"The active versions of the web service.",
1342- description=u"""A list of names of active versions of this
1343+ title="The active versions of the web service.",
1344+ description="""A list of names of active versions of this
1345 web service. They might be version numbers, names such as
1346 "beta", or the date a particular version was finalized.
1347
1348@@ -571,8 +568,8 @@ class IWebServiceConfiguration(Interface):
1349 version_descriptions = Dict(
1350 key_type=TextLine(),
1351 value_type=Text(),
1352- title=u"Human-readable descriptions of the web service versions.",
1353- description=u"""A dictionary mapping version names to
1354+ title="Human-readable descriptions of the web service versions.",
1355+ description="""A dictionary mapping version names to
1356 human-readable descriptions. The descriptions should describe
1357 what distinguishes this version from other versions, and
1358 mention if/when the version will be removed.
1359@@ -585,7 +582,7 @@ class IWebServiceConfiguration(Interface):
1360
1361 require_explicit_versions = Bool(
1362 default=False,
1363- description=u"""If true, each exported field and named
1364+ description="""If true, each exported field and named
1365 operation must explicitly declare the first version in which
1366 it appears. If false, fields and operations are published in
1367 all versions.""",
1368@@ -593,7 +590,7 @@ class IWebServiceConfiguration(Interface):
1369
1370 last_version_with_mutator_named_operations = TextLine(
1371 default=None,
1372- description=u"""In earlier versions of lazr.restful, mutator methods
1373+ description="""In earlier versions of lazr.restful, mutator methods
1374 were also published as named operations. This redundant
1375 behavior is no longer enabled by default, but this setting
1376 allows for backwards compatibility.
1377@@ -606,48 +603,48 @@ class IWebServiceConfiguration(Interface):
1378
1379 first_version_with_total_size_link = TextLine(
1380 default=None,
1381- description=u"""In earlier versions of lazr.restful collections
1382+ description="""In earlier versions of lazr.restful collections
1383 included a total_size field, now they include a total_size_link
1384 instead. Setting this value determines in which version the new
1385 behavior takes effect.""",
1386 )
1387
1388 code_revision = TextLine(
1389- default=u"",
1390- description=u"""A string designating the current revision
1391+ default="",
1392+ description="""A string designating the current revision
1393 number of the code running the webservice. This may be a
1394 revision number from version control, or a hand-chosen version
1395 number.""",
1396 )
1397
1398 show_tracebacks = Bool(
1399- title=u"Show tracebacks to end-users",
1400+ title="Show tracebacks to end-users",
1401 default=True,
1402- description=u"Whether or not to show tracebacks in an HTTP response "
1403+ description="Whether or not to show tracebacks in an HTTP response "
1404 "for a request that raised an exception.",
1405 )
1406
1407 default_batch_size = Int(
1408- title=u"The default batch size to use when serving a collection",
1409+ title="The default batch size to use when serving a collection",
1410 default=50,
1411- description=u"When the client requests a collection and doesn't "
1412+ description="When the client requests a collection and doesn't "
1413 "specify how many entries they want, this many entries will be "
1414 "served them in the first page.",
1415 )
1416
1417 max_batch_size = Int(
1418- title=u"The maximum batch size",
1419+ title="The maximum batch size",
1420 default=300,
1421- description=u"When the client requests a batch of entries from "
1422+ description="When the client requests a batch of entries from "
1423 "a collection, they will not be allowed to request more entries "
1424 "in the batch than this.",
1425 )
1426
1427 compensate_for_mod_compress_etag_modification = Bool(
1428- title=u"Accept incoming ETags that appear to have been modified "
1429+ title="Accept incoming ETags that appear to have been modified "
1430 "in transit by Apache's mod_compress.",
1431 default=False,
1432- description=u"""When mod_compress compresses an outgoing
1433+ description="""When mod_compress compresses an outgoing
1434 representation, it (correctly) modifies the ETag. But when
1435 that ETag comes back in on a conditional GET or PUT request,
1436 mod_compress does _not_ transparently remove the modification,
1437diff --git a/src/lazr/restful/jsoncache.py b/src/lazr/restful/jsoncache.py
1438index 5c217c2..02349c3 100644
1439--- a/src/lazr/restful/jsoncache.py
1440+++ b/src/lazr/restful/jsoncache.py
1441@@ -2,10 +2,6 @@
1442 #
1443 """A class for storing resources where they can be seen by a template."""
1444
1445-from __future__ import absolute_import, print_function
1446-
1447-__metaclass__ = type
1448-
1449 __all__ = ["JSONRequestCache"]
1450
1451 from lazr.restful.interfaces import IJSONRequestCache, LAZR_WEBSERVICE_NS
1452diff --git a/src/lazr/restful/marshallers.py b/src/lazr/restful/marshallers.py
1453index bec584a..3439106 100644
1454--- a/src/lazr/restful/marshallers.py
1455+++ b/src/lazr/restful/marshallers.py
1456@@ -2,9 +2,6 @@
1457
1458 """Marshallers for fields used in HTTP resources."""
1459
1460-from __future__ import absolute_import, print_function
1461-
1462-__metaclass__ = type
1463 __all__ = [
1464 "AbstractCollectionFieldMarshaller",
1465 "BoolFieldMarshaller",
1466@@ -31,7 +28,6 @@ import re
1467
1468 import pytz
1469 import simplejson
1470-import six
1471 from six.moves.urllib.parse import unquote
1472
1473 from zope.datetime import (
1474@@ -92,9 +88,9 @@ class URLDereferencingMixin:
1475 request_host = full_request_host
1476 request_port = default_port
1477
1478- if not isinstance(url, six.string_types):
1479+ if not isinstance(url, str):
1480 raise ValueError(
1481- u"got '%s', expected string: %r" % (type(url).__name__, url)
1482+ "got '%s', expected string: %r" % (type(url).__name__, url)
1483 )
1484 if url.startswith("/"):
1485 # It's a relative URI. Resolve it relative to the root of this
1486@@ -145,9 +141,9 @@ class URLDereferencingMixin:
1487 resource = self.dereference_url(url)
1488 except NotFound:
1489 # The URL doesn't correspond to any real object.
1490- raise ValueError(u'No such object "%s".' % url)
1491+ raise ValueError('No such object "%s".' % url)
1492 except InvalidURIError:
1493- raise ValueError(u'"%s" is not a valid URI.' % url)
1494+ raise ValueError('"%s" is not a valid URI.' % url)
1495 # We looked up the URL and got the thing at the other end of
1496 # the URL: a resource. But internally, a resource isn't a
1497 # valid value for any schema field. Instead we want the object
1498@@ -193,8 +189,8 @@ class SimpleFieldMarshaller:
1499 v = value
1500 if isinstance(v, bytes):
1501 v = v.decode("utf8") # assume utf8
1502- elif not isinstance(v, six.text_type):
1503- v = six.text_type(v)
1504+ elif not isinstance(v, str):
1505+ v = str(v)
1506 value = simplejson.loads(v)
1507 except (ValueError, TypeError):
1508 # Pass the value as is. This saves client from having to encode
1509@@ -225,7 +221,7 @@ class SimpleFieldMarshaller:
1510 else:
1511 expected_name = self._type.__name__
1512 raise ValueError(
1513- u"got '%s', expected %s: %r"
1514+ "got '%s', expected %s: %r"
1515 % (type(value).__name__, expected_name, value)
1516 )
1517 return value
1518@@ -275,9 +271,7 @@ class FloatFieldMarshaller(SimpleFieldMarshaller):
1519
1520 Converts the value to a float.
1521 """
1522- return float(
1523- super(FloatFieldMarshaller, self)._marshall_from_json_data(value)
1524- )
1525+ return float(super()._marshall_from_json_data(value))
1526
1527
1528 class BytesFieldMarshaller(SimpleFieldMarshaller):
1529@@ -319,7 +313,7 @@ class BytesFieldMarshaller(SimpleFieldMarshaller):
1530 if safe_hasattr(value, "seek"):
1531 value.seek(0)
1532 value = value.read()
1533- elif not isinstance(value, (bytes, six.text_type)):
1534+ elif not isinstance(value, (bytes, str)):
1535 value = str(value).encode("UTF-8")
1536 else:
1537 # Leave string conversion to _marshall_from_json_data.
1538@@ -331,17 +325,15 @@ class BytesFieldMarshaller(SimpleFieldMarshaller):
1539
1540 Convert all strings to byte strings.
1541 """
1542- if isinstance(value, six.text_type):
1543+ if isinstance(value, str):
1544 value = value.encode("utf-8")
1545- return super(BytesFieldMarshaller, self)._marshall_from_json_data(
1546- value
1547- )
1548+ return super()._marshall_from_json_data(value)
1549
1550
1551 class TextFieldMarshaller(SimpleFieldMarshaller):
1552 """FieldMarshaller for IText fields."""
1553
1554- _type = six.text_type
1555+ _type = str
1556 _type_error_message = "not a unicode string: %r"
1557
1558 def _marshall_from_request(self, value):
1559@@ -349,12 +341,12 @@ class TextFieldMarshaller(SimpleFieldMarshaller):
1560
1561 Converts the value to unicode.
1562 """
1563- value = six.text_type(value)
1564+ value = str(value)
1565 # multipart/form-data encoding of text fields is required (RFC 2046
1566 # section 4.1.1) to use CRLF for line breaks. Normalize to
1567 # Unix-style LF.
1568 value = re.sub(r"\r\n?", "\n", value)
1569- return super(TextFieldMarshaller, self)._marshall_from_request(value)
1570+ return super()._marshall_from_request(value)
1571
1572
1573 class FixedVocabularyFieldMarshaller(SimpleFieldMarshaller):
1574@@ -369,7 +361,7 @@ class FixedVocabularyFieldMarshaller(SimpleFieldMarshaller):
1575 part of a multiadapter lookup of the appropriate
1576 marshaller.
1577 """
1578- super(FixedVocabularyFieldMarshaller, self).__init__(field, request)
1579+ super().__init__(field, request)
1580
1581 def unmarshall_to_closeup(self, entry, value):
1582 """Describe all values, not just the selected value."""
1583@@ -386,9 +378,7 @@ class TokenizedVocabularyFieldMarshaller(FixedVocabularyFieldMarshaller):
1584 """A marshaller that looks up value using a token in a vocabulary."""
1585
1586 def __init__(self, field, request, vocabulary):
1587- super(TokenizedVocabularyFieldMarshaller, self).__init__(
1588- field, request, vocabulary
1589- )
1590+ super().__init__(field, request, vocabulary)
1591
1592 def _marshall_from_json_data(self, value):
1593 """See `SimpleFieldMarshaller`.
1594@@ -396,11 +386,9 @@ class TokenizedVocabularyFieldMarshaller(FixedVocabularyFieldMarshaller):
1595 Looks up the value as a token in the vocabulary.
1596 """
1597 try:
1598- return self.field.vocabulary.getTermByToken(
1599- six.text_type(value)
1600- ).value
1601+ return self.field.vocabulary.getTermByToken(str(value)).value
1602 except LookupError:
1603- raise ValueError(u"%r isn't a valid token" % value)
1604+ raise ValueError("%r isn't a valid token" % value)
1605
1606
1607 class DateTimeFieldMarshaller(SimpleFieldMarshaller):
1608@@ -454,7 +442,7 @@ class DateFieldMarshaller(DateTimeFieldMarshaller):
1609
1610 def _marshall_from_json_data(self, value):
1611 """Parse the value as a datetime.date object."""
1612- super_class = super(DateFieldMarshaller, self)
1613+ super_class = super()
1614 date_time = super_class._marshall_from_json_data(value)
1615 return date_time.date()
1616
1617@@ -475,7 +463,7 @@ class AbstractCollectionFieldMarshaller(SimpleFieldMarshaller):
1618
1619 This also looks for the appropriate marshaller for value_type.
1620 """
1621- super(AbstractCollectionFieldMarshaller, self).__init__(field, request)
1622+ super().__init__(field, request)
1623 self.value_marshaller = getMultiAdapter(
1624 (field.value_type or Field(), request), IFieldMarshaller
1625 )
1626@@ -486,9 +474,7 @@ class AbstractCollectionFieldMarshaller(SimpleFieldMarshaller):
1627 Marshall every elements of the list using the appropriate
1628 marshaller.
1629 """
1630- value = super(
1631- AbstractCollectionFieldMarshaller, self
1632- )._marshall_from_json_data(value)
1633+ value = super()._marshall_from_json_data(value)
1634
1635 # In AbstractCollection subclasses, _type contains the type object,
1636 # which can be used as a factory.
1637@@ -556,7 +542,7 @@ class DictFieldMarshaller(SimpleFieldMarshaller):
1638 value_type. If key_type or value_type are not specified, the default
1639 field marshaller is used.
1640 """
1641- super(DictFieldMarshaller, self).__init__(field, request)
1642+ super().__init__(field, request)
1643 self.key_marshaller = getMultiAdapter(
1644 (field.key_type or Field(), request), IFieldMarshaller
1645 )
1646@@ -582,7 +568,7 @@ class DictFieldMarshaller(SimpleFieldMarshaller):
1647 try:
1648 value = dict(nv.split(",", 2) for nv in value)
1649 except ValueError:
1650- raise ValueError(u"got '%s', list of name,value pairs" % value)
1651+ raise ValueError("got '%s', list of name,value pairs" % value)
1652 return {
1653 self.key_marshaller.marshall_from_json_data(
1654 key
1655@@ -602,9 +588,7 @@ class DictFieldMarshaller(SimpleFieldMarshaller):
1656 if isinstance(value, list):
1657 value = dict(value)
1658 # Call super to check for errors and raise a ValueError if necessary.
1659- value = super(DictFieldMarshaller, self)._marshall_from_json_data(
1660- value
1661- )
1662+ value = super()._marshall_from_json_data(value)
1663 return {
1664 self.key_marshaller.marshall_from_json_data(
1665 key
1666@@ -671,9 +655,7 @@ class SimpleVocabularyLookupFieldMarshaller(FixedVocabularyFieldMarshaller):
1667
1668 def __init__(self, field, request, vocabulary):
1669 """Initialize the marshaller with the vocabulary it'll use."""
1670- super(SimpleVocabularyLookupFieldMarshaller, self).__init__(
1671- field, request, vocabulary
1672- )
1673+ super().__init__(field, request, vocabulary)
1674 self.vocabulary = vocabulary
1675
1676 def _marshall_from_json_data(self, value):
1677@@ -684,7 +666,7 @@ class SimpleVocabularyLookupFieldMarshaller(FixedVocabularyFieldMarshaller):
1678 return item
1679 valid_titles.append(item.title)
1680 raise ValueError(
1681- u'Invalid value "%s". Acceptable values are: %s'
1682+ 'Invalid value "%s". Acceptable values are: %s'
1683 % (value, ", ".join(valid_titles))
1684 )
1685
1686@@ -704,7 +686,7 @@ class ObjectLookupFieldMarshaller(
1687 """
1688
1689 def __init__(self, field, request, vocabulary=None):
1690- super(ObjectLookupFieldMarshaller, self).__init__(field, request)
1691+ super().__init__(field, request)
1692 self.vocabulary = vocabulary
1693
1694 @property
1695diff --git a/src/lazr/restful/metazcml.py b/src/lazr/restful/metazcml.py
1696index 1fe9422..09c0274 100644
1697--- a/src/lazr/restful/metazcml.py
1698+++ b/src/lazr/restful/metazcml.py
1699@@ -2,9 +2,6 @@
1700
1701 """ZCML registration directives for the LAZR webservice framework."""
1702
1703-from __future__ import absolute_import, print_function
1704-
1705-__metaclass__ = type
1706 __all__ = []
1707
1708
1709@@ -82,7 +79,7 @@ class IRegisterDirective(Interface):
1710 """
1711
1712 module = GlobalObject(
1713- title=u"Module which will be inspected for webservice declarations"
1714+ title="Module which will be inspected for webservice declarations"
1715 )
1716
1717
1718diff --git a/src/lazr/restful/publisher.py b/src/lazr/restful/publisher.py
1719index eb628a4..92b668a 100644
1720--- a/src/lazr/restful/publisher.py
1721+++ b/src/lazr/restful/publisher.py
1722@@ -6,9 +6,6 @@ This module defines classes that are usually needed for integration
1723 with the Zope publisher.
1724 """
1725
1726-from __future__ import absolute_import, division, print_function
1727-
1728-__metaclass__ = type
1729 __all__ = [
1730 "browser_request_to_web_service_request",
1731 "WebServicePublicationMixin",
1732@@ -119,9 +116,7 @@ class WebServicePublicationMixin:
1733 else:
1734 # Falls through to our parent version.
1735 pass
1736- return super(WebServicePublicationMixin, self).traverseName(
1737- request, ob, name
1738- )
1739+ return super().traverseName(request, ob, name)
1740
1741 def _traverseToByteStorage(self, request, entry, field, name):
1742 """Try to traverse to a byte storage resource in entry."""
1743@@ -223,9 +218,7 @@ class WebServicePublicationMixin:
1744
1745 def callObject(self, request, object):
1746 """Help web browsers handle redirects correctly."""
1747- value = super(WebServicePublicationMixin, self).callObject(
1748- request, object
1749- )
1750+ value = super().callObject(request, object)
1751 self._processNotifications(request)
1752 if request.response.getStatus() // 100 == 3:
1753 if IWebBrowserInitiatedRequest.providedBy(request):
1754@@ -263,7 +256,7 @@ class WebServicePublicationMixin:
1755
1756
1757 @implementer(IWebServiceClientRequest)
1758-class WebServiceRequestTraversal(object):
1759+class WebServiceRequestTraversal:
1760 """Mixin providing web-service resource wrapping in traversal.
1761
1762 This should be mixed in the request using to the base publication used.
1763@@ -288,7 +281,7 @@ class WebServiceRequestTraversal(object):
1764 # was requested and has set the application appropriately, so
1765 # now we can get a good value for 'ob' and traverse it.
1766 ob = self.publication.getApplication(self)
1767- result = super(WebServiceRequestTraversal, self).traverse(ob)
1768+ result = super().traverse(ob)
1769 return self.publication.getResource(self, result)
1770
1771 def _removeVirtualHostTraversals(self):
1772diff --git a/src/lazr/restful/security.py b/src/lazr/restful/security.py
1773index 05d5802..f7cc532 100644
1774--- a/src/lazr/restful/security.py
1775+++ b/src/lazr/restful/security.py
1776@@ -2,9 +2,6 @@
1777
1778 """Utilities for dealing with zope security."""
1779
1780-from __future__ import absolute_import, print_function
1781-
1782-__metaclass__ = type
1783 __all__ = [
1784 "protect_schema",
1785 ]
1786diff --git a/src/lazr/restful/simple.py b/src/lazr/restful/simple.py
1787index b846e96..2c58320 100644
1788--- a/src/lazr/restful/simple.py
1789+++ b/src/lazr/restful/simple.py
1790@@ -1,8 +1,5 @@
1791 """Simple implementations of various Zope and lazr.restful interfaces."""
1792
1793-from __future__ import absolute_import, print_function
1794-
1795-__metaclass__ = type
1796 __all__ = [
1797 "BaseRepresentationCache",
1798 "BaseWebServiceConfiguration",
1799@@ -20,7 +17,6 @@ __all__ = [
1800
1801 import traceback
1802
1803-import six
1804 from six.moves.urllib.parse import (
1805 quote,
1806 unquote,
1807@@ -63,7 +59,7 @@ from lazr.restful.utils import (
1808
1809
1810 @implementer(IPublication)
1811-class PublicationMixin(object):
1812+class PublicationMixin:
1813 """A very simple implementation of `IPublication`.
1814
1815 The object passed to the constructor is returned by getApplication().
1816@@ -160,7 +156,7 @@ class Publication(WebServicePublicationMixin, PublicationMixin):
1817
1818
1819 @implementer(ITraverseWithGet)
1820-class TraverseWithGet(object):
1821+class TraverseWithGet:
1822 """An implementation of `IPublishTraverse` that uses the get() method.
1823
1824 This is a simple traversal technique that works with any object
1825@@ -395,9 +391,7 @@ class MultiplePathPartAbsoluteURL:
1826 parts = getattr(self.context, "__path_parts__", None)
1827 if parts is None:
1828 raise TypeError(_insufficientContext)
1829- if isinstance(parts, six.string_types) or not hasattr(
1830- parts, "__iter__"
1831- ):
1832+ if isinstance(parts, str) or not hasattr(parts, "__iter__"):
1833 raise TypeError(
1834 "Expected an iterable of strings for __path_parts__."
1835 )
1836@@ -409,7 +403,7 @@ class MultiplePathPartAbsoluteURL:
1837
1838
1839 @implementer(IRepresentationCache)
1840-class BaseRepresentationCache(object):
1841+class BaseRepresentationCache:
1842 """A useful base class for representation caches.
1843
1844 When an object is invalidated, all of its representations must be
1845diff --git a/src/lazr/restful/tales.py b/src/lazr/restful/tales.py
1846index 2968667..0be2185 100644
1847--- a/src/lazr/restful/tales.py
1848+++ b/src/lazr/restful/tales.py
1849@@ -26,10 +26,6 @@
1850
1851 """Implementation of the ws: namespace in TALES."""
1852
1853-from __future__ import absolute_import, print_function
1854-
1855-__metaclass__ = type
1856-
1857 import operator
1858 import re
1859 import simplejson
1860@@ -370,7 +366,7 @@ class WadlEntryResourceAPI(WadlResourceAPI):
1861
1862 def __init__(self, entry_resource):
1863 "Initialize with an entry resource."
1864- super(WadlEntryResourceAPI, self).__init__(entry_resource)
1865+ super().__init__(entry_resource)
1866 self.entry = self.resource.entry
1867 self.schema = self.entry.schema
1868
1869@@ -407,7 +403,7 @@ class WadlCollectionResourceAPI(WadlResourceAPI):
1870 + quote(relationship_name)
1871 )
1872 else:
1873- return super(WadlCollectionResourceAPI, self).url
1874+ return super().url
1875
1876 @property
1877 def type_link(self):
1878@@ -563,9 +559,7 @@ class WadlEntryInterfaceAdapterAPI(WadlResourceAdapterAPI):
1879 """
1880
1881 def __init__(self, entry_interface):
1882- super(WadlEntryInterfaceAdapterAPI, self).__init__(
1883- entry_interface, IEntry
1884- )
1885+ super().__init__(entry_interface, IEntry)
1886 self.utility = EntryAdapterUtility.forEntryInterface(
1887 entry_interface, get_current_web_service_request()
1888 )
1889@@ -584,7 +578,7 @@ class WadlEntryAdapterAPI(WadlResourceAdapterAPI):
1890 """
1891
1892 def __init__(self, adapter):
1893- super(WadlEntryAdapterAPI, self).__init__(adapter, IEntry)
1894+ super().__init__(adapter, IEntry)
1895 self.utility = EntryAdapterUtility(adapter)
1896
1897 @property
1898@@ -662,7 +656,7 @@ class WadlCollectionAdapterAPI(WadlResourceAdapterAPI):
1899 "Namespace for WADL functions that operate on collection adapters."
1900
1901 def __init__(self, adapter):
1902- super(WadlCollectionAdapterAPI, self).__init__(adapter, ICollection)
1903+ super().__init__(adapter, ICollection)
1904
1905 @property
1906 def collection_type(self):
1907diff --git a/src/lazr/restful/testing/event.py b/src/lazr/restful/testing/event.py
1908index 7431413..e199790 100644
1909--- a/src/lazr/restful/testing/event.py
1910+++ b/src/lazr/restful/testing/event.py
1911@@ -2,10 +2,6 @@
1912
1913 """Helper class for checking the event notifications."""
1914
1915-from __future__ import absolute_import, print_function
1916-
1917-__metaclass__ = type
1918-
1919 import zope.component
1920
1921
1922diff --git a/src/lazr/restful/testing/helpers.py b/src/lazr/restful/testing/helpers.py
1923index 46c7d90..fc9c8b1 100644
1924--- a/src/lazr/restful/testing/helpers.py
1925+++ b/src/lazr/restful/testing/helpers.py
1926@@ -1,5 +1,3 @@
1927-from __future__ import absolute_import, print_function
1928-
1929 import sys
1930 from types import ModuleType
1931
1932diff --git a/src/lazr/restful/testing/tales.py b/src/lazr/restful/testing/tales.py
1933index ad64e0b..ce08dce 100644
1934--- a/src/lazr/restful/testing/tales.py
1935+++ b/src/lazr/restful/testing/tales.py
1936@@ -2,10 +2,6 @@
1937
1938 """Helper functions for testing TALES expressions."""
1939
1940-from __future__ import absolute_import, print_function
1941-
1942-__metaclass__ = type
1943-
1944 __all__ = [
1945 "test_tales",
1946 ]
1947diff --git a/src/lazr/restful/testing/webservice.py b/src/lazr/restful/testing/webservice.py
1948index 9eccb04..a4405b1 100644
1949--- a/src/lazr/restful/testing/webservice.py
1950+++ b/src/lazr/restful/testing/webservice.py
1951@@ -2,9 +2,6 @@
1952
1953 """Testing helpers for webservice unit tests."""
1954
1955-from __future__ import absolute_import, print_function
1956-
1957-__metaclass__ = type
1958 __all__ = [
1959 "create_web_service_request",
1960 "StubAbsoluteURL",
1961@@ -141,7 +138,7 @@ class FakeResponse:
1962 if result is None:
1963 result = ""
1964
1965- if not isinstance(result, six.string_types):
1966+ if not isinstance(result, str):
1967 raise ValueError("only strings and None results are handled")
1968
1969 self.result = result
1970@@ -200,7 +197,7 @@ def pformat_value(value):
1971 JSON strings are always Unicode, never bytes, so this doesn't introduce
1972 ambiguity.
1973 """
1974- if isinstance(value, six.text_type):
1975+ if isinstance(value, str):
1976 value = value.encode("unicode_escape").decode("ASCII")
1977 if "'" in value and '"' not in value:
1978 return '"%s"' % value
1979@@ -259,7 +256,7 @@ class WebServiceApplication(Application):
1980 """A WSGI application for the tests."""
1981
1982 def __init__(self, global_config, publication, **options):
1983- if isinstance(publication, six.string_types):
1984+ if isinstance(publication, str):
1985 Application.__init__(self, global_config, publication, **options)
1986 else:
1987 self.publication = publication(global_config, **options)
1988@@ -329,7 +326,7 @@ class WebServiceCaller:
1989 headers=None,
1990 api_version=None,
1991 ):
1992- if isinstance(path_or_url, (bytes, six.text_type)):
1993+ if isinstance(path_or_url, (bytes, str)):
1994 path_or_url = six.ensure_str(path_or_url)
1995 else:
1996 path_or_url = str(path_or_url)
1997@@ -468,7 +465,7 @@ class WebServiceCaller:
1998 if isinstance(value, io.BufferedIOBase):
1999 buf.write(value.read())
2000 else:
2001- if not isinstance(value, six.string_types):
2002+ if not isinstance(value, str):
2003 value = simplejson.dumps(value)
2004 lines = re.split(r"\r\n|\r|\n", value)
2005 for line in lines[:-1]:
2006@@ -536,7 +533,7 @@ class WebServiceCaller:
2007
2008 This may mean turning the value into a JSON string.
2009 """
2010- if not isinstance(value, six.string_types):
2011+ if not isinstance(value, str):
2012 value = simplejson.dumps(value)
2013 return quote(value)
2014
2015@@ -560,17 +557,16 @@ class WebServiceAjaxCaller(WebServiceCaller):
2016 def default_api_version(self):
2017 """Introduce the Ajax path override to the URI prefix."""
2018 config = getUtility(IWebServiceConfiguration)
2019- default_version = super(WebServiceAjaxCaller, self).default_api_version
2020+ default_version = super().default_api_version
2021 return config.path_override + "/" + default_version
2022
2023
2024-@six.python_2_unicode_compatible
2025 class WebServiceResponseWrapper(ProxyBase):
2026 """A response from the web service with easy access to the JSON body."""
2027
2028 def __init__(self, response):
2029 self.body = response.read()
2030- super(WebServiceResponseWrapper, self).__init__(response)
2031+ super().__init__(response)
2032
2033 def getHeader(self, key, default=None):
2034 return self.getheader(key, default)
2035@@ -659,7 +655,7 @@ class TestCaseWithWebServiceFixtures(CleanUp, unittest.TestCase):
2036 """
2037
2038 def setUp(self):
2039- super(TestCaseWithWebServiceFixtures, self).setUp()
2040+ super().setUp()
2041 # Register a simple configuration object.
2042 webservice_configuration = WebServiceTestConfiguration()
2043 sm = getGlobalSiteManager()
2044@@ -717,7 +713,7 @@ class WebServiceTestCase(TestCaseWithWebServiceFixtures):
2045
2046 def setUp(self):
2047 """Set the component registry with the given model."""
2048- super(WebServiceTestCase, self).setUp()
2049+ super().setUp()
2050
2051 # Register a service root resource
2052 sm = getGlobalSiteManager()
2053@@ -769,12 +765,12 @@ class IGenericEntry(Interface):
2054 # pylint: disable-msg=E0213
2055 a_field = exported(
2056 TextLine(
2057- title=u'A "field"',
2058- description=u"The only field that can be <> 0 in the entry.",
2059+ title='A "field"',
2060+ description="The only field that can be <> 0 in the entry.",
2061 )
2062 )
2063
2064- @operation_parameters(message=TextLine(title=u"Message to say"))
2065+ @operation_parameters(message=TextLine(title="Message to say"))
2066 @export_read_operation()
2067 def greet(message):
2068 """Print an appropriate greeting based on the message.
2069@@ -831,4 +827,4 @@ def simple_renderer(value):
2070 This is a good HTML field renderer to use in tests, because it
2071 tests Unicode values and embedded HTML.
2072 """
2073- return u"\N{SNOWMAN} <b>%s</b>" % value
2074+ return "\N{SNOWMAN} <b>%s</b>" % value
2075diff --git a/src/lazr/restful/tests/test_declarations.py b/src/lazr/restful/tests/test_declarations.py
2076index f1c688c..305709b 100644
2077--- a/src/lazr/restful/tests/test_declarations.py
2078+++ b/src/lazr/restful/tests/test_declarations.py
2079@@ -2,8 +2,6 @@
2080
2081 """Unit tests for the conversion of interfaces into a web service."""
2082
2083-from __future__ import absolute_import, print_function
2084-
2085 import sys
2086
2087 import testtools
2088@@ -85,7 +83,7 @@ class ContributingInterfacesTestCase(TestCaseWithWebServiceFixtures):
2089 """Tests for interfaces that contribute fields/operations to others."""
2090
2091 def setUp(self):
2092- super(ContributingInterfacesTestCase, self).setUp()
2093+ super().setUp()
2094 sm = getSiteManager()
2095 sm.registerAdapter(ProductToHasBugsAdapter)
2096 sm.registerAdapter(ProjectToHasBugsAdapter)
2097@@ -152,7 +150,7 @@ class ContributingInterfacesTestCase(TestCaseWithWebServiceFixtures):
2098 @exported_as_webservice_entry(contributes_to=[IProduct])
2099 class IHasTooManyAccessors(Interface):
2100 needs_an_accessor = exported(
2101- TextLine(title=u"This needs an accessor", readonly=True)
2102+ TextLine(title="This needs an accessor", readonly=True)
2103 )
2104
2105 @accessor_for(needs_an_accessor)
2106@@ -353,7 +351,7 @@ class ContributingInterfacesTestCase(TestCaseWithWebServiceFixtures):
2107
2108 @exported_as_webservice_entry(contributes_to=[INotExported])
2109 class IContributor(Interface):
2110- title = exported(TextLine(title=u"The project title"))
2111+ title = exported(TextLine(title="The project title"))
2112
2113 self.assertRaises(
2114 AttemptToContributeToNonExportedInterface,
2115@@ -436,7 +434,7 @@ class TestExportAsWebserviceEntry(testtools.TestCase):
2116 """Tests for export_as_webservice_entry."""
2117
2118 def setUp(self):
2119- super(TestExportAsWebserviceEntry, self).setUp()
2120+ super().setUp()
2121 if sys.version_info[0] >= 3:
2122 self.skipTest(
2123 "export_as_webservice_entry is only supported on Python 2"
2124@@ -454,7 +452,7 @@ class TestExportAsWebserviceEntry(testtools.TestCase):
2125 def test_requires_interface(self):
2126 # export_as_webservice_entry can only be used on Interface.
2127 def export_non_interface():
2128- class NotAnInterface(object):
2129+ class NotAnInterface:
2130 export_as_webservice_entry()
2131
2132 exception = self.assertRaises(TypeError, export_non_interface)
2133@@ -478,7 +476,7 @@ class TestExportAsWebserviceCollection(testtools.TestCase):
2134 """Tests for export_as_webservice_collection."""
2135
2136 def setUp(self):
2137- super(TestExportAsWebserviceCollection, self).setUp()
2138+ super().setUp()
2139 if sys.version_info[0] >= 3:
2140 self.skipTest(
2141 "export_as_webservice_collection is only supported on "
2142@@ -568,7 +566,7 @@ class TestExportAsWebserviceCollection(testtools.TestCase):
2143 def test_requires_interface(self):
2144 # export_as_webservice_collection can only be used on Interface.
2145 def export_non_interface():
2146- class NotAnInterface(object):
2147+ class NotAnInterface:
2148 export_as_webservice_collection(Interface)
2149
2150 exception = self.assertRaises(TypeError, export_non_interface)
2151@@ -626,21 +624,21 @@ class TestFindExportedInterfaces(testtools.TestCase):
2152 )
2153
2154 def test_finds_exported_exceptions(self):
2155- class Module(object):
2156+ class Module:
2157 NotExportedException_copy = NotExportedException
2158 ExportedExceptionOne_copy = ExportedExceptionOne
2159
2160 self.assertExportsNames(Module, ["ExportedExceptionOne"])
2161
2162 def test_finds_exported_interfaces(self):
2163- class Module(object):
2164+ class Module:
2165 INotExported_copy = INotExported
2166 IExported_copy = IExported
2167
2168 self.assertExportsNames(Module, ["IExported"])
2169
2170 def test_honours_all(self):
2171- class Module(object):
2172+ class Module:
2173 __all__ = ["ExportedExceptionOne_copy"]
2174 ExportedExceptionOne_copy = ExportedExceptionOne
2175 ExportedExceptionTwo_copy = ExportedExceptionTwo
2176@@ -648,7 +646,7 @@ class TestFindExportedInterfaces(testtools.TestCase):
2177 self.assertExportsNames(Module, ["ExportedExceptionOne"])
2178
2179 def test_skips_leading_underscore_without_all(self):
2180- class Module(object):
2181+ class Module:
2182 ExportedExceptionOne_copy = ExportedExceptionOne
2183 _ExportedExceptionTwo_copy = ExportedExceptionTwo
2184
2185@@ -657,7 +655,7 @@ class TestFindExportedInterfaces(testtools.TestCase):
2186
2187 @exported_as_webservice_entry()
2188 class IProduct(Interface):
2189- title = exported(TextLine(title=u"The product title"))
2190+ title = exported(TextLine(title="The product title"))
2191 # Need to define the three attributes below because we have a test which
2192 # wraps a Product object with a security proxy and later uses adapters
2193 # that access _dev_branch, _branches and _bug_count.
2194@@ -668,7 +666,7 @@ class IProduct(Interface):
2195
2196
2197 @implementer(IProduct)
2198-class Product(object):
2199+class Product:
2200 title = "A product"
2201 _bug_count = 0
2202 _dev_branch = None
2203@@ -678,21 +676,21 @@ class Product(object):
2204
2205 @exported_as_webservice_entry()
2206 class IProject(Interface):
2207- title = exported(TextLine(title=u"The project title"))
2208+ title = exported(TextLine(title="The project title"))
2209
2210
2211 @implementer(IProject)
2212-class Project(object):
2213+class Project:
2214 title = "A project"
2215 _bug_count = 0
2216
2217
2218 @exported_as_webservice_entry(contributes_to=[IProduct, IProject])
2219 class IHasBugs(Interface):
2220- bug_count = exported(Int(title=u"Number of bugs"))
2221- not_exported = TextLine(title=u"Not exported")
2222+ bug_count = exported(Int(title="Number of bugs"))
2223+ not_exported = TextLine(title="Not exported")
2224 bug_target_name = exported(
2225- TextLine(title=u"The bug target name of this object.", readonly=True)
2226+ TextLine(title="The bug target name of this object.", readonly=True)
2227 )
2228
2229 @export_read_operation()
2230@@ -726,13 +724,13 @@ class IHasBugs(Interface):
2231
2232 @exported_as_webservice_entry(contributes_to=[IProduct])
2233 class IHasBugs2(Interface):
2234- bug_count = exported(Int(title=u"Number of bugs"))
2235- not_exported = TextLine(title=u"Not exported")
2236+ bug_count = exported(Int(title="Number of bugs"))
2237+ not_exported = TextLine(title="Not exported")
2238
2239
2240 @exported_as_webservice_entry(contributes_to=[IProduct])
2241 class IHasBugs3(Interface):
2242- not_exported = TextLine(title=u"Not exported")
2243+ not_exported = TextLine(title="Not exported")
2244
2245 @export_read_operation()
2246 def getBugsCount():
2247@@ -741,7 +739,7 @@ class IHasBugs3(Interface):
2248
2249 @adapter(IProduct)
2250 @implementer(IHasBugs)
2251-class ProductToHasBugsAdapter(object):
2252+class ProductToHasBugsAdapter:
2253 def __init__(self, context):
2254 self.context = context
2255 self.bug_count = context._bug_count
2256@@ -766,18 +764,18 @@ class ProjectToHasBugsAdapter(ProductToHasBugsAdapter):
2257
2258 @exported_as_webservice_entry()
2259 class IBranch(Interface):
2260- name = TextLine(title=u"The branch name")
2261+ name = TextLine(title="The branch name")
2262
2263
2264 @implementer(IBranch)
2265-class Branch(object):
2266+class Branch:
2267 def __init__(self, name):
2268 self.name = name
2269
2270
2271 @exported_as_webservice_entry(contributes_to=[IProduct])
2272 class IHasBranches(Interface):
2273- not_exported = TextLine(title=u"Not exported")
2274+ not_exported = TextLine(title="Not exported")
2275 development_branch = exported(
2276 Reference(schema=IBranch, readonly=True),
2277 ("2.0", dict(exported_as="development_branch_20")),
2278@@ -804,7 +802,7 @@ class IHasBranches(Interface):
2279
2280 @adapter(IProduct)
2281 @implementer(IHasBranches)
2282-class ProductToHasBranchesAdapter(object):
2283+class ProductToHasBranchesAdapter:
2284 def __init__(self, context):
2285 self.context = context
2286
2287@@ -876,7 +874,7 @@ class TestEntryMultiversion(TestCaseWithWebServiceFixtures):
2288 interfaces = generate_entry_interfaces(
2289 INotInitiallyExported,
2290 [],
2291- *getUtility(IWebServiceConfiguration).active_versions
2292+ *getUtility(IWebServiceConfiguration).active_versions,
2293 )
2294 self.assertEqual(len(interfaces), 1)
2295 self.assertEqual(interfaces[0].version, "2.0")
2296@@ -887,7 +885,7 @@ class TestEntryMultiversion(TestCaseWithWebServiceFixtures):
2297 interfaces = generate_entry_interfaces(
2298 INotPresentInLaterVersion,
2299 [],
2300- *getUtility(IWebServiceConfiguration).active_versions
2301+ *getUtility(IWebServiceConfiguration).active_versions,
2302 )
2303 self.assertEqual(len(interfaces), 1)
2304 self.assertEqual(interfaces[0].version, "1.0")
2305@@ -898,7 +896,7 @@ class TestEntryMultiversion(TestCaseWithWebServiceFixtures):
2306 interfaces = generate_entry_interfaces(
2307 IHasDifferentNamesInDifferentVersions,
2308 [],
2309- *getUtility(IWebServiceConfiguration).active_versions
2310+ *getUtility(IWebServiceConfiguration).active_versions,
2311 )
2312 interface_10 = interfaces[0].object
2313 tags_10 = interface_10.getTaggedValue(LAZR_WEBSERVICE_NAME)
2314@@ -936,7 +934,7 @@ class TestEntryMultiversion(TestCaseWithWebServiceFixtures):
2315 interfaces = generate_entry_interfaces(
2316 IHasDifferentSingularNamesInDifferentVersions,
2317 [],
2318- *getUtility(IWebServiceConfiguration).active_versions
2319+ *getUtility(IWebServiceConfiguration).active_versions,
2320 )
2321 interface_10 = interfaces[0].object
2322 tags_10 = interface_10.getTaggedValue(LAZR_WEBSERVICE_NAME)
2323@@ -1024,7 +1022,7 @@ class IFieldExplicitOperationDefinition(Interface):
2324
2325
2326 @implementer(IFieldExplicitOperationDefinition)
2327-class FieldExplicitOperationDefinition(object):
2328+class FieldExplicitOperationDefinition:
2329 pass
2330
2331
2332@@ -1032,7 +1030,7 @@ class TestRequireExplicitVersions(TestCaseWithWebServiceFixtures):
2333 """Test behavior when require_explicit_versions is True."""
2334
2335 def setUp(self):
2336- super(TestRequireExplicitVersions, self).setUp()
2337+ super().setUp()
2338 self.utility = getUtility(IWebServiceConfiguration)
2339 self.utility.require_explicit_versions = True
2340
2341@@ -1061,7 +1059,7 @@ class TestRequireExplicitVersions(TestCaseWithWebServiceFixtures):
2342 generate_entry_interfaces,
2343 IEntryExportedWithoutAsOf,
2344 [],
2345- *self.utility.active_versions
2346+ *self.utility.active_versions,
2347 )
2348 self.assertEqual(
2349 str(exception),
2350@@ -1078,7 +1076,7 @@ class TestRequireExplicitVersions(TestCaseWithWebServiceFixtures):
2351 interfaces = generate_entry_interfaces(
2352 IFieldExportedToEarliestVersionUsingAsOf,
2353 [],
2354- *self.utility.active_versions
2355+ *self.utility.active_versions,
2356 )
2357 interface_10 = interfaces[0].object
2358 interface_20 = interfaces[1].object
2359@@ -1093,7 +1091,7 @@ class TestRequireExplicitVersions(TestCaseWithWebServiceFixtures):
2360 interfaces = generate_entry_interfaces(
2361 IFieldExportedToLatestVersionUsingAsOf,
2362 [],
2363- *self.utility.active_versions
2364+ *self.utility.active_versions,
2365 )
2366 interface_10 = interfaces[0].object
2367 interface_20 = interfaces[1].object
2368@@ -1108,7 +1106,7 @@ class TestRequireExplicitVersions(TestCaseWithWebServiceFixtures):
2369 generate_entry_interfaces,
2370 IFieldExportedWithoutAsOf,
2371 [],
2372- *self.utility.active_versions
2373+ *self.utility.active_versions,
2374 )
2375 self.assertEqual(
2376 str(exception),
2377@@ -1140,7 +1138,7 @@ class TestRequireExplicitVersions(TestCaseWithWebServiceFixtures):
2378 generate_entry_interfaces,
2379 IFieldAsOfNonexistentVersion,
2380 [],
2381- *self.utility.active_versions
2382+ *self.utility.active_versions,
2383 )
2384 self.assertEqual(
2385 str(exception),
2386@@ -1158,7 +1156,7 @@ class TestRequireExplicitVersions(TestCaseWithWebServiceFixtures):
2387 generate_entry_interfaces,
2388 IFieldDoubleDefinition,
2389 [],
2390- *self.utility.active_versions
2391+ *self.utility.active_versions,
2392 )
2393 self.assertEqual(
2394 str(exception),
2395@@ -1176,7 +1174,7 @@ class TestRequireExplicitVersions(TestCaseWithWebServiceFixtures):
2396 generate_entry_interfaces,
2397 IFieldDefiningAttributesBeforeAsOf,
2398 [],
2399- *self.utility.active_versions
2400+ *self.utility.active_versions,
2401 )
2402 self.assertEqual(
2403 str(exception),
2404@@ -1370,7 +1368,7 @@ class TestCoherenceChecking(TestCaseWithWebServiceFixtures):
2405 ValueError,
2406 register_test_module,
2407 "testmod",
2408- *(list(classes) + [expect_failure_due_to_interface])
2409+ *(list(classes) + [expect_failure_due_to_interface]),
2410 )
2411 expected_message = (
2412 "In version %(version)s, %(reason)s, but version %(version)s "
2413diff --git a/src/lazr/restful/tests/test_docs.py b/src/lazr/restful/tests/test_docs.py
2414index a503ae6..26f9645 100644
2415--- a/src/lazr/restful/tests/test_docs.py
2416+++ b/src/lazr/restful/tests/test_docs.py
2417@@ -17,9 +17,6 @@
2418
2419 # pylint: disable=E0611,W0142
2420
2421-from __future__ import absolute_import, print_function
2422-
2423-__metaclass__ = type
2424 __all__ = []
2425
2426 import atexit
2427@@ -66,19 +63,14 @@ def load_tests(loader, tests, pattern):
2428 )
2429 )
2430 atexit.register(cleanup_resources)
2431- globs = {
2432- "absolute_import": absolute_import,
2433- "print_function": print_function,
2434- }
2435 tests.addTest(
2436 doctest.DocFileSuite(
2437 *doctest_files,
2438 module_relative=False,
2439 optionflags=DOCTEST_FLAGS,
2440 tearDown=tearDown,
2441- globs=globs,
2442 encoding="UTF-8",
2443- checker=checker
2444+ checker=checker,
2445 )
2446 )
2447 return tests
2448diff --git a/src/lazr/restful/tests/test_error.py b/src/lazr/restful/tests/test_error.py
2449index d407ccb..69adf07 100644
2450--- a/src/lazr/restful/tests/test_error.py
2451+++ b/src/lazr/restful/tests/test_error.py
2452@@ -2,10 +2,6 @@
2453
2454 """Tests of lazr.restful navigation."""
2455
2456-from __future__ import absolute_import, print_function
2457-
2458-__metaclass__ = type
2459-
2460 from pkg_resources import resource_filename
2461 import os
2462 import traceback
2463@@ -30,7 +26,7 @@ from lazr.restful.testing.webservice import FakeRequest
2464 class TestResource(ReadWriteResource):
2465 def __init__(self, callable, request):
2466 self.callable = callable
2467- super(TestResource, self).__init__(context=None, request=request)
2468+ super().__init__(context=None, request=request)
2469
2470 def do_GET(self):
2471 return self.callable()
2472@@ -57,7 +53,7 @@ class ErrorsTestCase(unittest.TestCase):
2473 pass
2474
2475 self.exception_class = MyException
2476- super(ErrorsTestCase, self).setUp()
2477+ super().setUp()
2478
2479 def test_decorated_exception_class_becomes_error_view(self):
2480 # An exposed exception, when raised, will set the response
2481@@ -140,7 +136,7 @@ class ErrorsTestCase(unittest.TestCase):
2482 # Register a view for the exception that does not subclass
2483 # WebServiceExceptionView and provides no information about
2484 # which HTTP status code should be used.
2485- class ViewHasNoStatus(object):
2486+ class ViewHasNoStatus:
2487 def __init__(*args):
2488 pass
2489
2490diff --git a/src/lazr/restful/tests/test_etag.py b/src/lazr/restful/tests/test_etag.py
2491index ed9a950..e9421a0 100644
2492--- a/src/lazr/restful/tests/test_etag.py
2493+++ b/src/lazr/restful/tests/test_etag.py
2494@@ -1,10 +1,6 @@
2495 # Copyright 2008 Canonical Ltd. All rights reserved.
2496 """Tests for ETag generation."""
2497
2498-from __future__ import absolute_import, print_function
2499-
2500-__metaclass__ = type
2501-
2502 from collections import OrderedDict
2503 from datetime import (
2504 date,
2505@@ -178,11 +174,11 @@ class EntryFieldResourceTests(unittest.TestCase):
2506 self.set_field_value("this is the field value")
2507
2508 # Find the cores generated with a given revision...
2509- self.config.code_revision = u"42"
2510+ self.config.code_revision = "42"
2511 first_cores = self.resource._getETagCores(self.resource.JSON_TYPE)
2512
2513 # ...find the cores generated with a different revision.
2514- self.config.code_revision = u"99"
2515+ self.config.code_revision = "99"
2516 second_cores = self.resource._getETagCores(self.resource.JSON_TYPE)
2517
2518 # The cores should be different.
2519@@ -223,11 +219,11 @@ class ServiceRootResourceTests(unittest.TestCase):
2520 # web service change.
2521
2522 # Find the cores generated with a given revision...
2523- self.config.code_revision = u"42"
2524+ self.config.code_revision = "42"
2525 first_cores = self.resource._getETagCores(self.resource.JSON_TYPE)
2526
2527 # ...find the cores generated with a different revision.
2528- self.config.code_revision = u"99"
2529+ self.config.code_revision = "99"
2530 second_cores = self.resource._getETagCores(self.resource.JSON_TYPE)
2531
2532 # The cores should be different.
2533@@ -240,12 +236,12 @@ class ServiceRootResourceTests(unittest.TestCase):
2534 # information.)
2535
2536 # Find the ETag generated with a given revision...
2537- self.config.code_revision = u"42"
2538+ self.config.code_revision = "42"
2539 first_etag = self.resource.getETag(self.resource.WADL_TYPE)
2540
2541 # ...and find the ETag generated with a different revision.
2542 self.resource.etags_by_media_type = {}
2543- self.config.code_revision = u"99"
2544+ self.config.code_revision = "99"
2545 second_etag = self.resource.getETag(self.resource.WADL_TYPE)
2546
2547 # The ETags should be different.
2548diff --git a/src/lazr/restful/tests/test_navigation.py b/src/lazr/restful/tests/test_navigation.py
2549index 568205e..ec5cc6d 100644
2550--- a/src/lazr/restful/tests/test_navigation.py
2551+++ b/src/lazr/restful/tests/test_navigation.py
2552@@ -2,10 +2,6 @@
2553
2554 """Tests of lazr.restful navigation."""
2555
2556-from __future__ import absolute_import, print_function
2557-
2558-__metaclass__ = type
2559-
2560 import unittest
2561
2562 from zope.component import (
2563@@ -34,14 +30,14 @@ from lazr.restful.testing.webservice import FakeRequest
2564 class IChild(Interface):
2565 """Interface for a simple entry."""
2566
2567- one = Text(title=u"One")
2568- two = Text(title=u"Two")
2569+ one = Text(title="One")
2570+ two = Text(title="Two")
2571
2572
2573 class IParent(Interface):
2574 """Interface for a simple entry that contains another entry."""
2575
2576- three = Text(title=u"Three")
2577+ three = Text(title="Three")
2578 child = Reference(schema=IChild)
2579
2580
2581@@ -49,8 +45,8 @@ class IParent(Interface):
2582 class Child:
2583 """A simple implementation of IChild."""
2584
2585- one = u"one"
2586- two = u"two"
2587+ one = "one"
2588+ two = "two"
2589
2590
2591 class ChildEntry:
2592@@ -66,7 +62,7 @@ class ChildEntry:
2593 class Parent:
2594 """A simple implementation of IParent."""
2595
2596- three = u"three"
2597+ three = "three"
2598 child = Child()
2599
2600
2601diff --git a/src/lazr/restful/tests/test_utils.py b/src/lazr/restful/tests/test_utils.py
2602index d095e02..db180d0 100644
2603--- a/src/lazr/restful/tests/test_utils.py
2604+++ b/src/lazr/restful/tests/test_utils.py
2605@@ -2,10 +2,6 @@
2606
2607 """Test for lazr.restful.utils."""
2608
2609-from __future__ import absolute_import, print_function
2610-
2611-__metaclass__ = type
2612-
2613 import random
2614 import testtools
2615 import unittest
2616@@ -101,7 +97,7 @@ class TestUtils(unittest.TestCase):
2617
2618 class TestVersionedDict(testtools.TestCase):
2619 def setUp(self):
2620- super(TestVersionedDict, self).setUp()
2621+ super().setUp()
2622 self.dict = VersionedDict()
2623
2624 def test_rename_version_works(self):
2625diff --git a/src/lazr/restful/tests/test_webservice.py b/src/lazr/restful/tests/test_webservice.py
2626index 4864150..e8c8010 100644
2627--- a/src/lazr/restful/tests/test_webservice.py
2628+++ b/src/lazr/restful/tests/test_webservice.py
2629@@ -2,10 +2,6 @@
2630
2631 """Test for the WADL generation."""
2632
2633-from __future__ import absolute_import, print_function
2634-
2635-__metaclass__ = type
2636-
2637 from contextlib import contextmanager
2638 from io import (
2639 BytesIO,
2640@@ -19,7 +15,6 @@ import re
2641 import simplejson
2642 import unittest
2643
2644-import six
2645 from zope.component import (
2646 eventtesting,
2647 getGlobalSiteManager,
2648@@ -256,7 +251,7 @@ class EntryTestCase(WebServiceTestCase):
2649 class IHasOneField(Interface):
2650 """An entry with a single field."""
2651
2652- a_field = exported(TextLine(title=u"A field."))
2653+ a_field = exported(TextLine(title="A field."))
2654
2655
2656 @implementer(IHasOneField)
2657@@ -271,8 +266,8 @@ class HasOneField:
2658 class IHasTwoFields(Interface):
2659 """An entry with two fields."""
2660
2661- a_field = exported(TextLine(title=u"A field."))
2662- another_field = exported(TextLine(title=u"Another field."))
2663+ a_field = exported(TextLine(title="A field."))
2664+ another_field = exported(TextLine(title="Another field."))
2665
2666
2667 @implementer(IHasTwoFields)
2668@@ -353,7 +348,7 @@ class TestEntryWebLink(EntryTestCase):
2669 class IHasNoWebLink(Interface):
2670 """An entry that does not publish a web_link."""
2671
2672- a_field = exported(TextLine(title=u"A field."))
2673+ a_field = exported(TextLine(title="A field."))
2674
2675
2676 @implementer(IHasNoWebLink)
2677@@ -383,7 +378,7 @@ class InterfaceRestrictedField(TextLine):
2678
2679 def __init__(self, restrict_to_interface, *args, **kwargs):
2680 self.restrict_to_interface = restrict_to_interface
2681- super(InterfaceRestrictedField, self).__init__(*args, **kwargs)
2682+ super().__init__(*args, **kwargs)
2683
2684 def bind(self, context):
2685 if not self.restrict_to_interface.providedBy(context):
2686@@ -391,7 +386,7 @@ class InterfaceRestrictedField(TextLine):
2687 "InterfaceRestrictedField can only be used with %s"
2688 % self.restrict_to_interface.__name__
2689 )
2690- return super(InterfaceRestrictedField, self).bind(context)
2691+ return super().bind(context)
2692
2693
2694 @exported_as_webservice_entry()
2695@@ -413,7 +408,7 @@ class HasRestrictedField:
2696 class IHasFieldExportedAsDifferentName(Interface):
2697 """An entry with a field exported as a different name."""
2698
2699- a_field = exported(TextLine(title=u"A field."), exported_as="field")
2700+ a_field = exported(TextLine(title="A field."), exported_as="field")
2701
2702
2703 @implementer(IHasFieldExportedAsDifferentName)
2704@@ -437,7 +432,7 @@ class TestEntryWrite(EntryTestCase):
2705 # If web_link is not published, applyChanges rejects a request
2706 # that references it.
2707 with self.entry_resource(HasOneField, "") as resource:
2708- errors = resource.applyChanges({"web_link": u"some_value"})
2709+ errors = resource.applyChanges({"web_link": "some_value"})
2710 self.assertEqual(
2711 errors,
2712 "web_link: You tried to modify a nonexistent attribute.",
2713@@ -448,7 +443,7 @@ class TestEntryWrite(EntryTestCase):
2714 self._register_website_url_space(IHasOneField)
2715
2716 with self.entry_resource(HasOneField, "") as resource:
2717- errors = resource.applyChanges({"web_link": u"some_value"})
2718+ errors = resource.applyChanges({"web_link": "some_value"})
2719 self.assertEqual(
2720 errors, "web_link: You tried to modify a read-only attribute."
2721 )
2722@@ -484,7 +479,7 @@ class TestEntryWrite(EntryTestCase):
2723
2724 with self.entry_resource(
2725 HasFieldExportedAsDifferentName,
2726- u"initial value",
2727+ "initial value",
2728 ) as resource:
2729 # We have an entry that has a different name on the
2730 # entry than on its context.
2731@@ -492,13 +487,13 @@ class TestEntryWrite(EntryTestCase):
2732 self.assertEqual(entry.field, entry.context.a_field)
2733 # This populates the cache.
2734 self.assertEqual(
2735- u"initial value", resource.toDataForJSON()["field"]
2736+ "initial value", resource.toDataForJSON()["field"]
2737 )
2738 # This returns the changed value.
2739 representation = simplejson.loads(
2740- resource.applyChanges(dict(field=u"new value"))
2741+ resource.applyChanges(dict(field="new value"))
2742 )
2743- self.assertEqual(u"new value", representation["field"])
2744+ self.assertEqual("new value", representation["field"])
2745
2746
2747 class TestEntryWriteForRestrictedField(EntryTestCase):
2748@@ -518,7 +513,7 @@ class TestEntryWriteForRestrictedField(EntryTestCase):
2749 entry = resource.entry
2750 entry.schema["a_field"].restrict_to_interface = IHasRestrictedField
2751 self.assertEqual(entry.a_field, "")
2752- resource.applyChanges({"a_field": u"a_value"})
2753+ resource.applyChanges({"a_field": "a_value"})
2754 self.assertEqual(entry.a_field, "a_value")
2755
2756 # Make sure that IHasRestrictedField itself works correctly.
2757@@ -531,7 +526,7 @@ class TestEntryWriteForRestrictedField(EntryTestCase):
2758 self.assertRaises(
2759 AssertionError,
2760 resource.applyChanges,
2761- {"a_field": u"a_new_value"},
2762+ {"a_field": "a_new_value"},
2763 )
2764 self.assertEqual(resource.entry.a_field, "a_value")
2765
2766@@ -542,9 +537,9 @@ class HTMLRepresentationTest(EntryTestCase):
2767 default_media_type = "application/xhtml+xml"
2768
2769 def setUp(self):
2770- super(HTMLRepresentationTest, self).setUp()
2771+ super().setUp()
2772 self._register_url_adapter(IHasOneField)
2773- self.unicode_message = u"Hello from a \N{SNOWMAN}"
2774+ self.unicode_message = "Hello from a \N{SNOWMAN}"
2775 self.utf8_message = self.unicode_message.encode("utf-8")
2776
2777 def test_entry_html_representation_is_utf8(self):
2778@@ -567,15 +562,13 @@ class JSONPlusHTMLRepresentationTest(EntryTestCase):
2779 testmodule_objects = [HasTwoFields, IHasTwoFields]
2780
2781 def setUp(self):
2782- super(JSONPlusHTMLRepresentationTest, self).setUp()
2783+ super().setUp()
2784 self.default_media_type = "application/json;include=lp_html"
2785 self._register_url_adapter(IHasTwoFields)
2786
2787 def register_html_field_renderer(self, name=""):
2788 """Simplify the register_html_field_renderer call."""
2789- super(
2790- JSONPlusHTMLRepresentationTest, self
2791- ).register_html_field_renderer(
2792+ super().register_html_field_renderer(
2793 IHasTwoFields, ITextLine, simple_renderer, name
2794 )
2795
2796@@ -584,8 +577,8 @@ class JSONPlusHTMLRepresentationTest(EntryTestCase):
2797 """Simplify the entry_resource call."""
2798 with self.entry_resource(
2799 HasTwoFields,
2800- six.text_type(value_1),
2801- six.text_type(value_2),
2802+ str(value_1),
2803+ str(value_2),
2804 ) as resource:
2805 yield resource
2806
2807@@ -654,7 +647,7 @@ class JSONPlusHTMLRepresentationTest(EntryTestCase):
2808 with self.resource() as resource:
2809 json_plus_xhtml = resource.JSON_PLUS_XHTML_TYPE
2810 json = simplejson.loads(
2811- six.text_type(resource._representation(json_plus_xhtml))
2812+ str(resource._representation(json_plus_xhtml))
2813 )
2814 resource.applyChanges(json, json_plus_xhtml)
2815 self.assertEqual(resource.request.response.getStatus(), 209)
2816@@ -664,9 +657,7 @@ class JSONPlusHTMLRepresentationTest(EntryTestCase):
2817 json = None
2818 with self.resource() as resource:
2819 json = simplejson.loads(
2820- six.text_type(
2821- resource._representation(resource.JSON_PLUS_XHTML_TYPE)
2822- )
2823+ str(resource._representation(resource.JSON_PLUS_XHTML_TYPE))
2824 )
2825 resource.applyChanges(json, resource.JSON_TYPE)
2826 self.assertEqual(resource.request.response.getStatus(), 400)
2827@@ -676,7 +667,7 @@ class UnicodeChoice(EnumeratedType):
2828 """A choice between an ASCII value and a Unicode value."""
2829
2830 ASCII = Item("Ascii", "Ascii choice")
2831- UNICODE = Item(u"Uni\u00e7ode", "Uni\u00e7ode choice")
2832+ UNICODE = Item("Uni\u00e7ode", "Uni\u00e7ode choice")
2833
2834
2835 @exported_as_webservice_entry()
2836@@ -686,7 +677,7 @@ class ICanBeSetToUnicodeValue(Interface):
2837 a_field = exported(
2838 Choice(
2839 vocabulary=UnicodeChoice,
2840- title=u"A value that might be ASCII or Unicode.",
2841+ title="A value that might be ASCII or Unicode.",
2842 required=False,
2843 default=None,
2844 )
2845@@ -707,7 +698,7 @@ class UnicodeErrorTestCase(EntryTestCase):
2846 testmodule_objects = [CanBeSetToUnicodeValue, ICanBeSetToUnicodeValue]
2847
2848 def setUp(self):
2849- super(UnicodeErrorTestCase, self).setUp()
2850+ super().setUp()
2851 self._register_url_adapter(ICanBeSetToUnicodeValue)
2852
2853 def test_unicode_error(self):
2854@@ -715,14 +706,14 @@ class UnicodeErrorTestCase(EntryTestCase):
2855
2856 # This will raise an exception, which will cause the request
2857 # to fail with a 400 error code.
2858- error = resource.applyChanges({"a_field": u"No such value"})
2859+ error = resource.applyChanges({"a_field": "No such value"})
2860 self.assertEqual(resource.request.response.getStatus(), 400)
2861
2862 # The error message is a Unicode string which mentions both
2863 # the ASCII value and the Unicode value,
2864 expected_error = (
2865- u'a_field: Invalid value "No such value". Acceptable values '
2866- u"are: Ascii, Uni\u00e7ode"
2867+ 'a_field: Invalid value "No such value". Acceptable values '
2868+ "are: Ascii, Uni\u00e7ode"
2869 )
2870 self.assertEqual(error, expected_error)
2871
2872@@ -887,7 +878,7 @@ class DuplicateNameTestCase(WebServiceTestCase):
2873 def make_entry(name):
2874 """Make an entity with some attibutes to expose as a web service."""
2875 fields = {
2876- "%s_field" % letter: exported(TextLine(title=u"Field %s" % letter))
2877+ "%s_field" % letter: exported(TextLine(title="Field %s" % letter))
2878 for letter in "rstuvwxyz"
2879 }
2880 cls = InterfaceClass(name, bases=(Interface,), attrs=fields)
2881@@ -901,7 +892,7 @@ class TestWadlDeterminism(WebServiceTestCase):
2882 # make some -- randomly ordered -- objects to use to build the WADL
2883 self.testmodule_objects = [make_entry(name) for name in "abcdefghijk"]
2884 random.shuffle(self.testmodule_objects)
2885- super(TestWadlDeterminism, self).__init__(*args, **kwargs)
2886+ super().__init__(*args, **kwargs)
2887
2888 @property
2889 def wadl(self):
2890@@ -1026,7 +1017,7 @@ class BaseBatchingTest:
2891 testmodule_objects = [HasRestrictedField, IHasRestrictedField]
2892
2893 def setUp(self):
2894- super(BaseBatchingTest, self).setUp()
2895+ super().setUp()
2896 # Register TestEntry as the IEntry implementation for ITestEntry.
2897 getGlobalSiteManager().registerAdapter(
2898 TestEntry, [ITestEntry, IWebServiceClientRequest], provided=IEntry
2899@@ -1100,7 +1091,7 @@ class NotificationsProviderTest(EntryTestCase):
2900 ]
2901
2902 def setUp(self):
2903- super(NotificationsProviderTest, self).setUp()
2904+ super().setUp()
2905 self.default_media_type = "application/json;include=lp_html"
2906 self._register_website_url_space(IHasOneField)
2907 self._register_notification_adapter()
2908@@ -1146,7 +1137,7 @@ class EventTestCase(EntryTestCase):
2909 testmodule_objects = [IHasOneField]
2910
2911 def setUp(self):
2912- super(EventTestCase, self).setUp()
2913+ super().setUp()
2914 self._register_url_adapter(IHasOneField)
2915 eventtesting.setUp()
2916
2917@@ -1154,7 +1145,7 @@ class EventTestCase(EntryTestCase):
2918 # Passing in a non-empty changeset spawns an
2919 # IObjectModifiedEvent.
2920 with self.entry_resource(HasOneField, "") as resource:
2921- resource.applyChanges({"a_field": u"Some value"})
2922+ resource.applyChanges({"a_field": "Some value"})
2923 events = eventtesting.getEvents()
2924 self.assertEqual(len(events), 1)
2925 event = events[0]
2926@@ -1175,9 +1166,9 @@ class MalformedRequest(EntryTestCase):
2927 default_media_type = "application/xhtml+xml"
2928
2929 def setUp(self):
2930- super(MalformedRequest, self).setUp()
2931+ super().setUp()
2932 self._register_url_adapter(IHasOneField)
2933- self.unicode_message = u"Hello from a \N{SNOWMAN}"
2934+ self.unicode_message = "Hello from a \N{SNOWMAN}"
2935
2936 def test_multiple_named_operations_generate_error_on_GET(self):
2937 with self.entry_resource(
2938diff --git a/src/lazr/restful/utils.py b/src/lazr/restful/utils.py
2939index 043ed87..2175977 100644
2940--- a/src/lazr/restful/utils.py
2941+++ b/src/lazr/restful/utils.py
2942@@ -2,9 +2,6 @@
2943
2944 """Various utility functions."""
2945
2946-from __future__ import absolute_import, print_function
2947-
2948-__metaclass__ = type
2949 __all__ = [
2950 "camelcase_to_underscore_separated",
2951 "get_current_browser_request",
2952@@ -20,7 +17,7 @@ __all__ = [
2953 "VersionedObject",
2954 ]
2955
2956-
2957+import builtins
2958 import collections
2959 import copy
2960 import operator
2961@@ -28,8 +25,6 @@ import re
2962 import string
2963 import subprocess
2964
2965-import six
2966-
2967 from zope.component import getUtility
2968 from zope.schema import getFieldsInOrder
2969 from zope.interface import alsoProvides, classImplements
2970@@ -134,7 +129,7 @@ VersionedObject = collections.namedtuple(
2971 )
2972
2973
2974-class VersionedDict(object):
2975+class VersionedDict:
2976 """A stack of named dictionaries.
2977
2978 Most access to the stack actually operates on the dictionary on
2979@@ -368,9 +363,11 @@ def safe_hasattr(ob, name):
2980
2981 def smartquote(str):
2982 """Return a copy of the string, with typographical quote marks applied."""
2983- str = six.text_type(str)
2984- str = re.compile(u'(^| )(")([^" ])').sub(u"\\1\u201c\\3", str)
2985- str = re.compile(u'([^ "])(")($|[\\s.,;:!?])').sub(u"\\1\u201d\\3", str)
2986+ # Using builtins.str here is weird, but it lets us cope with the
2987+ # unfortunate naming of our positional argument without breaking API.
2988+ str = builtins.str(str)
2989+ str = re.compile('(^| )(")([^" ])').sub("\\1\u201c\\3", str)
2990+ str = re.compile('([^ "])(")($|[\\s.,;:!?])').sub("\\1\u201d\\3", str)
2991 return str
2992
2993
2994diff --git a/src/lazr/restful/wsgi.py b/src/lazr/restful/wsgi.py
2995index 2b03ab3..fc298e0 100644
2996--- a/src/lazr/restful/wsgi.py
2997+++ b/src/lazr/restful/wsgi.py
2998@@ -1,8 +1,5 @@
2999 """A WSGI application for a lazr.restful web service."""
3000
3001-from __future__ import absolute_import, print_function
3002-
3003-__metaclass__ = type
3004 __all__ = [
3005 "BaseWSGIWebServiceConfiguration",
3006 "WSGIApplication",

Subscribers

People subscribed via source and target branches