From c77bb16369660d2cca6501d6f6d0c470663b7905 Mon Sep 17 00:00:00 2001 From: snijder <snijder@astron.nl> Date: Wed, 1 Feb 2023 17:04:24 +0100 Subject: [PATCH] worked on fixing the code --- Attribute_wrapper/__init__.py | 2 +- Attribute_wrapper/attribute_wrapper.py | 25 +++++++++++++------ Attribute_wrapper/cool_module.py | 6 ----- VERSION | 1 + requirements.txt | 4 ++- tests/test_attr_wrapper.py | 34 +++++++++++--------------- tests/test_client.py | 8 +++--- tox.ini | 9 ++++--- 8 files changed, 46 insertions(+), 43 deletions(-) delete mode 100644 Attribute_wrapper/cool_module.py create mode 100644 VERSION diff --git a/Attribute_wrapper/__init__.py b/Attribute_wrapper/__init__.py index a917d91..2787b16 100644 --- a/Attribute_wrapper/__init__.py +++ b/Attribute_wrapper/__init__.py @@ -5,4 +5,4 @@ try: except ImportError: # for Python<3.8 import importlib_metadata as metadata -__version__ = metadata.version("AttributeWrapper") +#__version__ = metadata.version("AttributeWrapper") diff --git a/Attribute_wrapper/attribute_wrapper.py b/Attribute_wrapper/attribute_wrapper.py index 4923c17..cbb0138 100644 --- a/Attribute_wrapper/attribute_wrapper.py +++ b/Attribute_wrapper/attribute_wrapper.py @@ -4,6 +4,7 @@ import logging from functools import reduce from operator import mul +from functools import wraps import numpy from tango import AttrWriteType, AttReqType @@ -13,6 +14,7 @@ logger = logging.getLogger() __all__ = ["AttributeWrapper"] + def fault_on_error(): """ Wrapper to catch exceptions. Sets the device in a FAULT state if any occurs. @@ -63,7 +65,8 @@ class AttributeIO(object): def cached_write_function(self, value): """Writes the given value to the device, and updates the cache.""" - # flexible array sizes are not supported by all clients. make sure we only write arrays of maximum size. + # flexible array sizes are not supported by all clients. make sure we only + # write arrays of maximum size. if self.attribute_wrapper.shape != (): if isinstance(value, numpy.ndarray): value_shape = value.shape @@ -117,14 +120,19 @@ class AttributeWrapper(attribute): f"Attribute needs to be a Tango-supported numpy, str or bool type, but has type {datatype}" ) - self.comms_id = comms_id # store data that can be used to identify the comms interface to use. not used by the wrapper itself - self.comms_annotation = comms_annotation # store data that can be used by the comms interface. not used by the wrapper itself + # store data that can be used to identify the comms interface to use. not + # used by the wrapper itself + self.comms_id = comms_id + # store data that can be used by the comms interface. not used by the + # wrapper itself + self.comms_annotation = comms_annotation self.datatype = datatype if dims == (1,): # scalar - # Tango defines a scalar as having dimensions (1,0), see https://pytango.readthedocs.io/en/stable/server_api/attribute.html + # Tango defines a scalar as having dimensions (1,0), see + # https://pytango.readthedocs.io/en/stable/server_api/attribute.html max_dim_x = 1 max_dim_y = 0 dtype = datatype @@ -181,7 +189,8 @@ class AttributeWrapper(attribute): read_func_wrapper reads the attribute value, stores it and returns it" """ - # lofar.read_attribute ignores fisallowed. So check again if we're allowed to read. + # lofar.read_attribute ignores fisallowed. So check again if we're + # allowed to read. if not device.is_attribute_access_allowed(AttReqType.READ_REQ): return None @@ -205,7 +214,8 @@ class AttributeWrapper(attribute): read_func_wrapper reads the attribute value, stores it and returns it" """ - # lofar.read_attribute ignores fisallowed. So check again if we're allowed to read. + # lofar.read_attribute ignores fisallowed. So check again if we're + # allowed to read. if not device.is_attribute_access_allowed(AttReqType.READ_REQ): return None @@ -225,7 +235,8 @@ class AttributeWrapper(attribute): # 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 - # So we have to use fisallowed=<str> here, which causes the function device.<str> to be called. + # So we have to use fisallowed=<str> here, which causes the function + # device.<str> to be called. super().__init__( dtype=dtype, max_dim_y=max_dim_y, diff --git a/Attribute_wrapper/cool_module.py b/Attribute_wrapper/cool_module.py deleted file mode 100644 index bd9416c..0000000 --- a/Attribute_wrapper/cool_module.py +++ /dev/null @@ -1,6 +0,0 @@ -""" Cool module containing functions, classes and other useful things """ - - -def greeter(): - """Prints a nice message""" - print("Hello World!") diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..49d5957 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.1 diff --git a/requirements.txt b/requirements.txt index 87f0831..ad16c92 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ numpy >= 1.20.0 # BSD -testtools>=2.2.0 # MIT \ No newline at end of file +stestr>=3.0.0 # Apache-2.0 +testscenarios>=0.5.0 # Apache-2.0/BSD +testtools>=2.4.0 # MIT \ No newline at end of file diff --git a/tests/test_attr_wrapper.py b/tests/test_attr_wrapper.py index 24d7988..97985b1 100644 --- a/tests/test_attr_wrapper.py +++ b/tests/test_attr_wrapper.py @@ -6,7 +6,7 @@ import asyncio -import mock +from unittest import mock import numpy # External imports @@ -15,11 +15,10 @@ from tango.server import attribute, command, Device, DeviceMeta # Test imports from tango.test_context import DeviceTestContext -import AttributeWrapper -from tangostationcontrol.test import base +from Attribute_wrapper.attribute_wrapper import AttributeWrapper # Internal imports -from test.test_client import TestClient +from test_client import TestClient SCALAR_DIMS = (1,) SPECTRUM_DIMS = (4,) @@ -37,11 +36,12 @@ def dev_init(device): asyncio.run(i.async_set_comm_client(device, device.test_client)) device.test_client.start() + class device_wrapper(Device, metaclass=DeviceMeta): @classmethod def attr_list(cls): """Return a list of all the AttributeWrapper members of this class.""" - return [v for k, v in cls.__dict__.items() if type(v) == AttributeWrapper] + return [v for k, v in cls.__dict__.items() if isinstance(v, AttributeWrapper)] def off(self): self.set_state(DevState.OFF) @@ -52,12 +52,11 @@ class device_wrapper(Device, metaclass=DeviceMeta): def initialise(self): self.set_state(DevState.INIT) -class TestAttributeTypes(base.TestCase): + +class TestAttributeTypes(): def setUp(self): # Avoid the device trying to access itself as a client - self.deviceproxy_patch = mock.patch.object( - Device, "DeviceProxy" - ) + self.deviceproxy_patch = mock.patch.object(device_wrapper, "DeviceProxy") self.deviceproxy_patch.start() self.addCleanup(self.deviceproxy_patch.stop) @@ -572,7 +571,6 @@ class TestAttributeTypes(base.TestCase): def read_R_test(self, dev, dtype, test_type): """Test device""" with DeviceTestContext(dev, process=True) as proxy: - # initialise proxy.initialise() proxy.on() @@ -589,7 +587,8 @@ class TestAttributeTypes(base.TestCase): proxy.image_R ) # is needed for STR since they act differently - # cant use all() for 2d arrays so instead compare the dimensions and then flatten to 2d + # cant use all() for 2d arrays so instead compare the dimensions and + # then flatten to 2d self.assertEqual( val.shape, expected.shape, @@ -632,13 +631,11 @@ class TestAttributeTypes(base.TestCase): def write_RW_test(self, dev, dtype, test_type): """Test device""" with DeviceTestContext(dev, process=True) as proxy: - # initialise proxy.initialise() proxy.on() if test_type == "scalar": - if dtype is str: val = STR_SCALAR_VAL else: @@ -678,7 +675,6 @@ class TestAttributeTypes(base.TestCase): try: with DeviceTestContext(dev, process=True) as proxy: - # initialise proxy.initialise() proxy.on() @@ -695,7 +691,8 @@ class TestAttributeTypes(base.TestCase): proxy.image_RW ) # is needed for STR since they act differently - # cant use all() for 2d arrays so instead compare the dimensions and then flatten to 2d + # cant use all() for 2d arrays so instead compare the dimensions and + # then flatten to 2d self.assertEqual( val.shape, expected.shape, @@ -792,7 +789,6 @@ class TestAttributeTypes(base.TestCase): """Test device""" try: with DeviceTestContext(dev, process=True) as proxy: - # initialise proxy.initialise() proxy.on() @@ -1029,12 +1025,10 @@ class TestAttributeTypes(base.TestCase): ) -class TestAttributeAccess(base.TestCase): +class TestAttributeAccess(): def setUp(self): # Avoid the device trying to access itself as a client - self.deviceproxy_patch = mock.patch.object( - Device, "DeviceProxy" - ) + self.deviceproxy_patch = mock.patch.object(Device, "DeviceProxy") self.deviceproxy_patch.start() self.addCleanup(self.deviceproxy_patch.stop) diff --git a/tests/test_client.py b/tests/test_client.py index 1b31de2..b1a0c98 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -6,13 +6,10 @@ import logging # External imports import numpy -# Test imports -from tangostationcontrol.clients.comms_client import CommClient - logger = logging.getLogger() -class TestClient(CommClient): +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. @@ -126,7 +123,8 @@ class TestClient(CommClient): # process the comms_annotation self._setup_annotation(annotation) - # get all the necessary data to set up the read/write functions from the AttributeWrapper + # get all the necessary data to set up the read/write functions from the + # AttributeWrapper dims, dtype = self._setup_value_conversion(attribute) # configure and return the read/write functions diff --git a/tox.ini b/tox.ini index d538894..10e61a9 100644 --- a/tox.ini +++ b/tox.ini @@ -14,6 +14,9 @@ setenv = deps = -r{toxinidir}/requirements.txt -r{toxinidir}/tests/requirements.txt +commands_pre = + {envpython} --version + pip install --no-cache pytango commands = {envpython} --version {envpython} -m pytest @@ -34,9 +37,9 @@ commands = black: {envpython} -m black --version black: {envpython} -m black --check --diff . pylint: {envpython} -m pylint --version - pylint: {envpython} -m pylint my_awesome_app tests - format: {envpython} -m autopep8 -v -aa --in-place --recursive my_awesome_app - format: {envpython} -m autopep8 -v -aa --in-place --recursive tests + pylint: {envpython} -m pylint AttributeWrapper tests + format: {envpython} -m autopep8 -v -aa --in-place --recursive Attribute_wrapper/ + format: {envpython} -m autopep8 -v -aa --in-place --recursive tests/ format: {envpython} -m black -v . -- GitLab