diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 10c1c88da120f620f30ad21ea131693453c51544..ebbb4a14792901da84824e7c12480a8cb3ee9cec 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -11,18 +11,21 @@ Changed
 ^^^^^^^
 
 * The ``fslpy`` API ocumentation is now hosted at
-  https://open.win.ox.ac.uk/fsl/fslpy
+  https://open.win.ox.ac.uk/fsl/fslpy (!290).
 * The :mod:`fsl` and :mod:`fsl.scripts` packages have been changed from being
   `pkgutil-style
   <https://packaging.python.org/guides/packaging-namespace-packages/#pkgutil-style-namespace-packages>`_
   namespace packages to now being `native
   <https://packaging.python.org/guides/packaging-namespace-packages/#native-namespace-packages>`_
-  namespace packages.
+  namespace packages (!290).
 * The :class:`.TaskThread` now allows an error handler function to be
-  specified, which is run on the :mod:`.idle` loop.
+  specified, which is run on the :mod:`.idle` loop (!283).
 * The :func:`.bids.loadMetadata` function no long resolves sym-links when
-  determining whether a file is contained within a BIDS data set.
-
+  determining whether a file is contained within a BIDS data set (!287).
+* The :class:`.Image` class can now be created from a ``pathlib.Path`` object
+  (!292).
+* Some functions in the :mod:`.path` module can now be used with
+  ``pathlib.Path`` objects (!293).
 
 Deprecated
 ^^^^^^^^^^
@@ -32,17 +35,20 @@ Deprecated
   :mod:`fsl.utils.platform` module, including ``frozen``, ``haveGui``,
   ``canHaveGui``, ``inSSHSession``, ``inVNCSession``, ``wxPlatform``,
   ``wxFlavour``, ``glVersion``, ``glRenderer``, and ``glIsSoftwareRenderer``.
-  Equivalent functions are being added to the ``fsleyes-widgets`` library.
+  Equivalent functions are being added to the ``fsleyes-widgets`` library
+  (!285).
 * The :mod:`fsl.utils.filetree` package has been deprecated, and will be
   removed in a future version of ``fslpy`` - it is now published as a separate
-  library on [PyPI](https://pypi.org/project/file-tree/).
+  library on [PyPI](https://pypi.org/project/file-tree/) (!286).
 
 
 Fixed
 ^^^^^
 
 * Fixed an edge-case in the :mod:`.gifti` module, where a surface with a
-  single triangle was being loaded incorrectly.
+  single triangle was being loaded incorrectly (!288).
+* Fixed an issue in the :func:`.func_to_cmd` function, where it was
+  unintentionally leaving flie handles open (!291).
 
 
 
diff --git a/README.rst b/README.rst
index f8b8fd8a118d8b0ee4e3070735c2d56b6d3e7b56..06df04918be7c407e33517f1466553048e2c5edc 100644
--- a/README.rst
+++ b/README.rst
@@ -19,7 +19,7 @@ programming library written in Python. It is used by `FSLeyes
 <https://git.fmrib.ox.ac.uk/fsl/fsleyes/fsleyes/>`_.
 
 
-``fslpy`` is tested against Python versions 3.6, 3.7, 3.8 and 3.9.
+``fslpy`` is tested against Python versions 3.7, 3.8 and 3.9.
 
 
 Installation
diff --git a/fsl/data/bitmap.py b/fsl/data/bitmap.py
index 51b354f7ddfcef93cb44a2d2a83231b518d89fe2..4562300a794357d6382a3317a34b277f62d2b816 100644
--- a/fsl/data/bitmap.py
+++ b/fsl/data/bitmap.py
@@ -9,13 +9,13 @@ files. Pillow is required to use the ``Bitmap`` class.
 """
 
 
-import os.path      as op
-import                 logging
-import                 six
+import os.path as op
+import            pathlib
+import            logging
 
-import numpy        as np
+import numpy as np
 
-from . import image as fslimage
+import fsl.data.image as fslimage
 
 
 log = logging.getLogger(__name__)
@@ -51,7 +51,7 @@ class Bitmap(object):
                   data.
         """
 
-        if isinstance(bmp, six.string_types):
+        if isinstance(bmp, (pathlib.Path, str)):
 
             try:
                 # Allow big images
@@ -61,7 +61,7 @@ class Bitmap(object):
             except ImportError:
                 raise RuntimeError('Install Pillow to use the Bitmap class')
 
-            src = bmp
+            src = str(bmp)
             img = Image.open(src)
 
             # If this is a palette/LUT
diff --git a/fsl/data/image.py b/fsl/data/image.py
index 3dfe8a818286126c98939d83a3979f2f363cb375..b5d0cad72d12850aecbeeab7ac072aca9f9d3485 100644
--- a/fsl/data/image.py
+++ b/fsl/data/image.py
@@ -32,22 +32,21 @@ and file names:
 """
 
 
-import                      os
-import os.path           as op
-import itertools         as it
-import                      json
-import                      string
-import                      logging
-import                      tempfile
-
-import                      six
-import numpy             as np
+import                  os
+import os.path   as     op
+import itertools as     it
+import                  json
+import                  string
+import                  logging
+import                  tempfile
+
+from pathlib import Path
+from typing  import Union
 
+import numpy             as np
 import nibabel           as nib
 import nibabel.fileslice as fileslice
 
-from pathlib import Path
-
 import fsl.utils.meta        as meta
 import fsl.transform.affine  as affine
 import fsl.utils.notifier    as notifier
@@ -58,6 +57,10 @@ import fsl.data.constants    as constants
 import fsl.data.imagewrapper as imagewrapper
 
 
+PathLike    = Union[str, Path]
+ImageSource = Union[PathLike, nib.Nifti1Image, np.ndarray, 'Image']
+
+
 log = logging.getLogger(__name__)
 
 
@@ -993,21 +996,21 @@ class Image(Nifti):
 
 
     def __init__(self,
-                 image,
-                 name=None,
-                 header=None,
-                 xform=None,
-                 loadData=True,
-                 calcRange=True,
-                 threaded=False,
-                 dataSource=None,
-                 loadMeta=False,
+                 image      : ImageSource,
+                 name       : str              = None,
+                 header     : nib.Nifti1Header = None,
+                 xform      : np.ndarray       = None,
+                 loadData   : bool             = True,
+                 calcRange  : bool             = True,
+                 threaded   : bool             = False,
+                 dataSource : PathLike         = None,
+                 loadMeta   : bool             = False,
                  **kwargs):
         """Create an ``Image`` object with the given image data or file name.
 
         :arg image:      A string containing the name of an image file to load,
-                         or a Path object pointing to an image file, or a 
-                         :mod:`numpy` array, or a :mod:`nibabel` image object, 
+                         or a Path object pointing to an image file, or a
+                         :mod:`numpy` array, or a :mod:`nibabel` image object,
                          or an ``Image`` object.
 
         :arg name:       A name for the image.
@@ -1086,16 +1089,11 @@ class Image(Nifti):
             header.set_qform(xform, code=qform)
 
         # The image parameter may be the name of an image file
-        if isinstance(image, six.string_types):
+        if isinstance(image, (str, Path)):
             image      = op.abspath(addExt(image))
             nibImage   = nib.load(image, **kwargs)
             dataSource = image
             saved      = True
-        # The image parameter may be a Path object pointing to an image file
-        elif isinstance(image, Path):
-            nibImage   = nib.load(image, **kwargs)
-            dataSource = str(image)
-            saved      = True
 
         # Or a numpy array - we wrap it in a nibabel image,
         # with an identity transformation (each voxel maps
@@ -1141,15 +1139,13 @@ class Image(Nifti):
             nibImage = image
 
         # Figure out the name of this image, if
-        # it has not beenbeen explicitly passed in
+        # it has not been explicitly passed in
         if name is None:
 
             # If this image was loaded
             # from disk, use the file name.
-            if isinstance(image, six.string_types):
+            if isinstance(image, (str, Path)):
                 name = removeExt(op.basename(image))
-            elif isinstance(image, Path):
-                name = image.name
 
             # Or the image was created from a numpy array
             elif isinstance(image, np.ndarray):
diff --git a/fsl/data/mghimage.py b/fsl/data/mghimage.py
index 38f854446d3333cd7f150bd082d80d76df6cc236..8464d3d2ce674e7c07fc7d7b03b3c5b2f4cdd898 100644
--- a/fsl/data/mghimage.py
+++ b/fsl/data/mghimage.py
@@ -10,8 +10,8 @@ Freesurfer ``mgh``/``mgz`` image files.
 
 
 import os.path as op
+import            pathlib
 
-import            six
 import numpy   as np
 import nibabel as nib
 
@@ -47,7 +47,7 @@ class MGHImage(fslimage.Image):
         All other arguments are passed through to :meth:`Image.__init__`
         """
 
-        if isinstance(image, six.string_types):
+        if isinstance(image, (str, pathlib.Path)):
             filename = op.abspath(image)
             name     = op.basename(filename)
             image    = nib.load(image)
diff --git a/fsl/utils/ensure.py b/fsl/utils/ensure.py
index a2fd8d4913dc921f541a1e8430933b72bec43b12..3e3ea8e92e1a2ce570a53c3898521af38c1af0ef 100644
--- a/fsl/utils/ensure.py
+++ b/fsl/utils/ensure.py
@@ -14,8 +14,6 @@ that some condition is met.
 """
 
 
-import six
-
 import nibabel as nib
 
 import fsl.data.image as fslimage
@@ -24,7 +22,7 @@ import fsl.data.image as fslimage
 def ensureIsImage(img):
     """Ensures that the given ``img`` is an in-memory ``nibabel`` object.
     """
-    if isinstance(img, six.string_types):
+    if isinstance(img, str):
         img = fslimage.addExt(img)
         img = nib.load(img)
     return img
diff --git a/fsl/utils/fslsub.py b/fsl/utils/fslsub.py
index 4a09f0828cb0bea65305c1e4272437fc4094b57f..22e9de1ece00c4d7a62238f6da0c4193274dac88 100644
--- a/fsl/utils/fslsub.py
+++ b/fsl/utils/fslsub.py
@@ -37,7 +37,7 @@ Example usage, building a short pipeline::
 """
 
 
-from six import BytesIO
+from io import BytesIO
 import os.path as op
 import glob
 import time
@@ -439,9 +439,9 @@ _external_job = ("""#!{}
 # This is a temporary file designed to run the python function {},
 # so that it can be submitted to the cluster
 import pickle
-from six import BytesIO
+from io import BytesIO
 from importlib import import_module
-{} 
+{}
 pickle_bytes = BytesIO({})
 name_type, name, func_name, args, kwargs = pickle.load(pickle_bytes)
 
@@ -455,7 +455,7 @@ elif name_type == 'script':
     func = local_execute[func_name]
 else:
     raise ValueError('Unknown name_type: %r' % name_type)
-    
+
 {}
 
 """)
diff --git a/fsl/utils/memoize.py b/fsl/utils/memoize.py
index b777eed0c945a048858806107487bf214d710984..b7ee159c2d891db915e92d0bf37929ff3b5a7870 100644
--- a/fsl/utils/memoize.py
+++ b/fsl/utils/memoize.py
@@ -21,7 +21,6 @@ a function:
 import logging
 import hashlib
 import functools
-import six
 
 log = logging.getLogger(__name__)
 
@@ -171,7 +170,7 @@ def memoizeMD5(func):
         # compatible) bytes , and take
         # the hash of those bytes.
         for arg in args:
-            if not isinstance(arg, six.string_types):
+            if not isinstance(arg, str):
                 arg = str(arg)
             arg = arg.encode('utf-8')
             hashobj.update(arg)
diff --git a/fsl/utils/notifier.py b/fsl/utils/notifier.py
index cd07204e4907175c8f8a5bf3bfa21ebd7a5d2fd9..b294f6192ce01261275aed1f07213d3d0cb7a01d 100644
--- a/fsl/utils/notifier.py
+++ b/fsl/utils/notifier.py
@@ -14,9 +14,6 @@ import inspect
 import contextlib
 import collections
 
-import six
-
-
 import fsl.utils.idle        as idle
 import fsl.utils.weakfuncref as weakfuncref
 
@@ -297,7 +294,7 @@ class Notifier(object):
         :arg topic: Topic or topics that the listener is registered on.
         """
 
-        if topic is None or isinstance(topic, six.string_types):
+        if topic is None or isinstance(topic, str):
             topic = [topic]
 
         topics = topic
diff --git a/fsl/utils/path.py b/fsl/utils/path.py
index 0a0859528945a7b944482442b0ffc658d0dc05f9..09546f4b2cdf2660e234e49a7b09814232fac83e 100644
--- a/fsl/utils/path.py
+++ b/fsl/utils/path.py
@@ -32,16 +32,21 @@ import os.path as op
 import            os
 import            glob
 import            operator
+import            pathlib
 import            re
 
+from typing import Sequence, Tuple, Union
+
 from fsl.utils.platform import platform
 
 
+PathLike = Union[str, pathlib.Path]
+
+
 class PathError(Exception):
     """``Exception`` class raised by the functions defined in this module
     when something goes wrong.
     """
-    pass
 
 
 def deepest(path, suffixes):
@@ -52,12 +57,12 @@ def deepest(path, suffixes):
 
     path = path.strip()
 
-    if path == op.sep or path == '':
+    if path in (op.sep, ''):
         return None
 
     path = path.rstrip(op.sep)
 
-    if any([path.endswith(s) for s in suffixes]):
+    if any(path.endswith(s) for s in suffixes):
         return path
 
     return deepest(op.dirname(path), suffixes)
@@ -81,7 +86,7 @@ def shallowest(path, suffixes):
     if parent is not None:
         return parent
 
-    if any([path.endswith(s) for s in suffixes]):
+    if any(path.endswith(s) for s in suffixes):
         return path
 
     return None
@@ -101,19 +106,23 @@ def allFiles(root):
     return files
 
 
-def hasExt(path, allowedExts):
+def hasExt(path        : PathLike,
+           allowedExts : Sequence[str]) -> bool:
     """Convenience function which returns ``True`` if the given ``path``
     ends with any of the given ``allowedExts``, ``False`` otherwise.
     """
-    return any([path.endswith(e) for e in allowedExts])
-
-
-def addExt(prefix,
-           allowedExts=None,
-           mustExist=True,
-           defaultExt=None,
-           fileGroups=None,
-           unambiguous=True):
+    path = str(path)
+    return any(path.endswith(e) for e in allowedExts)
+
+
+def addExt(
+        prefix      : PathLike,
+        allowedExts : Sequence[str]           = None,
+        mustExist   : bool                    = True,
+        defaultExt  : str                     = None,
+        fileGroups  : Sequence[Sequence[str]] = None,
+        unambiguous : bool                    = True
+) -> Union[Sequence[str], str]:
     """Adds a file extension to the given file ``prefix``.
 
     If ``mustExist`` is False, and the file does not already have a
@@ -148,6 +157,8 @@ def addExt(prefix,
                       containing *all* matching files is returned.
     """
 
+    prefix = str(prefix)
+
     if allowedExts is None: allowedExts = []
     if fileGroups  is None: fileGroups  = {}
 
@@ -189,7 +200,8 @@ def addExt(prefix,
 
     # If ambiguity is ok, return
     # all matching paths
-    elif not unambiguous:
+    if not unambiguous:
+
         return allPaths
 
     # Ambiguity is not ok! More than
@@ -223,19 +235,29 @@ def addExt(prefix,
     return allPaths[0]
 
 
-def removeExt(filename, allowedExts=None, firstDot=False):
+def removeExt(
+        filename    : PathLike,
+        allowedExts : Sequence[str] = None,
+        firstDot    : bool          = False
+) -> str:
     """Returns the base name of the given file name.  See :func:`splitExt`. """
-
     return splitExt(filename, allowedExts, firstDot)[0]
 
 
-def getExt(filename, allowedExts=None, firstDot=False):
+def getExt(
+        filename    : PathLike,
+        allowedExts : Sequence[str] = None,
+        firstDot    : bool          = False
+) -> str:
     """Returns the extension of the given file name.  See :func:`splitExt`. """
-
     return splitExt(filename, allowedExts, firstDot)[1]
 
 
-def splitExt(filename, allowedExts=None, firstDot=False):
+def splitExt(
+        filename    : PathLike,
+        allowedExts : Sequence[str] = None,
+        firstDot    : bool          = False
+) -> Tuple[str, str]:
     """Returns the base name and the extension from the given file name.
 
     If ``allowedExts`` is ``None`` and ``firstDot`` is ``False``, this
@@ -262,6 +284,8 @@ def splitExt(filename, allowedExts=None, firstDot=False):
                       last period. Ignored if ``allowedExts`` is specified.
     """
 
+    filename = str(filename)
+
     # If allowedExts is not specified
     # we split on a period character
     if allowedExts is None:
@@ -465,7 +489,7 @@ def removeDuplicates(paths, allowedExts=None, fileGroups=None):
 
         groupFiles = getFileGroup(path, allowedExts, fileGroups)
 
-        if not any([p in unique for p in groupFiles]):
+        if not any(p in unique for p in groupFiles):
             unique.append(groupFiles[0])
 
     return unique
@@ -492,14 +516,13 @@ def uniquePrefix(path):
             break
 
         # Should never happen if path is valid
-        elif len(hits) == 0 or idx >= len(filename) - 1:
+        if len(hits) == 0 or idx >= len(filename) - 1:
             raise PathError('No unique prefix for {}'.format(filename))
 
         # Not unique - continue looping
-        else:
-            idx    += 1
-            prefix  = prefix + filename[idx]
-            hits    = [h for h in hits if h.startswith(prefix)]
+        idx    += 1
+        prefix  = prefix + filename[idx]
+        hits    = [h for h in hits if h.startswith(prefix)]
 
     return prefix
 
@@ -525,54 +548,56 @@ def commonBase(paths):
 
         last = base
 
-        if all([p.startswith(base) for p in paths]):
+        if all(p.startswith(base) for p in paths):
             return base
 
     raise PathError('No common base')
 
 
-def wslpath(winpath):
-    """
-    Convert Windows path (or a command line argument containing a Windows path)
-    to the equivalent WSL path (e.g. ``c:\\Users`` -> ``/mnt/c/Users``). Also supports
-    paths in the form ``\\wsl$\\(distro)\\users\\...``
-
-    :param winpath: Command line argument which may (or may not) contain a Windows path. It is assumed to be
-                    either of the form <windows path> or --<arg>=<windows path>. Note that we don't need to
-                    handle --arg <windows path> or -a <windows path> since in these cases the argument
-                    and the path will be parsed as separate entities.
-    :return: If ``winpath`` matches a Windows path, the converted argument (including the --<arg>= portion).
-                Otherwise returns ``winpath`` unchanged.
+def wslpath(path):
+    """Convert Windows path (or a command line argument containing a Windows
+    path) to the equivalent WSL path (e.g. ``c:\\Users`` -> ``/mnt/c/Users``).
+    Also supports paths in the form ``\\wsl$\\(distro)\\users\\...``
+
+    :param winpath: Command line argument which may (or may not) contain a
+                    Windows path. It is assumed to be either of the form
+                    <windows path> or --<arg>=<windows path>. Note that we
+                    don't need to handle --arg <windows path> or -a <windows
+                    path> since in these cases the argument and the path will
+                    be parsed as separate entities.
+    :return:        If ``winpath`` matches a Windows path, the converted
+                    argument (including the --<arg>= portion).  Otherwise
+                    returns ``winpath`` unchanged.
+
     """
-    match = re.match(r"^(--[\w-]+=)?\\\\wsl\$[\\\/][^\\^\/]+(.*)$", winpath)
+    match = re.match(r"^(--[\w-]+=)?\\\\wsl\$[\\\/][^\\^\/]+(.*)$", path)
     if match:
         arg, path = match.group(1, 2)
         if arg is None:
             arg = ""
         return arg + path.replace("\\", "/")
 
-    match = re.match(r"^(--[\w-]+=)?([a-zA-z]):(.+)$", winpath)
+    match = re.match(r"^(--[\w-]+=)?([a-zA-z]):(.+)$", path)
     if match:
         arg, drive, path = match.group(1, 2, 3)
         if arg is None:
             arg = ""
         return arg + "/mnt/" + drive.lower() + path.replace("\\", "/")
 
-    return winpath
+    return path
 
 
-def winpath(wslpath):
-    """
-    Convert a WSL-local filepath (for example ``/usr/local/fsl/``) into a path that can be used from
-    Windows.
+def winpath(path):
+    """Convert a WSL-local filepath (for example ``/usr/local/fsl/``) into a
+    path that can be used from Windows.
 
     If ``self.fslwsl`` is ``False``, simply returns ``wslpath`` unmodified
     Otherwise, uses ``FSLDIR`` to deduce the WSL distro in use for FSL.
-    This requires WSL2 which supports the ``\\wsl$\`` network path.
+    This requires WSL2 which supports the ``\\wsl$\\`` network path.
     wslpath is assumed to be an absolute path.
     """
     if not platform.fslwsl:
-        return wslpath
+        return path
     else:
         match = re.match(r"^\\\\wsl\$\\([^\\]+).*$", platform.fsldir)
         if match:
@@ -581,6 +606,7 @@ def winpath(wslpath):
             distro = None
 
         if not distro:
-            raise RuntimeError("Could not identify WSL installation from FSLDIR (%s)" % platform.fsldir)
+            raise RuntimeError('Could not identify WSL installation from '
+                               'FSLDIR (%s)' % platform.fsldir)
 
-        return "\\\\wsl$\\" + distro + wslpath.replace("/", "\\")
+        return "\\\\wsl$\\" + distro + path.replace("/", "\\")
diff --git a/fsl/utils/run.py b/fsl/utils/run.py
index 1e535c8a336de44f3a7d819f067417075eaa16d3..a7e4971baea5125e9723ce184d6a65dc5a58c0ce 100644
--- a/fsl/utils/run.py
+++ b/fsl/utils/run.py
@@ -30,8 +30,6 @@ import subprocess      as sp
 import os.path         as op
 import                    os
 
-import                    six
-
 from   fsl.utils.platform import platform as fslplatform
 import fsl.utils.fslsub                   as fslsub
 import fsl.utils.tempdir                  as tempdir
@@ -83,7 +81,7 @@ def prepareArgs(args):
     if len(args) == 1:
 
         # Argument was a command string
-        if isinstance(args[0], six.string_types):
+        if isinstance(args[0], str):
             args = shlex.split(args[0])
 
         # Argument was an unpacked sequence
diff --git a/fsl/utils/weakfuncref.py b/fsl/utils/weakfuncref.py
index 37e118566e814da3c5421037377ae02496483ab0..6216c2dd5f3ed267c6cdf2643707db7865634c69 100644
--- a/fsl/utils/weakfuncref.py
+++ b/fsl/utils/weakfuncref.py
@@ -7,13 +7,12 @@
 """This module provides the :class:`WeakFunctionRef` class. """
 
 
-import six
 import types
 import weakref
 import inspect
 
 
-class WeakFunctionRef(object):
+class WeakFunctionRef:
     """Class which encapsulates a :mod:`weakref` to a function or method.
 
     This class is used by :class:`.Notifier` instances to reference
@@ -28,10 +27,10 @@ class WeakFunctionRef(object):
         """
 
         # Bound method
-        if self.__isMethod(func):
+        if inspect.ismethod(func):
 
-            boundMeth = six.get_method_function(func)
-            boundSelf = six.get_method_self(    func)
+            boundMeth = func.__func__
+            boundSelf = func.__self__
 
             # We can't take a weakref of the method
             # object, so we have to weakref the object
@@ -73,35 +72,6 @@ class WeakFunctionRef(object):
         return self.__str__()
 
 
-    def __isMethod(self, func):
-        """Returns ``True`` if the given function is a bound method,
-        ``False`` otherwise.
-
-        This seems to be one of the few areas where python 2 and 3 are
-        irreconcilably incompatible (or just where :mod:`six` does not have a
-        function to help us).
-
-        In Python 3 there is no difference between an unbound method and a
-        function. But in Python 2, an unbound method is still a method (and
-        inspect.ismethod returns True).
-        """
-
-        ismethod = False
-
-        # Therefore, in python2 we need to test
-        # whether the function is a method, and
-        # also test whether it is bound.
-        if six.PY2:
-            ismethod = (inspect.ismethod(func) and
-                        six.get_method_self(func) is not None)
-
-        # But in python3, if the function is a
-        # method it is, by definition, bound.
-        elif six.PY3:
-            ismethod = inspect.ismethod(func)
-
-        return ismethod
-
 
     def __findPrivateMethod(self):
         """Finds and returns the bound method associated with the encapsulated
@@ -125,8 +95,7 @@ class WeakFunctionRef(object):
 
             att = getattr(obj, name)
 
-            if isinstance(att, types.MethodType) and \
-               six.get_method_function(att) is func:
+            if isinstance(att, types.MethodType) and att.__func__ is func:
                 return att
 
         return None
diff --git a/fsl/wrappers/fast.py b/fsl/wrappers/fast.py
index e18ec69effd6be4b6ef7cac023f7b1ae77a2414e..c51c9f245ad153018d1a76a81dd2d743f3b437c5 100644
--- a/fsl/wrappers/fast.py
+++ b/fsl/wrappers/fast.py
@@ -10,8 +10,6 @@
 """
 
 
-import six
-
 import fsl.utils.assertions as asrt
 from . import wrapperutils  as wutils
 
@@ -28,7 +26,7 @@ def fast(imgs, out='fast', **kwargs):
                     command line option)
     """
 
-    if isinstance(imgs, six.string_types):
+    if isinstance(imgs, str):
         imgs = [imgs]
 
     asrt.assertIsNifti(*imgs)
diff --git a/fsl/wrappers/fsl_anat.py b/fsl/wrappers/fsl_anat.py
index 868dacb70d206fe5a9b53907668cc7641513bf52..0b5e5e163ceb7b885bebf95e2bc714b13c12ebc0 100644
--- a/fsl/wrappers/fsl_anat.py
+++ b/fsl/wrappers/fsl_anat.py
@@ -8,8 +8,6 @@
 `FSL_ANAT <https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/fsl_anat>`_ command.
 """
 
-import six
-
 import fsl.utils.assertions as asrt
 from . import wrapperutils  as wutils
 
diff --git a/fsl/wrappers/wrapperutils.py b/fsl/wrappers/wrapperutils.py
index 8739a1a34fea38b025a956326e23d11471f343e5..60413b866bee6100c3e9be198ac14abb42e221fd 100644
--- a/fsl/wrappers/wrapperutils.py
+++ b/fsl/wrappers/wrapperutils.py
@@ -103,8 +103,6 @@ import                    tempfile
 import                    warnings
 import                    functools
 
-
-import            six
 import nibabel as nib
 import numpy   as np
 
@@ -346,8 +344,7 @@ def applyArgStyle(style,
 
     # always returns a sequence
     def fmtval(val):
-        if     isinstance(val, abc.Sequence) and \
-           not isinstance(val, six.string_types):
+        if isinstance(val, abc.Sequence) and (not isinstance(val, str)):
 
             val = [str(v) for v in val]
             if   valsep == ' ': return val
@@ -711,8 +708,7 @@ class FileOrThing(object):
            kwargs.get('cmdonly', False):
             allargs = {**dict(zip(argnames, args)), **kwargs}
             for name, val in allargs.items():
-                if (name in self.__things) and \
-                   (not isinstance(val, six.string_types)):
+                if (name in self.__things) and (not isinstance(val, str)):
                     raise ValueError('Cannot use in-memory objects '
                                      'or LOAD with submit=True!')
             return func(*args, **kwargs)
diff --git a/requirements.txt b/requirements.txt
index 23dc58fde626c364d58edc0b6ac7d76f077412b7..faf34174fc2bb63d9c44706feb097f8f2b619dee 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,5 +2,4 @@ h5py>=2.9
 nibabel>=2.4
 numpy>=1
 scipy>=0.18
-six>=1
 dataclasses
diff --git a/setup.py b/setup.py
index ebfa3afea50ef5e16cb9ccdeda8022dac84d3876..60c5d46c22b80ed27ad076a5e4ffe4c4b41c057e 100644
--- a/setup.py
+++ b/setup.py
@@ -8,8 +8,9 @@
 
 from __future__ import print_function
 
-import os.path as op
-import            shutil
+import os.path       as op
+import                  shutil
+import unittest.mock as mock
 
 from setuptools import setup
 from setuptools import find_namespace_packages
@@ -68,11 +69,6 @@ class doc(Command):
 
         import sphinx.cmd.build as sphinx_build
 
-        try:
-            import unittest.mock as mock
-        except:
-            import mock
-
         mockobj       = mock.MagicMock()
         mockobj.__version__ = '2.2.0'
         mockedModules = open(op.join(docdir, 'mock_modules.txt')).readlines()
@@ -104,6 +100,7 @@ setup(
         'License :: OSI Approved :: Apache Software License',
         'Programming Language :: Python :: 3.7',
         'Programming Language :: Python :: 3.8',
+        'Programming Language :: Python :: 3.9',
         'Topic :: Software Development :: Libraries :: Python Modules'],
 
     packages=packages,
diff --git a/tests/__init__.py b/tests/__init__.py
index 24587392fc29de81bea199cb8e991b6012cba22e..58e6d23beda36a3c4cf2ce61046c54310173d5e8 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -20,11 +20,9 @@ import os.path   as op
 import numpy     as np
 import nibabel   as nib
 
-from six import StringIO
+from io import StringIO
 
-
-try: from unittest import mock
-except ImportError: import mock
+from unittest import mock
 
 import fsl.data.image                     as fslimage
 from   fsl.utils.tempdir import              tempdir
diff --git a/tests/test_fsl_utils_path.py b/tests/test_fsl_utils_path.py
index 0361ced5ee2843f4c6827e4bbcabd705251d6cdf..fbf95953682951961db2078bdc26f04b98d310c5 100644
--- a/tests/test_fsl_utils_path.py
+++ b/tests/test_fsl_utils_path.py
@@ -5,15 +5,15 @@
 # Author: Paul McCarthy <pauldmccarthy@gmail.com>
 #
 
-from __future__ import print_function
-
 import            os
 import os.path as op
 import            shutil
+import            pathlib
 import            tempfile
 
+from unittest import mock
+
 import pytest
-import mock
 
 import fsl.utils.path as fslpath
 import fsl.data.image as fslimage
@@ -150,7 +150,8 @@ def test_hasExt():
     ]
 
     for path, aexts, expected in tests:
-        assert fslpath.hasExt(path, aexts) == expected
+        assert fslpath.hasExt(path,               aexts) == expected
+        assert fslpath.hasExt(pathlib.Path(path), aexts) == expected
 
 
 def test_addExt_imageFiles_mustExist_shouldPass():
@@ -248,18 +249,15 @@ def test_addExt_imageFiles_mustExist_shouldPass():
             for f in files_to_create:
                 make_dummy_image_file(op.join(workdir, f))
 
-            print('files_to_create: ', files_to_create)
-            print('workdir:         ', os.listdir(workdir))
-            print('prefix:          ', prefix)
-            print('expected:        ', expected)
-
-            result =  fslpath.addExt(op.join(workdir, prefix),
-                                     allowedExts,
-                                     mustExist=True,
-                                     fileGroups=groups)
-
-            print('result:          ', result)
-
+            result = fslpath.addExt(op.join(workdir, prefix),
+                                    allowedExts,
+                                    mustExist=True,
+                                    fileGroups=groups)
+            assert result == op.join(workdir, expected)
+            result = fslpath.addExt(pathlib.Path(op.join(workdir, prefix)),
+                                    allowedExts,
+                                    mustExist=True,
+                                    fileGroups=groups)
             assert result == op.join(workdir, expected)
 
             cleardir(workdir)
@@ -336,20 +334,15 @@ def test_addExt_otherFiles_mustExist_shouldPass():
             for f in files_to_create:
                 make_dummy_file(op.join(workdir, f))
 
-            print('files_to_create: ', files_to_create)
-            print('prefix:          ', prefix)
-            print('allowedExts:     ', allowedExts)
-            print('fileGroups:      ', fileGroups)
-            print('workdir:         ', os.listdir(workdir))
-            print('expected:        ', expected)
-
-            result =  fslpath.addExt(op.join(workdir, prefix),
-                                     allowedExts=allowedExts,
-                                     mustExist=True,
-                                     fileGroups=fileGroups)
-
-            print('result:          ', result)
-
+            result = fslpath.addExt(op.join(workdir, prefix),
+                                    allowedExts=allowedExts,
+                                    mustExist=True,
+                                    fileGroups=fileGroups)
+            assert result == op.join(workdir, expected)
+            result = fslpath.addExt(pathlib.Path(op.join(workdir, prefix)),
+                                    allowedExts=allowedExts,
+                                    mustExist=True,
+                                    fileGroups=fileGroups)
             assert result == op.join(workdir, expected)
 
             cleardir(workdir)
@@ -422,18 +415,16 @@ def test_addExt_imageFiles_mustExist_shouldFail():
             for f in files_to_create:
                 make_dummy_file(op.join(workdir, f))
 
-            print('files_to_create: ', files_to_create)
-            print('prefix:          ', prefix)
-            print('workdir:         ', os.listdir(workdir))
-
             with pytest.raises(fslpath.PathError):
-
-                result = fslpath.addExt(op.join(workdir, prefix),
-                                        allowedExts=allowedExts,
-                                        mustExist=True,
-                                        fileGroups=fileGroups)
-
-                print('result:          ', result)
+                fslpath.addExt(op.join(workdir, prefix),
+                               allowedExts=allowedExts,
+                               mustExist=True,
+                               fileGroups=fileGroups)
+            with pytest.raises(fslpath.PathError):
+                fslpath.addExt(pathlib.Path(op.join(workdir, prefix)),
+                               allowedExts=allowedExts,
+                               mustExist=True,
+                               fileGroups=fileGroups)
 
     finally:
         shutil.rmtree(workdir)
@@ -481,23 +472,19 @@ def test_addExt_otherFiles_mustExist_shouldFail():
             for f in files_to_create:
                 make_dummy_file(op.join(workdir, f))
 
-            print('files_to_create: ', files_to_create)
-            print('prefix:          ', prefix)
-            print('workdir:         ', os.listdir(workdir))
-
             with pytest.raises(fslpath.PathError):
-
-                result = fslpath.addExt(op.join(workdir, prefix),
-                                        allowedExts=allowedExts,
-                                        mustExist=True,
-                                        fileGroups=fileGroups)
-
-                print('result:          ', result)
-
+                fslpath.addExt(op.join(workdir, prefix),
+                               allowedExts=allowedExts,
+                               mustExist=True,
+                               fileGroups=fileGroups)
+            with pytest.raises(fslpath.PathError):
+                fslpath.addExt(pathlib.Path(op.join(workdir, prefix)),
+                               allowedExts=allowedExts,
+                               mustExist=True,
+                               fileGroups=fileGroups)
 
     finally:
         shutil.rmtree(workdir)
-    pass
 
 
 def test_addExt_noExist():
@@ -544,11 +531,14 @@ def test_addExt_noExist():
     ]
 
     for prefix, defaultExt, allowedExts, expected in tests:
-
         assert fslpath.addExt(prefix,
                               allowedExts,
                               defaultExt=defaultExt,
                               mustExist=False) == expected
+        assert fslpath.addExt(pathlib.Path(prefix),
+                              allowedExts,
+                              defaultExt=defaultExt,
+                              mustExist=False) == expected
 
 
 def test_addExt_unambiguous():
@@ -582,15 +572,20 @@ def test_addExt_unambiguous():
         expected = expected.split()
 
         with testdir(create) as td:
-
             result = fslpath.addExt(prefix,
                                     allowedExts=exts,
                                     fileGroups=groups,
                                     defaultExt=defaultExt,
                                     unambiguous=False)
-
+            assert sorted(expected) == sorted(result)
+            result = fslpath.addExt(pathlib.Path(prefix),
+                                    allowedExts=exts,
+                                    fileGroups=groups,
+                                    defaultExt=defaultExt,
+                                    unambiguous=False)
             assert sorted(expected) == sorted(result)
 
+
 def test_removeExt():
 
     allowedExts = fslimage.ALLOWED_EXTENSIONS
@@ -622,7 +617,8 @@ def test_removeExt():
         if len(test) == 2: allowed = allowedExts
         else:              allowed = test[2]
 
-        assert fslpath.removeExt(path, allowed) == output
+        assert fslpath.removeExt(path,               allowed) == output
+        assert fslpath.removeExt(pathlib.Path(path), allowed) == output
 
 
 def test_getExt():
@@ -658,8 +654,8 @@ def test_getExt():
         if len(test) == 2: allowed = allowedExts
         else:              allowed = test[2]
 
-        print(filename, '==', output)
-        assert fslpath.getExt(filename, allowed) == output
+        assert fslpath.getExt(filename,               allowed) == output
+        assert fslpath.getExt(pathlib.Path(filename), allowed) == output
 
 
 def test_splitExt():
@@ -704,13 +700,14 @@ def test_splitExt():
 
     for test in tests:
         filename          = test[0]
+        pfilename         = pathlib.Path(filename)
         outbase, outext   = test[1]
 
         if len(test) == 2: allowed = allowedExts
         else:              allowed = test[2]
 
-        print(filename, '==', (outbase, outext))
-        assert fslpath.splitExt(filename, allowed) == (outbase, outext)
+        assert fslpath.splitExt(filename,  allowed) == (outbase, outext)
+        assert fslpath.splitExt(pfilename, allowed) == (outbase, outext)
 
     # firstDot=True
     tests = [
@@ -721,7 +718,9 @@ def test_splitExt():
     ]
 
     for f, exp in tests:
-        assert fslpath.splitExt(f, firstDot=True) == exp
+        pf = pathlib.Path(f)
+        assert fslpath.splitExt(f,  firstDot=True) == exp
+        assert fslpath.splitExt(pf, firstDot=True) == exp
 
 
 def test_getFileGroup_imageFiles_shouldPass():
@@ -798,11 +797,6 @@ def test_getFileGroup_imageFiles_shouldPass():
                 with open(op.join(workdir, fn), 'wt') as f:
                     f.write('{}\n'.format(fn))
 
-            print()
-            print('files_to_create: ', files_to_create)
-            print('path:            ', path)
-            print('files_to_expect: ', files_to_expect)
-
             fullPaths = fslpath.getFileGroup(
                 op.join(workdir, path),
                 allowedExts=allowedExts,
@@ -918,13 +912,6 @@ def test_getFileGroup_otherFiles_shouldPass():
                 with open(op.join(workdir, fn), 'wt') as f:
                     f.write('{}\n'.format(fn))
 
-            print()
-            print('files_to_create: ', files_to_create)
-            print('path:            ', path)
-            print('allowedExts:     ', allowedExts)
-            print('fileGroups:      ', fileGroups)
-            print('files_to_expect: ', files_to_expect)
-
             fullPaths = fslpath.getFileGroup(
                 op.join(workdir, path),
                 allowedExts=allowedExts,
@@ -1006,32 +993,22 @@ def test_getFileGroup_shouldFail():
                 with open(op.join(workdir, fn), 'wt') as f:
                     f.write('{}\n'.format(fn))
 
-            print()
-            print('files_to_create: ', files_to_create)
-            print('path:            ', path)
-            print('allowedExts:     ', allowedExts)
-            print('fileGroups:      ', fileGroups)
-
             with pytest.raises(fslpath.PathError):
-                fullPaths = fslpath.getFileGroup(
+                fslpath.getFileGroup(
                     op.join(workdir, path),
                     allowedExts=allowedExts,
                     fileGroups=fileGroups,
                     fullPaths=True,
                     unambiguous=unambiguous)
 
-                print('fullPaths:       ', fullPaths)
-
             with pytest.raises(fslpath.PathError):
-                exts = fslpath.getFileGroup(
+                fslpath.getFileGroup(
                     op.join(workdir, path),
                     allowedExts=allowedExts,
                     fileGroups=fileGroups,
                     fullPaths=False,
                     unambiguous=unambiguous)
 
-                print('exts:            ', exts)
-
             cleardir(workdir)
 
     finally:
@@ -1117,16 +1094,9 @@ def test_removeDuplicates_imageFiles_shouldPass():
                 paths    = paths.split()
                 expected = expected.split()
 
-                print()
-                print('files_to_create: ', files_to_create)
-                print('paths:           ', paths)
-                print('expected:        ', expected)
-
                 paths  = [op.join(workdir, p) for p in paths]
                 result = fslpath.removeDuplicates(paths, allowedExts, groups)
 
-                print('result:   ', result)
-
                 assert result == [op.join(workdir, e) for e in expected]
 
             cleardir(workdir)
@@ -1196,20 +1166,10 @@ def test_removeDuplicates_otherFiles_shouldPass():
 
             for f in files_to_create:
                 make_dummy_file(op.join(workdir, f))
-
-            print('files_to_create: {}'.format(files_to_create))
-            print('paths:           {}'.format(paths))
-            print('allowedExts:     {}'.format(allowedExts))
-            print('fileGroups:      {}'.format(fileGroups))
-            print('workdir:         {}'.format(os.listdir(workdir)))
-            print('expected:        {}'.format(expected))
-
             result = fslpath.removeDuplicates([op.join(workdir, p) for p in paths],
                                               allowedExts=allowedExts,
                                               fileGroups=fileGroups)
 
-            print('result:          {}'.format(result))
-
             assert result == [op.join(workdir, e) for e in expected]
 
             cleardir(workdir)
@@ -1256,17 +1216,10 @@ def test_removeDuplicates_shouldFail():
                 with open(op.join(workdir, fn), 'wt') as f:
                     f.write('{}\n'.format(fn))
 
-            print()
-            print('files_to_create: ', files_to_create)
-            print('path:            ', path)
-            print('allowedExts:     ', allowedExts)
-            print('fileGroups:      ', fileGroups)
-
             with pytest.raises(fslpath.PathError):
-                result = fslpath.removeDuplicates(path,
-                                                  allowedExts=allowedExts,
-                                                  fileGroups=fileGroups)
-                print('result:          ', result)
+                fslpath.removeDuplicates(path,
+                                         allowedExts=allowedExts,
+                                         fileGroups=fileGroups)
 
     finally:
         shutil.rmtree(workdir)
diff --git a/tests/test_idle.py b/tests/test_idle.py
index edf0ecb171b54fe382d233c5c69a49ae77b57f1c..6ceb010bb91aa36ce642d1b3034f5655d7bc58c8 100644
--- a/tests/test_idle.py
+++ b/tests/test_idle.py
@@ -9,11 +9,10 @@ import gc
 import time
 import threading
 import random
-
-from six.moves import reload_module
+import importlib
 
 import pytest
-import mock
+from unittest import mock
 
 import fsl.utils.idle as idle
 from fsl.utils.platform import platform as fslplatform
@@ -428,7 +427,7 @@ def test_idle_alwaysQueue4():
         with pytest.raises(ImportError):
             import wx
 
-    reload_module(fsl.utils.platform)
+    importlib.reload(fsl.utils.platform)
 
     assert called[0]
 
diff --git a/tests/test_image.py b/tests/test_image.py
index e2e7f213f0d7c791737c62ceb9eaa57a75f42344..34a5482ce8f63a7d66ed83d881f9a575680a55ab 100644
--- a/tests/test_image.py
+++ b/tests/test_image.py
@@ -32,11 +32,7 @@ from fsl.utils.tempdir import tempdir
 from . import make_random_image
 from . import make_dummy_file
 
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
+from unittest import mock
 
 try:
     import indexed_gzip as igzip
@@ -208,6 +204,23 @@ def test_create():
             assert np.all(np.isclose(img.pixdim, (2, 3, 4)))
 
 
+def test_name_dataSource():
+    with tempdir():
+
+        expName       = 'image'
+        expDataSource = op.abspath('image.nii.gz')
+        make_image('image.nii.gz')
+
+        tests = ['image', 'image.nii.gz', op.abspath('image'),
+                 op.abspath('image.nii.gz')]
+        tests = tests + [Path(t) for t in tests]
+
+        for t in tests:
+            i = fslimage.Image(t)
+            assert i.name       == expName
+            assert i.dataSource == expDataSource
+
+
 def test_bad_create():
 
     class BadThing(object):
diff --git a/tests/test_image_advanced.py b/tests/test_image_advanced.py
index fd7f64359d9bc071b33689ff95a8697170c247d0..1f1aed8a2ba827836314f61709e3a0316e41616f 100644
--- a/tests/test_image_advanced.py
+++ b/tests/test_image_advanced.py
@@ -7,8 +7,8 @@
 
 import os.path as op
 import            time
+from unittest import mock
 
-import mock
 import pytest
 
 import numpy   as np
diff --git a/tests/test_memoize.py b/tests/test_memoize.py
index 386674659b4a9af2648dadf445efd1a84a170f37..30844884d4695c040e82c11af2db7295118d1a17 100644
--- a/tests/test_memoize.py
+++ b/tests/test_memoize.py
@@ -6,7 +6,6 @@
 #
 
 import collections
-import six
 
 import numpy as np
 
@@ -44,7 +43,7 @@ def test_memoize():
         assert timesCalled[0] == 6
 
     # Unicode arg
-    s = six.u('\u25B2')
+    s = '\u25B2'
     assert memoized(s) == s * 5
     assert timesCalled[0] == 7
     assert memoized(s) == s * 5
@@ -146,7 +145,7 @@ def test_memoizeMD5():
         assert timesCalled[0] == 6
 
     # Unicode arg (and return value)
-    s = six.u('\u25B2')
+    s = '\u25B2'
     assert memoized(s) == s * 5
     assert timesCalled[0] == 7
     assert memoized(s) == s * 5
diff --git a/tests/test_platform.py b/tests/test_platform.py
index 9024bec8262658dd419c48ef288f2d4af2a75c8c..a38408175e438447570a75b9c0115e9da3f1d927 100644
--- a/tests/test_platform.py
+++ b/tests/test_platform.py
@@ -6,15 +6,14 @@
 #
 
 
-import            os
-import            gc
-import os.path as op
-import            sys
-import            shutil
-import            tempfile
-import            pytest
-
-import mock
+import               os
+import               gc
+import os.path    as op
+import               sys
+import               shutil
+import               tempfile
+import               pytest
+from unittest import mock
 
 
 import fsl.utils.platform as fslplatform
@@ -216,7 +215,7 @@ def test_detect_ssh():
 def test_fslwsl():
     """
     Note that ``Platform.fsldir`` requires the directory in ``FSLDIR`` to exist and
-    sets ``FSLDIR`` to ``None`` if it doesn't. So we create a ``Platform`` first 
+    sets ``FSLDIR`` to ``None`` if it doesn't. So we create a ``Platform`` first
     and then overwrite ``FSLDIR``. This is a bit of a hack but the logic we are testing
     here is whether ``Platform.fslwsl`` recognizes a WSL ``FSLDIR`` string
     """
diff --git a/tests/test_run.py b/tests/test_run.py
index 7308b849c72f6f82afd00eb417c4d479b58d0f30..287ccd6432c4d98223f23712dda1da2c1bf668c2 100644
--- a/tests/test_run.py
+++ b/tests/test_run.py
@@ -11,12 +11,8 @@ import            os
 import            shutil
 import            textwrap
 
-# python 3
-try:  from unittest import mock
-# python 2
-except ImportError: import mock
+from unittest import mock
 
-import six
 import pytest
 
 import fsl.utils.tempdir                  as tempdir
@@ -273,7 +269,7 @@ def test_runfsl():
 
 
 def mock_submit(cmd, **kwargs):
-    if isinstance(cmd, six.string_types):
+    if isinstance(cmd, str):
         name = cmd.split()[0]
     else:
         name = cmd[0]
diff --git a/tests/test_settings.py b/tests/test_settings.py
index b17b1b87ab8e7ed747d2c2d0dd56d4e13053737a..fc0ca9edf7f90c0f5051d09c8e30a59319aae6c4 100644
--- a/tests/test_settings.py
+++ b/tests/test_settings.py
@@ -12,12 +12,7 @@ import            pickle
 import            textwrap
 import            tempfile
 
-# python 3
-try:
-    import unittest.mock as mock
-# python 2
-except:
-    import mock
+import unittest.mock as mock
 
 import pytest
 
diff --git a/tests/test_transform/test_affine.py b/tests/test_transform/test_affine.py
index f1dceb61312c7f05f97c9d871dc8a4a0ae95f492..e686080fc7040983b61047ce207f8d0fcb1966b2 100644
--- a/tests/test_transform/test_affine.py
+++ b/tests/test_transform/test_affine.py
@@ -6,8 +6,6 @@
 #
 
 
-from __future__ import division
-
 import                 random
 import                 glob
 import os.path      as op
@@ -15,8 +13,6 @@ import itertools    as it
 import numpy        as np
 import numpy.linalg as npla
 
-import six
-
 import pytest
 
 import fsl.transform.affine  as affine
@@ -39,8 +35,7 @@ def readlines(filename):
         #
         # Pass it [bytes, bytes, ...], and it works
         # fine.
-        if six.PY3:
-            lines = [l.encode('ascii') for l in lines]
+        lines = [l.encode('ascii') for l in lines]
 
     return lines
 
diff --git a/tests/test_wrappers/test_wrapperutils.py b/tests/test_wrappers/test_wrapperutils.py
index 9bddb5c6b97e7ba6b9b78690c579fc3011aada81..f8a9d0dd4baa98f47003bf1846a92652f8e270bd 100644
--- a/tests/test_wrappers/test_wrapperutils.py
+++ b/tests/test_wrappers/test_wrapperutils.py
@@ -11,10 +11,8 @@ import            shlex
 import            pathlib
 import            textwrap
 
-try: from unittest import mock
-except ImportError: import mock
+from unittest import mock
 
-import six
 import pytest
 
 import numpy as np
@@ -317,7 +315,7 @@ def test_fileOrThing_sequence():
     @wutils.fileOrArray('arrs', 'out')
     def func(arrs, out):
 
-        if isinstance(arrs, six.string_types):
+        if isinstance(arrs, str):
             arrs = [arrs]
 
         arrs = [np.loadtxt(a) for a in arrs]