Skip to content
Snippets Groups Projects
Commit 0a0d3ae5 authored by Jan David Mol's avatar Jan David Mol
Browse files

Merge branch 'L2SS-291-abstract-class-hierarchy' into 'master'

L2SS-291: Separate abstract device class across files and test

Closes L2SS-291

See merge request !139
parents 4b0d8de8 c2e18c64
No related branches found
No related tags found
1 merge request!139L2SS-291: Separate abstract device class across files and test
# -*- coding: utf-8 -*-
#
# This file is part of the XXX project
#
#
#
# Distributed under the terms of the APACHE license.
# See LICENSE.txt for more info.
"""Abstract Device Meta for LOFAR2.0
"""
from abc import ABCMeta
import logging
from tango.server import DeviceMeta
logger = logging.getLogger()
class AbstractDeviceMetas(DeviceMeta, ABCMeta):
"""Collects meta classes to allow hardware_device to be both a Device and an ABC. """
def __new__(mcs, name, bases, namespace, **kwargs):
cls = ABCMeta.__new__(mcs, name, bases, namespace, **kwargs)
cls = DeviceMeta.__new__(type(cls), name, bases, namespace)
return cls
......@@ -20,18 +20,15 @@ from tango import DevState, DebugIt, Attribute, DeviceProxy
from clients.attribute_wrapper import attribute_wrapper
from common.lofar_logging import log_exceptions
import logging
from devices.abstract_device import AbstractDeviceMetas
from devices.device_decorators import only_in_states, fault_on_error
import logging
__all__ = ["hardware_device"]
from devices.device_decorators import only_in_states, fault_on_error
logger = logging.getLogger()
class AbstractDeviceMetas(DeviceMeta, ABCMeta):
''' Collects meta classes to allow hardware_device to be both a Device and an ABC. '''
pass
#@log_exceptions()
class hardware_device(Device, metaclass=AbstractDeviceMetas):
......
# -*- coding: utf-8 -*-
#
# This file is part of the LOFAR 2.0 Station Software
#
#
#
# Distributed under the terms of the APACHE license.
# See LICENSE.txt for more info.
import abc
from unittest import mock
from tango import DevFailed
from tango import server
from tango.server import attribute
from tango.test_context import DeviceTestContext
from devices.abstract_device import AbstractDeviceMetas
from test import base
class TestAbstractDevice(base.TestCase):
class AbstractExample(object, metaclass=abc.ABCMeta):
"""A pure abc.ABCMeta metaclass with an abstract method
This is an abstract class that inherits object with the abc.ABCMeta as
metaclass
"""
@abc.abstractmethod
def example_method(self):
raise NotImplementedError
class TestHardwareDevice(server.Device, metaclass=AbstractDeviceMetas):
"""This is your overarching abstract class with a combined metaclass
Device is an object with DeviceMeta as metaclass
We use HardwareDeviceMetas as metaclass
Our metaclass contract is now fulfilled.
"""
@attribute(dtype=float)
def call_example_method(self):
return self.example_method()
@abc.abstractmethod
def example_method(self):
raise NotImplementedError
class ConcreteHardwareDevice(TestHardwareDevice):
def example_method(self):
return 12
def setUp(self):
super(TestAbstractDevice, self).setUp()
def test_instance_tango(self):
try:
with DeviceTestContext(self.TestHardwareDevice, process=True) as proxy:
# Calling this method raises the NotImplementedError exception
proxy.call_example_method()
except Exception as e:
self.assertIsInstance(e, DevFailed)
with DeviceTestContext(self.ConcreteHardwareDevice, process=True) as proxy:
self.assertEqual(12, proxy.call_example_method)
@mock.patch.object(server, 'get_worker')
@mock.patch.object(server, 'LatestDeviceImpl')
def test_instance_error(self, m_worker, m_implement):
# Creating this object should raise a type error but it does not
# combining metaclasses in this way does not have the desired result.
# This is a known limitation of this approach
m_device = self.TestHardwareDevice(mock.Mock(), mock.Mock())
# Raising the NotImplementedError works as expected, however.
self.assertRaises(NotImplementedError, m_device.example_method)
# Creating this object of a class that has a pure metaclass does raise
# the expected error.
self.assertRaises(TypeError, self.AbstractExample)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment