diff --git a/attribute_wrapper/attribute_wrapper.py b/attribute_wrapper/attribute_wrapper.py
index e1ae6d604e8cd84c0eb147a0bbd090e5dd3adebc..a1c6849cfbe08c1e565095ec05353eeaae8aaeef 100644
--- a/attribute_wrapper/attribute_wrapper.py
+++ b/attribute_wrapper/attribute_wrapper.py
@@ -80,7 +80,8 @@ class AttributeIO(object):
 
             if value_shape != self.attribute_wrapper.shape:
                 raise ValueError(
-                    f"Tried writing an array of shape {value_shape} into an attribute of shape {self.attribute_wrapper.shape}"
+                    f"Tried writing an array of shape {value_shape} into an attribute "
+                    f"of shape {self.attribute_wrapper.shape}"
                 )
 
         self.write_function(value)
@@ -88,9 +89,7 @@ class AttributeIO(object):
 
 
 class AttributeWrapper(attribute):
-    """
-    Wraps all the attributes in a wrapper class to manage most of the redundant code behind the scenes
-    """
+    """Wraps attribute to generate function creation"""
 
     def __init__(
         self,
@@ -102,22 +101,28 @@ class AttributeWrapper(attribute):
         **kwargs,
     ):
         """
-        wraps around the tango Attribute class. Provides an easier interface for 1d or 2d arrays. Also provides a way to abstract
-        managing the communications interface.
+        wraps around the tango Attribute class.
+
+        Provides an easier interface for 1d or 2d arrays. Also provides a way to
+        abstract managing the communications interface.
 
-        comms_id: user-supplied identifier that is attached to this object, to identify which communication class will need to be attached
-        comms_annotation: data passed along to the attribute. can be given any form of data. handling is up to client implementation
+        comms_id: user-supplied identifier that is attached to this object, to identify
+                  which communication class will need to be attached
+        comms_annotation: data passed along to the attribute. can be given any form of
+                          data. handling is up to client implementation
         datatype: any numpy datatype
         dims: dimensions of the attribute as a tuple, or (1,) for a scalar.
         init_value: value
         """
 
         # ensure the type is a numpy array.
-        # see also https://pytango.readthedocs.io/en/stable/server_api/server.html?highlight=devlong#module-tango.server for
-        # more details about type conversion Python/numpy -> PyTango
+        # see also
+        # https://pytango.readthedocs.io/en/stable/server_api/server.html?highlight=devlong#module-tango.server
+        # for more details about type conversion Python/numpy -> PyTango
         if "numpy" not in str(datatype) and datatype != str and datatype != bool:
             raise ValueError(
-                f"Attribute needs to be a Tango-supported numpy, str or bool type, but has type {datatype}"
+                f"Attribute needs to be a Tango-supported numpy, str or bool type, but "
+                f"has type {datatype}"
             )
 
         # store data that can be used to identify the comms interface to use. not
@@ -150,8 +155,8 @@ class AttributeWrapper(attribute):
             dtype = ((datatype,),)
             shape = (max_dim_y, max_dim_x)
         else:
-            # higher dimensional
-            # >2D arrays collapse into the X and Y dimensions. The Y (major) dimension mirrors the first dimension given, the
+            # higher dimensional, >2D arrays collapse into the X and Y dimensions.
+            # The Y (major) dimension mirrors the first dimension given, the
             # rest collapses into the X (minor) dimension.
             max_dim_x = reduce(mul, dims[1:])
             max_dim_y = dims[0]
@@ -162,7 +167,8 @@ class AttributeWrapper(attribute):
         self.shape = shape
 
         if access == AttrWriteType.READ_WRITE:
-            """If the attribute is of READ_WRITE type, assign the write and read functions to it"""
+            """If the attribute is of READ_WRITE type, assign the write and read
+            functions to it"""
 
             # we return the last written value, as we are the only ones in control,
             # and the hardware does not necessarily return what we've written
@@ -170,9 +176,7 @@ class AttributeWrapper(attribute):
 
             @fault_on_error()
             def write_func_wrapper(device, value):
-                """
-                write_func_wrapper writes a value to this attribute
-                """
+                """write_func_wrapper writes a value to this attribute"""
 
                 try:
                     io = self.get_attribute_io(device)
@@ -230,11 +234,14 @@ class AttributeWrapper(attribute):
 
             self.fget = read_func_wrapper
 
-        # "fisallowed" is called to ask us whether an attribute can be accessed. If not, the attribute won't be accessed,
-        # and the cache not updated. This forces Tango to also force a read the moment an attribute does become accessible.
-        # The provided function will be used with the call signature "(device: Device, req_type: AttReqType) -> bool".
+        # "fisallowed" is called to ask us whether an attribute can be accessed. If not,
+        # the attribute won't be accessed, and the cache not updated. This forces Tango
+        # to also force a read the moment an attribute does become accessible.
+        # The provided function will be used with the call signature:
+        #   "(device: Device, req_type: AttReqType) -> bool".
         #
-        # NOTE: fisallowed=<callable> does not work: https://gitlab.com/tango-controls/pytango/-/issues/435
+        # NOTE: fisallowed=<callable> does not work:
+        # https://gitlab.com/tango-controls/pytango/-/issues/435
         # So we have to use fisallowed=<str> here, which causes the function
         # device.<str> to be called.
         super().__init__(
@@ -248,8 +255,7 @@ class AttributeWrapper(attribute):
         )
 
     def get_attribute_io(self, device):
-        """returns the attribute I/O functions from a certain device, or registers it if not present
-        """
+        """Returns the attribute I/O functions from device"""
 
         try:
             return device._attribute_wrapper_io[self]
@@ -258,9 +264,11 @@ class AttributeWrapper(attribute):
             return device._attribute_wrapper_io[self]
 
     def set_comm_client(self, device, client):
-        """
-        takes a communications client as input arguments This client should be of a class containing a "get_mapping" function
-        and return a read and write function that the wrapper will use to get/set data.
+        """Takes communication client with 'get_mapping' function
+
+        takes a communications client as input arguments This client should be of a
+        class containing a "get_mapping" function and return a read and write function
+        that the wrapper will use to get/set data.
         """
         try:
             read_attr_func, write_attr_func = client.setup_attribute(
@@ -272,13 +280,12 @@ class AttributeWrapper(attribute):
             io.write_function = write_attr_func
         except Exception as e:
             raise Exception(
-                f"Exception while setting {client.__class__.__name__} attribute with annotation: '{self.comms_annotation}'"
+                f"Exception while setting {client.__class__.__name__} attribute with "
+                f"annotation: '{self.comms_annotation}'"
             ) from e
 
     async def async_set_comm_client(self, device, client):
-        """
-        Asynchronous version of set_comm_client.
-        """
+        """Asynchronous version of set_comm_client."""
         try:
             read_attr_func, write_attr_func = await client.setup_attribute(
                 self.comms_annotation, self
@@ -289,7 +296,8 @@ class AttributeWrapper(attribute):
             io.write_function = write_attr_func
         except Exception as e:
             raise Exception(
-                f"Exception while setting {client.__class__.__name__} attribute with annotation: '{self.comms_annotation}'"
+                f"Exception while setting {client.__class__.__name__} attribute with "
+                f"annotation: '{self.comms_annotation}'"
             ) from e
 
     def set_pass_func(self, device):
diff --git a/attribute_wrapper/interface.py b/attribute_wrapper/interface.py
index 90174f6a6cf702e16fd349a18bba0a0649a0078b..b27b928a1286e33230dd27e211a0f4840a77233b 100644
--- a/attribute_wrapper/interface.py
+++ b/attribute_wrapper/interface.py
@@ -7,8 +7,8 @@ logger = logging.getLogger()
 
 __all__ = ["AttributeWrapperInterface"]
 
-class AttributeWrapperInterface:
 
+class AttributeWrapperInterface:
     def __init__(self):
         """prepare the caches for attribute wrapper objects"""
         self._attribute_wrapper_io = {}
diff --git a/tests/test_attr_wrapper.py b/tests/test_attr_wrapper.py
index 57e532fdb4f5a61cc32e13654ab0459006636880..7e55be4e675f2e88253ace4aaa024ce979bb0ffd 100644
--- a/tests/test_attr_wrapper.py
+++ b/tests/test_attr_wrapper.py
@@ -12,15 +12,14 @@ from unittest import TestCase
 import testscenarios
 
 # External imports
-from tango import DevState, DevFailed, AttrWriteType, DeviceProxy
-from tango.server import attribute, command, Device, DeviceMeta
+from tango import DevState, DevFailed, AttrWriteType
+from tango.server import command, Device, DeviceMeta
 
 # Test imports
 from tango.test_context import DeviceTestContext
 
 # Internal imports
 from attribute_wrapper.attribute_wrapper import AttributeWrapper
-from attribute_wrapper.interface import AttributeWrapperInterface
 from attribute_wrapper.states import INITIALISED_STATES
 from test_client import TestClient
 
@@ -42,7 +41,6 @@ STR_IMAGE_VAL = [["1", "1"], ["1", "1"], ["1", "1"]]
 
 
 class DeviceWrapper(Device, metaclass=DeviceMeta):
-
     def __init__(self, cl, name):
         super().__init__(cl, name)
 
@@ -514,7 +512,7 @@ class TestAttributeTypes(testscenarios.WithScenarios, unittest.TestCase):
                 self.assertEqual(
                     val.shape,
                     expected.shape,
-                    " image R array dimensions got mangled. Expected {}, got  {}".format(
+                    "image R array dimensions got mangled. Expected {}, got {}".format(
                         expected.shape, val.shape
                     ),
                 )
@@ -523,27 +521,24 @@ class TestAttributeTypes(testscenarios.WithScenarios, unittest.TestCase):
                 self.assertEqual(
                     1,
                     2,
-                    " {} is not a valid test_type. please use either scalar, spectrum or image".format(
-                        test_type
-                    ),
+                    "{} is not a valid test_type. please use either scalar,"
+                    "spectrum or image".format(test_type),
                 )
 
             if test_type == "scalar":
                 comparison = expected == val
                 self.assertTrue(
                     comparison,
-                    " Value could not be read or was not what was expected. Expected: {}, got {}".format(
-                        expected, val
-                    ),
+                    "Value could not be read or was not what was expected. Expected:"
+                    "{}, got {}".format(expected, val),
                 )
             else:
                 comparison = expected == val
                 equal_arrays = comparison.all()
                 self.assertTrue(
                     equal_arrays,
-                    " Value could not be read or was not what was expected. Expected: {}, got {}".format(
-                        expected, val
-                    ),
+                    " Value could not be read or was not what was expected. Expected:"
+                    "{}, got {}".format(expected, val),
                 )
 
             print(
@@ -581,16 +576,10 @@ class TestAttributeTypes(testscenarios.WithScenarios, unittest.TestCase):
                 self.assertEqual(
                     1,
                     2,
-                    " {} is not a valid test_type. please use either scalar, spectrum or image".format(
-                        test_type
-                    ),
+                    " {} is not a valid test_type. please use either scalar,"
+                    "spectrum or image".format(test_type),
                 )
 
-            # can't really test anything here except that the writing didnt cause an error.
-            # reading back happens in readback_test
-
-            print(" Test passed! Managed to write: ".format(val))
-
     def read_RW_test(self, dev, dtype, test_type):
         """Test device"""
         expected = None
@@ -619,18 +608,16 @@ class TestAttributeTypes(testscenarios.WithScenarios, unittest.TestCase):
                     self.assertEqual(
                         val.shape,
                         expected.shape,
-                        " image R array dimensions got mangled. Expected {}, got  {}".format(
-                            expected.shape, val.shape
-                        ),
+                        "image R array dimensions got mangled. Expected {},"
+                        "got {}".format(expected.shape, val.shape),
                     )
                     val.reshape(-1)
                 else:
                     self.assertEqual(
                         1,
                         2,
-                        " {} is not a valid test_type. please use either scalar, spectrum or image".format(
-                            test_type
-                        ),
+                        " {} is not a valid test_type. please use either scalar,"
+                        "spectrum or image".format(test_type),
                     )
 
                 if test_type != "scalar":
@@ -639,13 +626,15 @@ class TestAttributeTypes(testscenarios.WithScenarios, unittest.TestCase):
                     equal_arrays = comparison.all()
                     self.assertTrue(
                         equal_arrays,
-                        " Value could not be handled by the atrribute_wrappers internal RW storer",
+                        "Value could not be handled by the atrribute_wrappers internal"
+                        "RW storer",
                     )
                 else:
                     comparison = expected == val
                     self.assertTrue(
                         comparison,
-                        " Value could not be handled by the atrribute_wrappers internal RW storer",
+                        "Value could not be handled by the atrribute_wrappers internal"
+                        "RW storer",
                     )
 
                 print(
@@ -701,9 +690,8 @@ class TestAttributeTypes(testscenarios.WithScenarios, unittest.TestCase):
             self.assertEqual(
                 1,
                 2,
-                " {} is not a valid test_type. please use either scalar, spectrum or image".format(
-                    test_type
-                ),
+                "{} is not a valid test_type. please use either scalar,"
+                "spectrum or image".format(test_type),
             )
 
         return result_R, result_RW, val
@@ -725,47 +713,45 @@ class TestAttributeTypes(testscenarios.WithScenarios, unittest.TestCase):
                     comparison = result_RW == val
                     self.assertTrue(
                         comparison,
-                        " Value could not be handled by the atrribute_wrappers internal RW storer. attempted to write: {}".format(
-                            val
-                        ),
+                        "Value could not be handled by the atrribute_wrappers internal "
+                        "RW storer. attempted to write: {}".format(val),
                     )
                     comparison = result_R == val
                     self.assertTrue(
                         comparison,
-                        " value in the clients R attribute not equal to what was written. read: {}, wrote {}".format(
-                            result_R, val
-                        ),
+                        "value in the clients R attribute not equal to what was"
+                        "written. read: {}, wrote {}".format(result_R, val),
                     )
                 elif dtype != str:
                     comparison = result_RW == val
                     equal_arrays = comparison.all()
                     self.assertTrue(
                         equal_arrays,
-                        " Value could not be handled by the atrribute_wrappers internal RW storer. attempted to write: {}".format(
-                            val
-                        ),
+                        "Value could not be handled by the atrribute_wrappers internal "
+                        "RW storer. attempted to write: {}".format(val),
                     )
                     comparison = result_R == val
                     equal_arrays = comparison.all()
                     self.assertTrue(
                         equal_arrays,
-                        " value in the clients R attribute not equal to what was written. read: {}, wrote {}".format(
-                            result_R, val
-                        ),
+                        "value in the clients R attribute not equal to what was "
+                        "written. read: {}, wrote {}".format(result_R, val),
                     )
                 else:
                     if test_type == "image":
                         self.assertEqual(
                             len(result_RW) * len(result_RW[0]),
                             6,
-                            "array dimensions do not match the expected dimensions. expected {}, got: {}".format(
+                            "array dimensions do not match the expected dimensions."
+                            "expected {}, got: {}".format(
                                 val, len(result_RW) * len(result_RW[0])
                             ),
                         )
                         self.assertEqual(
                             len(result_RW) * len(result_RW[0]),
                             6,
-                            "array dimensions do not match the expected dimensions. expected {}, got: {}".format(
+                            "array dimensions do not match the expected dimensions."
+                            "expected {}, got: {}".format(
                                 val, len(result_R) * len([0])
                             ),
                         )
@@ -773,16 +759,14 @@ class TestAttributeTypes(testscenarios.WithScenarios, unittest.TestCase):
                         self.assertEqual(
                             len(result_RW),
                             4,
-                            "array dimensions do not match the expected dimensions. expected {}, got: {}".format(
-                                4, len(result_RW)
-                            ),
+                            "array dimensions do not match the expected dimensions."
+                            "expected {}, got: {}".format(4, len(result_RW)),
                         )
                         self.assertEqual(
                             len(result_R),
                             4,
-                            "array dimensions do not match the expected dimensions. expected {}, got: {}".format(
-                                4, len(result_R)
-                            ),
+                            "array dimensions do not match the expected dimensions."
+                            "expected {}, got: {}".format(4, len(result_R)),
                         )
 
                 print(
@@ -790,9 +774,10 @@ class TestAttributeTypes(testscenarios.WithScenarios, unittest.TestCase):
                 )
 
         except Exception as e:
-            info = "Test failure in {} {} readback test  \n\tW: {} \n\tRW: {} \n\tR: {}".format(
-                test_type, dtype, val, result_RW, result_R
-            )
+            info = {
+                f"Test failure in {test_type} {dtype} readback test "
+                f"\n\tW: {val} \n\tRW: {result_RW} \n\tR: {result_R}"
+            }
             raise Exception(info) from e
 
     """
diff --git a/tests/test_client.py b/tests/test_client.py
index 790d3b3758b8bb86f816f9056ed271d6655920e5..a5a7b6ac42ad5e4b2b03678085227bad1adbef90 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -10,9 +10,10 @@ logger = logging.getLogger()
 
 
 class TestClient:
-    """
-    this class provides an example implementation of a comms_client.
-    During initialisation it creates a correctly shaped zero filled value. on read that value is returned and on write its modified.
+    """Example comms_client implementation
+
+    During initialisation it creates a correctly shaped zero filled value. on read that
+    value is returned and on write its modified.
     """
 
     def start(self):
@@ -37,9 +38,7 @@ class TestClient:
         self.connect()
 
     def connect(self):
-        """
-        this function provides a location for the code neccecary to connect to the client
-        """
+        """Connect to client"""
         self.connected = True  # set connected to true
 
     def disconnect(self):
@@ -49,12 +48,14 @@ class TestClient:
         logger.debug("disconnected from the 'client' ")
 
     def _setup_annotation(self, annotation):
-        """
-        this function gives the client access to the comm client annotation data given to the attribute wrapper.
-        The annotation data can be used to provide whatever extra data is necessary in order to find/access the monitor/control point.
+        """Provide additional data to monitor/control point
 
-        the annotation can be in whatever format may be required. it is up to the user to handle its content
-        example annotation may include:
+        this function gives the client access to the comm client annotation data given
+        to the attribute wrapper. The annotation data can be used to provide whatever
+        extra data is necessary in order to find/access the monitor/control point.
+
+        the annotation can be in whatever format may be required. it is up to the user
+        to handle its content, example annotations may include:
         - a file path and file line/location
         - server address
         - IDs
@@ -80,12 +81,10 @@ class TestClient:
         return dims, dtype
 
     def _setup_mapping(self, annotation, dims, dtype):
-        """
-        takes all gathered data to configure and return the correct read and write functions
-        """
+        """Take gathered data to configure and return read and write functions"""
 
-        # we emulate that values written to annotations ending in _RW show up in their corresponding _R
-        # point as well
+        # we emulate that values written to annotations ending in _RW show up in their
+        # corresponding _R point as well
         if annotation.endswith("_RW"):
             annotation = annotation[:-1]
 
@@ -114,14 +113,16 @@ class TestClient:
             self.values[annotation] = write_value
 
         logger.debug(
-            "created and bound example_client read/write functions to AttributeWrapper object"
+            "created and bound example_client read/write functions to AttributeWrapper "
+            "object"
         )
         return read_function, write_function
 
     async def setup_attribute(self, annotation=None, attribute=None):
-        """
-        MANDATORY function: is used by the attribute wrapper to get read/write functions.
-        must return the read and write functions
+        """Return tuple with read and write functions
+
+        MANDATORY function: is used by the attribute wrapper to get read/write
+        functions. must return the read and write functions
         """
 
         # process the comms_annotation