Skip to content
Snippets Groups Projects
Commit c77bb163 authored by Taya Snijder's avatar Taya Snijder
Browse files

worked on fixing the code

parent d6af35f7
Branches
Tags
No related merge requests found
Pipeline #43447 failed
...@@ -5,4 +5,4 @@ try: ...@@ -5,4 +5,4 @@ try:
except ImportError: # for Python<3.8 except ImportError: # for Python<3.8
import importlib_metadata as metadata import importlib_metadata as metadata
__version__ = metadata.version("AttributeWrapper") #__version__ = metadata.version("AttributeWrapper")
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import logging import logging
from functools import reduce from functools import reduce
from operator import mul from operator import mul
from functools import wraps
import numpy import numpy
from tango import AttrWriteType, AttReqType from tango import AttrWriteType, AttReqType
...@@ -13,6 +14,7 @@ logger = logging.getLogger() ...@@ -13,6 +14,7 @@ logger = logging.getLogger()
__all__ = ["AttributeWrapper"] __all__ = ["AttributeWrapper"]
def fault_on_error(): def fault_on_error():
""" """
Wrapper to catch exceptions. Sets the device in a FAULT state if any occurs. Wrapper to catch exceptions. Sets the device in a FAULT state if any occurs.
...@@ -63,7 +65,8 @@ class AttributeIO(object): ...@@ -63,7 +65,8 @@ class AttributeIO(object):
def cached_write_function(self, value): def cached_write_function(self, value):
"""Writes the given value to the device, and updates the cache.""" """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 self.attribute_wrapper.shape != ():
if isinstance(value, numpy.ndarray): if isinstance(value, numpy.ndarray):
value_shape = value.shape value_shape = value.shape
...@@ -117,14 +120,19 @@ class AttributeWrapper(attribute): ...@@ -117,14 +120,19 @@ class AttributeWrapper(attribute):
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 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 # store data that can be used to identify the comms interface to use. not
self.comms_annotation = comms_annotation # store data that can be used by the comms interface. not used by the wrapper itself # 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 self.datatype = datatype
if dims == (1,): if dims == (1,):
# scalar # 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_x = 1
max_dim_y = 0 max_dim_y = 0
dtype = datatype dtype = datatype
...@@ -181,7 +189,8 @@ class AttributeWrapper(attribute): ...@@ -181,7 +189,8 @@ class AttributeWrapper(attribute):
read_func_wrapper reads the attribute value, stores it and returns it" 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): if not device.is_attribute_access_allowed(AttReqType.READ_REQ):
return None return None
...@@ -205,7 +214,8 @@ class AttributeWrapper(attribute): ...@@ -205,7 +214,8 @@ class AttributeWrapper(attribute):
read_func_wrapper reads the attribute value, stores it and returns it" 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): if not device.is_attribute_access_allowed(AttReqType.READ_REQ):
return None return None
...@@ -225,7 +235,8 @@ class AttributeWrapper(attribute): ...@@ -225,7 +235,8 @@ class AttributeWrapper(attribute):
# The provided function will be used with the call signature "(device: Device, req_type: AttReqType) -> bool". # 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. # So we have to use fisallowed=<str> here, which causes the function
# device.<str> to be called.
super().__init__( super().__init__(
dtype=dtype, dtype=dtype,
max_dim_y=max_dim_y, max_dim_y=max_dim_y,
......
""" Cool module containing functions, classes and other useful things """
def greeter():
"""Prints a nice message"""
print("Hello World!")
0.1
numpy >= 1.20.0 # BSD numpy >= 1.20.0 # BSD
testtools>=2.2.0 # MIT stestr>=3.0.0 # Apache-2.0
\ No newline at end of file testscenarios>=0.5.0 # Apache-2.0/BSD
testtools>=2.4.0 # MIT
\ No newline at end of file
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
import asyncio import asyncio
import mock from unittest import mock
import numpy import numpy
# External imports # External imports
...@@ -15,11 +15,10 @@ from tango.server import attribute, command, Device, DeviceMeta ...@@ -15,11 +15,10 @@ from tango.server import attribute, command, Device, DeviceMeta
# Test imports # Test imports
from tango.test_context import DeviceTestContext from tango.test_context import DeviceTestContext
import AttributeWrapper from Attribute_wrapper.attribute_wrapper import AttributeWrapper
from tangostationcontrol.test import base
# Internal imports # Internal imports
from test.test_client import TestClient from test_client import TestClient
SCALAR_DIMS = (1,) SCALAR_DIMS = (1,)
SPECTRUM_DIMS = (4,) SPECTRUM_DIMS = (4,)
...@@ -37,11 +36,12 @@ def dev_init(device): ...@@ -37,11 +36,12 @@ def dev_init(device):
asyncio.run(i.async_set_comm_client(device, device.test_client)) asyncio.run(i.async_set_comm_client(device, device.test_client))
device.test_client.start() device.test_client.start()
class device_wrapper(Device, metaclass=DeviceMeta): class device_wrapper(Device, metaclass=DeviceMeta):
@classmethod @classmethod
def attr_list(cls): def attr_list(cls):
"""Return a list of all the AttributeWrapper members of this class.""" """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): def off(self):
self.set_state(DevState.OFF) self.set_state(DevState.OFF)
...@@ -52,12 +52,11 @@ class device_wrapper(Device, metaclass=DeviceMeta): ...@@ -52,12 +52,11 @@ class device_wrapper(Device, metaclass=DeviceMeta):
def initialise(self): def initialise(self):
self.set_state(DevState.INIT) self.set_state(DevState.INIT)
class TestAttributeTypes(base.TestCase):
class TestAttributeTypes():
def setUp(self): def setUp(self):
# Avoid the device trying to access itself as a client # Avoid the device trying to access itself as a client
self.deviceproxy_patch = mock.patch.object( self.deviceproxy_patch = mock.patch.object(device_wrapper, "DeviceProxy")
Device, "DeviceProxy"
)
self.deviceproxy_patch.start() self.deviceproxy_patch.start()
self.addCleanup(self.deviceproxy_patch.stop) self.addCleanup(self.deviceproxy_patch.stop)
...@@ -572,7 +571,6 @@ class TestAttributeTypes(base.TestCase): ...@@ -572,7 +571,6 @@ class TestAttributeTypes(base.TestCase):
def read_R_test(self, dev, dtype, test_type): def read_R_test(self, dev, dtype, test_type):
"""Test device""" """Test device"""
with DeviceTestContext(dev, process=True) as proxy: with DeviceTestContext(dev, process=True) as proxy:
# initialise # initialise
proxy.initialise() proxy.initialise()
proxy.on() proxy.on()
...@@ -589,7 +587,8 @@ class TestAttributeTypes(base.TestCase): ...@@ -589,7 +587,8 @@ class TestAttributeTypes(base.TestCase):
proxy.image_R proxy.image_R
) # is needed for STR since they act differently ) # 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( self.assertEqual(
val.shape, val.shape,
expected.shape, expected.shape,
...@@ -632,13 +631,11 @@ class TestAttributeTypes(base.TestCase): ...@@ -632,13 +631,11 @@ class TestAttributeTypes(base.TestCase):
def write_RW_test(self, dev, dtype, test_type): def write_RW_test(self, dev, dtype, test_type):
"""Test device""" """Test device"""
with DeviceTestContext(dev, process=True) as proxy: with DeviceTestContext(dev, process=True) as proxy:
# initialise # initialise
proxy.initialise() proxy.initialise()
proxy.on() proxy.on()
if test_type == "scalar": if test_type == "scalar":
if dtype is str: if dtype is str:
val = STR_SCALAR_VAL val = STR_SCALAR_VAL
else: else:
...@@ -678,7 +675,6 @@ class TestAttributeTypes(base.TestCase): ...@@ -678,7 +675,6 @@ class TestAttributeTypes(base.TestCase):
try: try:
with DeviceTestContext(dev, process=True) as proxy: with DeviceTestContext(dev, process=True) as proxy:
# initialise # initialise
proxy.initialise() proxy.initialise()
proxy.on() proxy.on()
...@@ -695,7 +691,8 @@ class TestAttributeTypes(base.TestCase): ...@@ -695,7 +691,8 @@ class TestAttributeTypes(base.TestCase):
proxy.image_RW proxy.image_RW
) # is needed for STR since they act differently ) # 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( self.assertEqual(
val.shape, val.shape,
expected.shape, expected.shape,
...@@ -792,7 +789,6 @@ class TestAttributeTypes(base.TestCase): ...@@ -792,7 +789,6 @@ class TestAttributeTypes(base.TestCase):
"""Test device""" """Test device"""
try: try:
with DeviceTestContext(dev, process=True) as proxy: with DeviceTestContext(dev, process=True) as proxy:
# initialise # initialise
proxy.initialise() proxy.initialise()
proxy.on() proxy.on()
...@@ -1029,12 +1025,10 @@ class TestAttributeTypes(base.TestCase): ...@@ -1029,12 +1025,10 @@ class TestAttributeTypes(base.TestCase):
) )
class TestAttributeAccess(base.TestCase): class TestAttributeAccess():
def setUp(self): def setUp(self):
# Avoid the device trying to access itself as a client # Avoid the device trying to access itself as a client
self.deviceproxy_patch = mock.patch.object( self.deviceproxy_patch = mock.patch.object(Device, "DeviceProxy")
Device, "DeviceProxy"
)
self.deviceproxy_patch.start() self.deviceproxy_patch.start()
self.addCleanup(self.deviceproxy_patch.stop) self.addCleanup(self.deviceproxy_patch.stop)
......
...@@ -6,13 +6,10 @@ import logging ...@@ -6,13 +6,10 @@ import logging
# External imports # External imports
import numpy import numpy
# Test imports
from tangostationcontrol.clients.comms_client import CommClient
logger = logging.getLogger() logger = logging.getLogger()
class TestClient(CommClient): class TestClient:
""" """
this class provides an example implementation of a comms_client. 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. 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): ...@@ -126,7 +123,8 @@ class TestClient(CommClient):
# process the comms_annotation # process the comms_annotation
self._setup_annotation(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) dims, dtype = self._setup_value_conversion(attribute)
# configure and return the read/write functions # configure and return the read/write functions
......
...@@ -14,6 +14,9 @@ setenv = ...@@ -14,6 +14,9 @@ setenv =
deps = deps =
-r{toxinidir}/requirements.txt -r{toxinidir}/requirements.txt
-r{toxinidir}/tests/requirements.txt -r{toxinidir}/tests/requirements.txt
commands_pre =
{envpython} --version
pip install --no-cache pytango
commands = commands =
{envpython} --version {envpython} --version
{envpython} -m pytest {envpython} -m pytest
...@@ -34,9 +37,9 @@ commands = ...@@ -34,9 +37,9 @@ commands =
black: {envpython} -m black --version black: {envpython} -m black --version
black: {envpython} -m black --check --diff . black: {envpython} -m black --check --diff .
pylint: {envpython} -m pylint --version pylint: {envpython} -m pylint --version
pylint: {envpython} -m pylint my_awesome_app tests pylint: {envpython} -m pylint AttributeWrapper tests
format: {envpython} -m autopep8 -v -aa --in-place --recursive my_awesome_app format: {envpython} -m autopep8 -v -aa --in-place --recursive Attribute_wrapper/
format: {envpython} -m autopep8 -v -aa --in-place --recursive tests format: {envpython} -m autopep8 -v -aa --in-place --recursive tests/
format: {envpython} -m black -v . format: {envpython} -m black -v .
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment