From 36667f6536dd69b69bfe6fe3c2685573cf877831 Mon Sep 17 00:00:00 2001
From: Jean-Paul Calderone <exarkun@twistedmatrix.com>
Date: Wed, 5 Jan 2022 12:42:34 -0500
Subject: [PATCH] drop __future__ and future imports

They're all redundant on Python 3
---
 src/_zkapauthorizer/_base64.py                |  2 -
 src/_zkapauthorizer/_plugin.py                |  8 +-
 src/_zkapauthorizer/_storage_client.py        | 77 ++++++-------------
 src/_zkapauthorizer/_storage_server.py        | 34 +-------
 src/_zkapauthorizer/configutil.py             |  3 -
 src/_zkapauthorizer/controller.py             | 34 +-------
 src/_zkapauthorizer/eliot.py                  | 29 -------
 src/_zkapauthorizer/foolscap.py               |  8 +-
 src/_zkapauthorizer/lease_maintenance.py      | 29 -------
 src/_zkapauthorizer/model.py                  | 46 +----------
 src/_zkapauthorizer/private.py                |  2 -
 src/_zkapauthorizer/resource.py               | 33 +-------
 src/_zkapauthorizer/schema.py                 |  3 -
 src/_zkapauthorizer/server/spending.py        |  7 +-
 src/_zkapauthorizer/spending.py               | 41 ++--------
 src/_zkapauthorizer/storage_common.py         | 36 +--------
 src/_zkapauthorizer/tests/eliot.py            |  2 -
 src/_zkapauthorizer/tests/fixtures.py         | 29 -------
 src/_zkapauthorizer/tests/foolscap.py         |  4 +-
 src/_zkapauthorizer/tests/json.py             |  2 -
 src/_zkapauthorizer/tests/privacypass.py      |  2 -
 src/_zkapauthorizer/tests/storage_common.py   |  3 +-
 src/_zkapauthorizer/tests/strategies.py       | 37 +--------
 src/_zkapauthorizer/tests/test_base64.py      |  2 -
 .../tests/test_client_resource.py             | 43 ++---------
 src/_zkapauthorizer/tests/test_controller.py  |  6 +-
 src/_zkapauthorizer/tests/test_foolscap.py    | 41 ++--------
 .../tests/test_lease_maintenance.py           | 29 -------
 src/_zkapauthorizer/tests/test_matchers.py    |  2 -
 src/_zkapauthorizer/tests/test_model.py       | 29 -------
 src/_zkapauthorizer/tests/test_plugin.py      | 42 +---------
 .../tests/test_pricecalculator.py             | 29 -------
 src/_zkapauthorizer/tests/test_private.py     | 28 -------
 src/_zkapauthorizer/tests/test_schema.py      |  2 -
 src/_zkapauthorizer/tests/test_spending.py    | 29 -------
 .../tests/test_storage_client.py              | 29 -------
 .../tests/test_storage_protocol.py            |  2 -
 .../tests/test_storage_server.py              |  4 +-
 src/_zkapauthorizer/tests/test_strategies.py  | 29 -------
 39 files changed, 64 insertions(+), 753 deletions(-)

diff --git a/src/_zkapauthorizer/_base64.py b/src/_zkapauthorizer/_base64.py
index 473cb41..604797e 100644
--- a/src/_zkapauthorizer/_base64.py
+++ b/src/_zkapauthorizer/_base64.py
@@ -16,8 +16,6 @@
 This module implements base64 encoding-related functionality.
 """
 
-from __future__ import absolute_import
-
 from base64 import b64decode as _b64decode
 from binascii import Error
 from re import compile as _compile
diff --git a/src/_zkapauthorizer/_plugin.py b/src/_zkapauthorizer/_plugin.py
index 5deab0d..68a5d19 100644
--- a/src/_zkapauthorizer/_plugin.py
+++ b/src/_zkapauthorizer/_plugin.py
@@ -17,17 +17,11 @@ The Twisted plugin that glues the Zero-Knowledge Access Pass system into
 Tahoe-LAFS.
 """
 
-from __future__ import absolute_import
-
 import random
 from datetime import datetime
 from functools import partial
 from weakref import WeakValueDictionary
-
-try:
-    from typing import Callable
-except ImportError:
-    pass
+from typing import Callable
 
 import attr
 from allmydata.client import _Client
diff --git a/src/_zkapauthorizer/_storage_client.py b/src/_zkapauthorizer/_storage_client.py
index ecb785f..1f9d19a 100644
--- a/src/_zkapauthorizer/_storage_client.py
+++ b/src/_zkapauthorizer/_storage_client.py
@@ -20,43 +20,15 @@ This is the client part of a storage access protocol.  The server part is
 implemented in ``_storage_server.py``.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if  PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from functools import partial, wraps
+from typing import Any, Tuple, Dict, List, Optional
 
 import attr
 from allmydata.interfaces import IStorageServer
 from allmydata.util.eliotutil import log_call_deferred
 from attr.validators import provides
 from eliot.twisted import inline_callbacks
-from twisted.internet.defer import returnValue
+from twisted.internet.defer import returnValue, Deferred
 from twisted.internet.interfaces import IReactorTime
 from twisted.python.reflect import namedAny
 from zope.interface import implementer
@@ -73,6 +45,20 @@ from .storage_common import (
     slot_testv_and_readv_and_writev_message,
 )
 
+Secrets = Tuple[bytes, bytes, bytes]
+TestWriteVectors = Dict[
+    int,
+    Tuple[
+        List[
+            Tuple[int, int, bytes, bytes],
+        ],
+        List[
+            Tuple[int, bytes],
+        ],
+        Optional[int],
+    ],
+]
+ReadVector = List[Tuple[int, int]]
 
 class IncorrectStorageServerReference(Exception):
     """
@@ -444,31 +430,12 @@ class ZKAPAuthorizerStorageClient(object):
     @with_rref
     def slot_testv_and_readv_and_writev(
         self,
-        rref,
-        storage_index,
-        secrets,
-        tw_vectors,
-        r_vector,
-    ):
-        # type: (
-        #   Any,
-        #   bytes,
-        #   Tuple[bytes, bytes, bytes],
-        #   Dict[
-        #     int,
-        #     Tuple[
-        #       List[
-        #         Tuple[int, int, bytes, bytes],
-        #       ],
-        #       List[
-        #         Tuple[int, bytes],
-        #       ],
-        #       Optional[int],
-        #     ],
-        #   ],
-        #   List[Tuple[int, int]],
-        # ) -> Deferred
-
+        rref: Any,
+        storage_index: bytes,
+        secrets: Secrets,
+        tw_vectors: TestWriteVectors,
+        r_vector: ReadVector,
+    ) -> Deferred:
         # Read operations are free.
         num_passes = 0
 
diff --git a/src/_zkapauthorizer/_storage_server.py b/src/_zkapauthorizer/_storage_server.py
index 6e0ea94..2aedd90 100644
--- a/src/_zkapauthorizer/_storage_server.py
+++ b/src/_zkapauthorizer/_storage_server.py
@@ -21,41 +21,13 @@ This is the server part of a storage access protocol.  The client part is
 implemented in ``_storage_client.py``.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from datetime import timedelta
 from errno import ENOENT
 from functools import partial
 from os import listdir, stat
 from os.path import join
 from struct import calcsize, unpack
+from typing import Dict, List, Optional
 
 import attr
 from allmydata.interfaces import RIStorageServer, TestAndWriteVectorsForShares
@@ -96,10 +68,6 @@ from .storage_common import (
     slot_testv_and_readv_and_writev_message,
 )
 
-try:
-    from typing import Dict, List, Optional
-except ImportError:
-    pass
 
 # The last Python 2-supporting prometheus_client nevertheless tries to use
 # FileNotFoundError, an exception type from Python 3.  Since that release,
diff --git a/src/_zkapauthorizer/configutil.py b/src/_zkapauthorizer/configutil.py
index 2df26fc..8270936 100644
--- a/src/_zkapauthorizer/configutil.py
+++ b/src/_zkapauthorizer/configutil.py
@@ -16,9 +16,6 @@
 Basic utilities related to the Tahoe configuration file.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-
 def _merge_dictionaries(dictionaries):
     """
     Collapse a sequence of dictionaries into one, with collisions resolved by
diff --git a/src/_zkapauthorizer/controller.py b/src/_zkapauthorizer/controller.py
index 4be61aa..a1147a7 100644
--- a/src/_zkapauthorizer/controller.py
+++ b/src/_zkapauthorizer/controller.py
@@ -17,42 +17,13 @@ This module implements controllers (in the MVC sense) for the web interface
 for the client side of the storage plugin.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
+from typing import List
 from base64 import b64decode, b64encode
 from datetime import timedelta
 from functools import partial
 from hashlib import sha256
 from json import loads
 from operator import delitem, setitem
-from sys import exc_info
 
 from six import ensure_text
 import attr
@@ -1056,10 +1027,7 @@ def bracket(first, last, between):
     except GeneratorExit:
         raise
     except:
-        info = exc_info()
         yield last()
-        if PY2:
-            exec("raise info[0], info[1], info[2]")
         raise
     else:
         yield last()
diff --git a/src/_zkapauthorizer/eliot.py b/src/_zkapauthorizer/eliot.py
index 8267605..e9f4d49 100644
--- a/src/_zkapauthorizer/eliot.py
+++ b/src/_zkapauthorizer/eliot.py
@@ -16,35 +16,6 @@
 Eliot field, message, and action definitions for ZKAPAuthorizer.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from eliot import ActionType, Field, MessageType
 
 PRIVACYPASS_MESSAGE = Field(
diff --git a/src/_zkapauthorizer/foolscap.py b/src/_zkapauthorizer/foolscap.py
index c2d814e..efd2e74 100644
--- a/src/_zkapauthorizer/foolscap.py
+++ b/src/_zkapauthorizer/foolscap.py
@@ -17,15 +17,11 @@ Definitions related to the Foolscap-based protocol used by ZKAPAuthorizer
 to communicate between storage clients and servers.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
 import attr
 from allmydata.interfaces import Offset, RIStorageServer, StorageIndex
 from foolscap.api import Any, Copyable, DictOf, ListOf, RemoteCopy
 from foolscap.constraint import ByteStringConstraint
 from foolscap.remoteinterface import RemoteInterface, RemoteMethodSchema
-from six import ensure_str
 
 @attr.s
 class ShareStat(Copyable, RemoteCopy):
@@ -38,7 +34,7 @@ class ShareStat(Copyable, RemoteCopy):
         lease on this share expires, or None if there is no lease.
     """
 
-    typeToCopy = copytype = ensure_str("ShareStat")
+    typeToCopy = copytype = "ShareStat"
 
     # To be a RemoteCopy it must be possible to instantiate this with no
     # arguments. :/ So supply defaults for these attributes.
@@ -137,7 +133,7 @@ class RIPrivacyPassAuthorizedStorageServer(RemoteInterface):
     validated is service provided.
     """
 
-    __remote_name__ = ensure_str(
+    __remote_name__ = (
         "RIPrivacyPassAuthorizedStorageServer.tahoe.privatestorage.io"
     )
 
diff --git a/src/_zkapauthorizer/lease_maintenance.py b/src/_zkapauthorizer/lease_maintenance.py
index 4916768..48f6ecf 100644
--- a/src/_zkapauthorizer/lease_maintenance.py
+++ b/src/_zkapauthorizer/lease_maintenance.py
@@ -17,35 +17,6 @@ This module implements a service which periodically spends ZKAPs to
 refresh leases on all shares reachable from a root.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if  PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from datetime import datetime, timedelta
 from errno import ENOENT
 from functools import partial
diff --git a/src/_zkapauthorizer/model.py b/src/_zkapauthorizer/model.py
index 0aec9d3..a568ba2 100644
--- a/src/_zkapauthorizer/model.py
+++ b/src/_zkapauthorizer/model.py
@@ -17,35 +17,6 @@ This module implements models (in the MVC sense) for the client side of
 the storage plugin.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from datetime import datetime
 from functools import wraps
 from json import loads
@@ -53,7 +24,7 @@ from sqlite3 import OperationalError
 from sqlite3 import connect as _connect
 
 import attr
-from aniso8601 import parse_datetime as _parse_datetime
+from aniso8601 import parse_datetime
 from past.builtins import long
 from twisted.logger import Logger
 from twisted.python.filepath import FilePath
@@ -71,21 +42,6 @@ from .storage_common import (
 from .validators import greater_than, has_length, is_base64_encoded
 
 
-if PY2:
-    def parse_datetime(s, **kw):
-        """
-        Like ``aniso8601.parse_datetime`` but accept str as well.
-        """
-        if isinstance(s, str):
-            s = s.encode("utf-8")
-        assert isinstance(s, bytes)
-        if "delimiter" in kw and isinstance(kw["delimiter"], str):
-            kw["delimiter"] = kw["delimiter"].encode("utf-8")
-        return _parse_datetime(s, **kw)
-else:
-    parse_datetime = _parse_datetime
-
-
 class ILeaseMaintenanceObserver(Interface):
     """
     An object which is interested in receiving events related to the progress
diff --git a/src/_zkapauthorizer/private.py b/src/_zkapauthorizer/private.py
index 535c002..7e2adb0 100644
--- a/src/_zkapauthorizer/private.py
+++ b/src/_zkapauthorizer/private.py
@@ -10,8 +10,6 @@ Support code for applying token-based HTTP authorization rules to a
 Twisted Web resource hierarchy.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
 # https://github.com/twisted/nevow/issues/106 may affect this code but if so
 # then the hotfix Tahoe-LAFS applies should deal with it.
 #
diff --git a/src/_zkapauthorizer/resource.py b/src/_zkapauthorizer/resource.py
index b2b9752..68ef2b7 100644
--- a/src/_zkapauthorizer/resource.py
+++ b/src/_zkapauthorizer/resource.py
@@ -21,40 +21,11 @@ vouchers for fresh tokens.
 In the future it should also allow users to read statistics about token usage.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from itertools import islice
 from json import load, loads
 from sys import maxsize
 
-from six import ensure_str, ensure_binary
+from six import ensure_binary
 from past.builtins import long
 from twisted.logger import Logger
 from twisted.web.http import BAD_REQUEST
@@ -172,7 +143,7 @@ def from_configuration(
     )
 
     root = create_private_tree(
-        lambda: ensure_binary(node_config.get_private_config(ensure_str("api_auth_token"))),
+        lambda: ensure_binary(node_config.get_private_config("api_auth_token")),
         authorizationless_resource_tree(
             store,
             controller,
diff --git a/src/_zkapauthorizer/schema.py b/src/_zkapauthorizer/schema.py
index 9fe72b6..c25dfa9 100644
--- a/src/_zkapauthorizer/schema.py
+++ b/src/_zkapauthorizer/schema.py
@@ -11,9 +11,6 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-
-from __future__ import unicode_literals
-
 """
 This module defines the database schema used by the model interface.
 """
diff --git a/src/_zkapauthorizer/server/spending.py b/src/_zkapauthorizer/server/spending.py
index f93f156..66fe819 100644
--- a/src/_zkapauthorizer/server/spending.py
+++ b/src/_zkapauthorizer/server/spending.py
@@ -1,9 +1,4 @@
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-try:
-    from typing import Any
-except ImportError:
-    pass
+from typing import Any
 
 import attr
 from challenge_bypass_ristretto import PublicKey
diff --git a/src/_zkapauthorizer/spending.py b/src/_zkapauthorizer/spending.py
index 49983f4..0543fac 100644
--- a/src/_zkapauthorizer/spending.py
+++ b/src/_zkapauthorizer/spending.py
@@ -16,40 +16,13 @@
 A module for logic controlling the manner in which ZKAPs are spent.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if  PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
+from typing import List, Tuple
 
 import attr
 from zope.interface import Attribute, Interface, implementer
 
 from .eliot import GET_PASSES, INVALID_PASSES, RESET_PASSES, SPENT_PASSES
-
+from .model import UnblindedToken, Pass
 
 class IPassGroup(Interface):
     """
@@ -140,7 +113,7 @@ class PassGroup(object):
 
     _message = attr.ib(validator=attr.validators.instance_of(bytes))  # type: bytes
     _factory = attr.ib(validator=attr.validators.provides(IPassFactory))  # type: IPassFactory
-    _tokens = attr.ib(validator=attr.validators.instance_of(list))  # type: List[(UnblinidedToken, Pass)]
+    _tokens = attr.ib(validator=attr.validators.instance_of(list))  # type: List[Tuple[UnblindedToken, Pass]]
 
     @property
     def passes(self):
@@ -195,11 +168,11 @@ class SpendingController(object):
     """
 
     get_unblinded_tokens = attr.ib()  # type: (int) -> [UnblindedToken]
-    discard_unblinded_tokens = attr.ib()  # type: ([UnblindedTokens]) -> None
-    invalidate_unblinded_tokens = attr.ib()  # type: ([UnblindedTokens]) -> None
-    reset_unblinded_tokens = attr.ib()  # type: ([UnblindedTokens]) -> None
+    discard_unblinded_tokens = attr.ib()  # type: ([UnblindedToken]) -> None
+    invalidate_unblinded_tokens = attr.ib()  # type: ([UnblindedToken]) -> None
+    reset_unblinded_tokens = attr.ib()  # type: ([UnblindedToken]) -> None
 
-    tokens_to_passes = attr.ib() # type: (bytes, [UnblindedTokens]) -> [Pass]
+    tokens_to_passes = attr.ib() # type: (bytes, [UnblindedToken]) -> [Pass]
 
     @classmethod
     def for_store(cls, tokens_to_passes, store):
diff --git a/src/_zkapauthorizer/storage_common.py b/src/_zkapauthorizer/storage_common.py
index b9c4b2c..5313b31 100644
--- a/src/_zkapauthorizer/storage_common.py
+++ b/src/_zkapauthorizer/storage_common.py
@@ -16,39 +16,9 @@
 Functionality shared between the storage client and server.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from base64 import b64encode
 
 import attr
-from past.builtins import long
 from pyutil.mathutil import div_ceil
 
 from .eliot import MUTABLE_PASSES_REQUIRED
@@ -71,8 +41,8 @@ class MorePassesRequired(Exception):
         passes indicating passes which failed the signature check.
     """
 
-    valid_count = attr.ib(validator=attr.validators.instance_of((int, long)))
-    required_count = attr.ib(validator=attr.validators.instance_of((int, long)))
+    valid_count = attr.ib(validator=attr.validators.instance_of(int))
+    required_count = attr.ib(validator=attr.validators.instance_of(int))
     signature_check_failed = attr.ib(converter=frozenset)
 
 
@@ -332,7 +302,7 @@ def pass_value_attribute():
     """
     return attr.ib(
         validator=attr.validators.and_(
-            attr.validators.instance_of((int, long)),
+            attr.validators.instance_of(int),
             greater_than(0),
         ),
     )
diff --git a/src/_zkapauthorizer/tests/eliot.py b/src/_zkapauthorizer/tests/eliot.py
index ba010cf..094b64d 100644
--- a/src/_zkapauthorizer/tests/eliot.py
+++ b/src/_zkapauthorizer/tests/eliot.py
@@ -16,8 +16,6 @@
 Eliot testing helpers.
 """
 
-from __future__ import absolute_import
-
 from functools import wraps
 from unittest import SkipTest
 
diff --git a/src/_zkapauthorizer/tests/fixtures.py b/src/_zkapauthorizer/tests/fixtures.py
index 2bc62c8..9ed90e1 100644
--- a/src/_zkapauthorizer/tests/fixtures.py
+++ b/src/_zkapauthorizer/tests/fixtures.py
@@ -16,35 +16,6 @@
 Common fixtures to let the test suite focus on application logic.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from base64 import b64encode
 
 import attr
diff --git a/src/_zkapauthorizer/tests/foolscap.py b/src/_zkapauthorizer/tests/foolscap.py
index e2d1c43..8ad3345 100644
--- a/src/_zkapauthorizer/tests/foolscap.py
+++ b/src/_zkapauthorizer/tests/foolscap.py
@@ -16,8 +16,6 @@
 Testing helpers related to Foolscap.
 """
 
-from __future__ import absolute_import
-
 import attr
 from allmydata.interfaces import RIStorageServer
 from foolscap.api import Any, Copyable, Referenceable, RemoteInterface
@@ -80,7 +78,7 @@ class LocalTracker(object):
         self.interfaceName = self.interface.__remote_name__
 
     def getURL(self):
-        return b"pb://abcd@127.0.0.1:12345/efgh"
+        return "pb://abcd@127.0.0.1:12345/efgh"
 
 
 @attr.s
diff --git a/src/_zkapauthorizer/tests/json.py b/src/_zkapauthorizer/tests/json.py
index b8aa7c7..7296412 100644
--- a/src/_zkapauthorizer/tests/json.py
+++ b/src/_zkapauthorizer/tests/json.py
@@ -16,8 +16,6 @@
 A better JSON module.
 """
 
-from __future__ import absolute_import
-
 from json import loads as _loads
 
 
diff --git a/src/_zkapauthorizer/tests/privacypass.py b/src/_zkapauthorizer/tests/privacypass.py
index 0f42877..fb4fcc7 100644
--- a/src/_zkapauthorizer/tests/privacypass.py
+++ b/src/_zkapauthorizer/tests/privacypass.py
@@ -16,8 +16,6 @@
 Ristretto-flavored PrivacyPass helpers for the test suite.
 """
 
-from __future__ import absolute_import
-
 from challenge_bypass_ristretto import BatchDLEQProof, PublicKey
 
 from ..model import Pass
diff --git a/src/_zkapauthorizer/tests/storage_common.py b/src/_zkapauthorizer/tests/storage_common.py
index 61c061c..35d52fa 100644
--- a/src/_zkapauthorizer/tests/storage_common.py
+++ b/src/_zkapauthorizer/tests/storage_common.py
@@ -20,6 +20,7 @@ from functools import partial
 from itertools import islice
 from os import SEEK_CUR
 from struct import pack
+from typing import List, Set, Dict
 
 import attr
 from challenge_bypass_ristretto import RandomToken
@@ -222,7 +223,7 @@ class _PassFactory(object):
 
     returned = attr.ib(default=attr.Factory(list), init=False)  # type: List[int]
     in_use = attr.ib(default=attr.Factory(set), init=False)  # type: Set[int]
-    invalid = attr.ib(default=attr.Factory(dict), init=False)  # type: Dict[int, unicode]
+    invalid = attr.ib(default=attr.Factory(dict), init=False)  # type: Dict[int, str]
     spent = attr.ib(default=attr.Factory(set), init=False)  # type: Set[int]
     issued = attr.ib(default=attr.Factory(set), init=False)  # type: Set[int]
 
diff --git a/src/_zkapauthorizer/tests/strategies.py b/src/_zkapauthorizer/tests/strategies.py
index 54306ea..977362a 100644
--- a/src/_zkapauthorizer/tests/strategies.py
+++ b/src/_zkapauthorizer/tests/strategies.py
@@ -16,35 +16,6 @@
 Hypothesis strategies for property testing.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from base64 import b64encode, urlsafe_b64encode
 from datetime import datetime, timedelta
 
@@ -69,8 +40,7 @@ from hypothesis.strategies import (
     text,
     tuples,
 )
-from six.moves.urllib.parse import quote
-from six import ensure_binary
+from urllib.parse import quote
 from twisted.internet.defer import succeed
 from twisted.internet.task import Clock
 from twisted.web.test.requesthelper import DummyRequest
@@ -759,10 +729,7 @@ def request_paths():
     :see: ``requests``
     """
     def quote_segment(seg):
-        if PY2:
-            return quote(seg.encode("utf-8"), safe=b"")
-        else:
-            return quote(seg, safe="").encode("utf-8")
+        return quote(seg, safe="").encode("utf-8")
 
     return lists(text().map(quote_segment))
 
diff --git a/src/_zkapauthorizer/tests/test_base64.py b/src/_zkapauthorizer/tests/test_base64.py
index d91bbac..df3111d 100644
--- a/src/_zkapauthorizer/tests/test_base64.py
+++ b/src/_zkapauthorizer/tests/test_base64.py
@@ -16,8 +16,6 @@
 Tests for ``_zkapauthorizer._base64``.
 """
 
-from __future__ import absolute_import
-
 from base64 import urlsafe_b64encode
 
 from hypothesis import given
diff --git a/src/_zkapauthorizer/tests/test_client_resource.py b/src/_zkapauthorizer/tests/test_client_resource.py
index 63acf4c..f206bdd 100644
--- a/src/_zkapauthorizer/tests/test_client_resource.py
+++ b/src/_zkapauthorizer/tests/test_client_resource.py
@@ -17,39 +17,11 @@ Tests for the web resource provided by the client part of the Tahoe-LAFS
 plugin.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from datetime import datetime
 from io import BytesIO
-from six.moves.urllib.parse import quote
-from six import ensure_binary, ensure_text
+from urllib.parse import quote
+from six import ensure_text
+from typing import Set, TypeVar, Optional
 
 import attr
 from allmydata.client import config_from_string
@@ -138,6 +110,8 @@ from .strategies import (
     vouchers,
 )
 
+Strategy = TypeVar()
+
 TRANSIENT_ERROR = "something went wrong, who knows what"
 
 # Helper to work-around https://github.com/twisted/treq/issues/161
@@ -1427,15 +1401,12 @@ class VoucherTests(TestCase):
             ),
         )
 
-
-def mime_types(blacklist=None):
+def mime_types(blacklist: Optional[Set[str]] = None) -> Strategy[str]:
     """
     Build MIME types as b"major/minor" byte strings.
 
-    :param blacklist: If not ``None``, MIME types to
-        exclude from the result.
+    :param blacklist: If not ``None``, MIME types to exclude from the result.
     """
-    # type: Optional[Set[unicode]] -> Strategy[unicode]
     if blacklist is None:
         blacklist = set()
     return (
diff --git a/src/_zkapauthorizer/tests/test_controller.py b/src/_zkapauthorizer/tests/test_controller.py
index 1ffac55..b7efbe8 100644
--- a/src/_zkapauthorizer/tests/test_controller.py
+++ b/src/_zkapauthorizer/tests/test_controller.py
@@ -16,8 +16,6 @@
 Tests for ``_zkapauthorizer.controller``.
 """
 
-from __future__ import absolute_import, division
-
 from datetime import datetime, timedelta
 from functools import partial
 from json import loads
@@ -1300,10 +1298,10 @@ class _BracketTestMixin:
     Tests for ``bracket``.
     """
     def wrap_success(self, result):
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def wrap_failure(self, result):
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def test_success(self):
         """
diff --git a/src/_zkapauthorizer/tests/test_foolscap.py b/src/_zkapauthorizer/tests/test_foolscap.py
index 1dee261..f22985f 100644
--- a/src/_zkapauthorizer/tests/test_foolscap.py
+++ b/src/_zkapauthorizer/tests/test_foolscap.py
@@ -16,36 +16,6 @@
 Tests for Foolscap-related test helpers.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-# if PY2:
-#     from future.builtins import (  # noqa: F401
-#         filter,
-#         map,
-#         zip,
-#         ascii,
-#         chr,
-#         hex,
-#         input,
-#         next,
-#         oct,
-#         open,
-#         pow,
-#         round,
-#         super,
-#         bytes,
-#         dict,
-#         list,
-#         object,
-#         range,
-#         str,
-#         max,
-#         min,
-#     )
-
-from six import ensure_str
 from fixtures import Fixture
 from foolscap.api import Any, RemoteInterface, Violation
 from foolscap.furl import decode_furl
@@ -83,7 +53,7 @@ class IHasSchema(RemoteInterface):
 def remote_reference():
     tub = Tub()
     tub.setLocation("127.0.0.1:12345")
-    url = tub.buildURL(ensure_str("efgh"))
+    url = tub.buildURL("efgh")
 
     # Ugh ugh ugh.  Skip over the extra correctness checking in
     # RemoteReferenceTracker.__init__ that requires having a broker by passing
@@ -113,9 +83,12 @@ class LocalRemoteTests(TestCase):
         """
         self.assertThat(
             ref.tracker.getURL(),
-            AfterPreprocessing(
-                decode_furl,
-                Always(),
+            MatchesAll(
+                IsInstance(str),
+                AfterPreprocessing(
+                    decode_furl,
+                    Always(),
+                ),
             ),
         )
 
diff --git a/src/_zkapauthorizer/tests/test_lease_maintenance.py b/src/_zkapauthorizer/tests/test_lease_maintenance.py
index 15d9ca9..2f20fcd 100644
--- a/src/_zkapauthorizer/tests/test_lease_maintenance.py
+++ b/src/_zkapauthorizer/tests/test_lease_maintenance.py
@@ -16,35 +16,6 @@
 Tests for ``_zkapauthorizer.lease_maintenance``.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if  PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from datetime import datetime, timedelta
 
 import attr
diff --git a/src/_zkapauthorizer/tests/test_matchers.py b/src/_zkapauthorizer/tests/test_matchers.py
index e34bb8a..d97ac1a 100644
--- a/src/_zkapauthorizer/tests/test_matchers.py
+++ b/src/_zkapauthorizer/tests/test_matchers.py
@@ -16,8 +16,6 @@
 Tests for ``_zkapauthorizer.tests.matchers``.
 """
 
-from __future__ import absolute_import
-
 from testtools import TestCase
 from testtools.matchers import Is, Not
 from zope.interface import Interface, implementer
diff --git a/src/_zkapauthorizer/tests/test_model.py b/src/_zkapauthorizer/tests/test_model.py
index 0102ee7..914bb9a 100644
--- a/src/_zkapauthorizer/tests/test_model.py
+++ b/src/_zkapauthorizer/tests/test_model.py
@@ -17,35 +17,6 @@
 Tests for ``_zkapauthorizer.model``.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-# if PY2:
-#     from future.builtins import (  # noqa: F401
-#         filter,
-#         map,
-#         zip,
-#         ascii,
-#         chr,
-#         hex,
-#         input,
-#         next,
-#         oct,
-#         open,
-#         pow,
-#         round,
-#         super,
-#         bytes,
-#         dict,
-#         list,
-#         object,
-#         range,
-#         str,
-#         max,
-#         min,
-#     )
-
 from datetime import datetime, timedelta
 from errno import EACCES
 from os import mkdir
diff --git a/src/_zkapauthorizer/tests/test_plugin.py b/src/_zkapauthorizer/tests/test_plugin.py
index 0baa112..80d9813 100644
--- a/src/_zkapauthorizer/tests/test_plugin.py
+++ b/src/_zkapauthorizer/tests/test_plugin.py
@@ -16,35 +16,6 @@
 Tests for the Tahoe-LAFS plugin.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from datetime import timedelta
 from functools import partial
 from os import makedirs
@@ -67,8 +38,7 @@ from hypothesis import given, settings
 from hypothesis.strategies import datetimes, just, sampled_from, timedeltas
 from prometheus_client import Gauge
 from prometheus_client.parser import text_string_to_metric_families
-from six.moves import StringIO
-from six import ensure_binary
+from io import StringIO
 from testtools import TestCase
 from testtools.content import text_content
 from testtools.matchers import (
@@ -418,16 +388,6 @@ class ClientPluginTests(TestCase):
             u"tub.port",
             config_text.encode("utf-8"),
         )
-        # On Tahoe-LAFS <1.16, the config is written as bytes.
-        # On Tahoe-LAFS >=1.16, the config is written as unicode.
-        #
-        # So we'll use `StringIO.StringIO` (not `io.StringIO`) here - which
-        # will allow either type (it will also implicitly decode bytes to
-        # unicode if we mix them, though I don't think that should happen
-        # here).
-        #
-        # After support for Tahoe <1.16 support is dropped we probably want to
-        # switch to an io.StringIO here.
         config_text = StringIO()
         node_config.config.write(config_text)
         self.addDetail("config", text_content(config_text.getvalue()))
diff --git a/src/_zkapauthorizer/tests/test_pricecalculator.py b/src/_zkapauthorizer/tests/test_pricecalculator.py
index b69135b..2d447e3 100644
--- a/src/_zkapauthorizer/tests/test_pricecalculator.py
+++ b/src/_zkapauthorizer/tests/test_pricecalculator.py
@@ -17,35 +17,6 @@
 Tests for ``_zkapauthorizer.pricecalculator``.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from functools import partial
 
 from hypothesis import given
diff --git a/src/_zkapauthorizer/tests/test_private.py b/src/_zkapauthorizer/tests/test_private.py
index effc6dc..ba1fa34 100644
--- a/src/_zkapauthorizer/tests/test_private.py
+++ b/src/_zkapauthorizer/tests/test_private.py
@@ -9,34 +9,6 @@
 Tests for ``_zkapauthorizer.private``.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-from future.utils import PY2
-if  PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
-
 from allmydata.test.web.matchers import has_response_code
 from testtools import TestCase
 from testtools.matchers import Equals
diff --git a/src/_zkapauthorizer/tests/test_schema.py b/src/_zkapauthorizer/tests/test_schema.py
index 1c53556..f0dc6f8 100644
--- a/src/_zkapauthorizer/tests/test_schema.py
+++ b/src/_zkapauthorizer/tests/test_schema.py
@@ -17,8 +17,6 @@
 Tests for ``_zkapauthorizer.schema``.
 """
 
-from __future__ import absolute_import
-
 from testtools import TestCase
 from testtools.matchers import Equals
 
diff --git a/src/_zkapauthorizer/tests/test_spending.py b/src/_zkapauthorizer/tests/test_spending.py
index 55f9aa9..42a5d87 100644
--- a/src/_zkapauthorizer/tests/test_spending.py
+++ b/src/_zkapauthorizer/tests/test_spending.py
@@ -16,35 +16,6 @@
 Tests for ``_zkapauthorizer.spending``.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if  PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from hypothesis import given
 from hypothesis.strategies import data, integers, randoms
 from testtools import TestCase
diff --git a/src/_zkapauthorizer/tests/test_storage_client.py b/src/_zkapauthorizer/tests/test_storage_client.py
index 8da2975..5a0658b 100644
--- a/src/_zkapauthorizer/tests/test_storage_client.py
+++ b/src/_zkapauthorizer/tests/test_storage_client.py
@@ -16,35 +16,6 @@
 Tests for ``_zkapauthorizer._storage_client``.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if  PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from functools import partial
 
 from allmydata.client import config_from_string
diff --git a/src/_zkapauthorizer/tests/test_storage_protocol.py b/src/_zkapauthorizer/tests/test_storage_protocol.py
index 7e5fb3e..a231c66 100644
--- a/src/_zkapauthorizer/tests/test_storage_protocol.py
+++ b/src/_zkapauthorizer/tests/test_storage_protocol.py
@@ -16,8 +16,6 @@
 Tests for communication between the client and server components.
 """
 
-from __future__ import absolute_import
-
 from allmydata.storage.common import storage_index_to_dir
 from allmydata.storage.shares import get_share_file
 from challenge_bypass_ristretto import PublicKey, random_signing_key
diff --git a/src/_zkapauthorizer/tests/test_storage_server.py b/src/_zkapauthorizer/tests/test_storage_server.py
index b40e826..d482991 100644
--- a/src/_zkapauthorizer/tests/test_storage_server.py
+++ b/src/_zkapauthorizer/tests/test_storage_server.py
@@ -16,8 +16,6 @@
 Tests for ``_zkapauthorizer._storage_server``.
 """
 
-from __future__ import absolute_import, division
-
 from random import shuffle
 from time import time
 
@@ -136,7 +134,7 @@ class ValidationResultTests(TestCase):
                     AfterPreprocessing(
                         str,
                         Equals(
-                            "MorePassesRequired(valid_count=4, required_count=10, signature_check_failed={})".format(str(frozenset([4]))),
+                            "MorePassesRequired(valid_count=4, required_count=10, signature_check_failed=frozenset({4}))",
                         ),
                     ),
                 ),
diff --git a/src/_zkapauthorizer/tests/test_strategies.py b/src/_zkapauthorizer/tests/test_strategies.py
index da97570..1184dbb 100644
--- a/src/_zkapauthorizer/tests/test_strategies.py
+++ b/src/_zkapauthorizer/tests/test_strategies.py
@@ -16,35 +16,6 @@
 Tests for our custom Hypothesis strategies.
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
-from future.utils import PY2
-
-if PY2:
-    from future.builtins import (  # noqa: F401
-        filter,
-        map,
-        zip,
-        ascii,
-        chr,
-        hex,
-        input,
-        next,
-        oct,
-        open,
-        pow,
-        round,
-        super,
-        bytes,
-        dict,
-        list,
-        object,
-        range,
-        str,
-        max,
-        min,
-    )
-
 from allmydata.client import config_from_string
 from fixtures import TempDir
 from hypothesis import given, note
-- 
GitLab