Use built-in abc module
... to detect any missing interface implementation in subclasses. Change-Id: I8c9cae3e155c8c76ab1a2a1502f9b0bf6fbeb8fe
This commit is contained in:
parent
afabbf34c2
commit
96db0c2a0a
@ -12,9 +12,10 @@
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import abc
|
||||
|
||||
|
||||
class FileManager(object):
|
||||
class FileManager(object, metaclass=abc.ABCMeta):
|
||||
"""
|
||||
This class is used to load/save files required for storlet execution
|
||||
from/into the storage which also stores data to be processed
|
||||
@ -23,22 +24,25 @@ class FileManager(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_storlet(self, name):
|
||||
"""
|
||||
Load storlet file content
|
||||
|
||||
:param name: storlet file name
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_dependency(self, name):
|
||||
"""
|
||||
Load dependency file content
|
||||
|
||||
:param name: dependency file name
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def put_log(self, name, fobj):
|
||||
"""
|
||||
Save storlet log file to storage
|
||||
@ -46,4 +50,4 @@ class FileManager(object):
|
||||
:param name: log file name
|
||||
:param data_iter: File Object
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
pass
|
||||
|
@ -12,6 +12,7 @@
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import abc
|
||||
import copy
|
||||
import json
|
||||
|
||||
@ -47,14 +48,15 @@ class SBusFileDescriptor(object):
|
||||
return cls(fdtype, fileno, storlets_metadata, storage_metadata)
|
||||
|
||||
|
||||
class SBusDatagram(object):
|
||||
class SBusDatagram(object, metaclass=abc.ABCMeta):
|
||||
"""
|
||||
The manager class for the datagram passed over sbus protocol
|
||||
"""
|
||||
|
||||
# Each child Datagram should define what fd types are expected with
|
||||
# list format
|
||||
_required_fdtypes = None
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def _required_fdtypes(self):
|
||||
pass
|
||||
|
||||
def __init__(self, command, sfds, params=None, task_id=None):
|
||||
"""
|
||||
@ -67,9 +69,6 @@ class SBusDatagram(object):
|
||||
:param task_id: An optional string task id. This is currently used for
|
||||
cancel command
|
||||
"""
|
||||
if type(self) == SBusDatagram:
|
||||
raise NotImplementedError(
|
||||
'SBusDatagram class should not be initialized as bare')
|
||||
self.command = command
|
||||
fdtypes = [sfd.fdtype for sfd in sfds]
|
||||
self._check_required_fdtypes(fdtypes)
|
||||
@ -145,11 +144,6 @@ class SBusDatagram(object):
|
||||
return ret[0]
|
||||
|
||||
def _check_required_fdtypes(self, given_fdtypes):
|
||||
if self._required_fdtypes is None:
|
||||
raise NotImplementedError(
|
||||
'SBusDatagram class should define _required_fdtypes')
|
||||
# the first len(self._required_fdtypes) types should be fit
|
||||
# to the required list
|
||||
if given_fdtypes[:len(self._required_fdtypes)] != \
|
||||
self._required_fdtypes:
|
||||
raise ValueError('Fd type mismatch given_fdtypes:%s \
|
||||
@ -178,7 +172,9 @@ class SBusServiceDatagram(SBusDatagram):
|
||||
- SBUS_CMD_PING
|
||||
- SBUS_CMD_CANCEL
|
||||
"""
|
||||
_required_fdtypes = [sbus_fd.SBUS_FD_SERVICE_OUT]
|
||||
@property
|
||||
def _required_fdtypes(self):
|
||||
return [sbus_fd.SBUS_FD_SERVICE_OUT]
|
||||
|
||||
def __init__(self, command, sfds, params=None, task_id=None):
|
||||
super(SBusServiceDatagram, self).__init__(
|
||||
@ -190,11 +186,16 @@ class SBusServiceDatagram(SBusDatagram):
|
||||
|
||||
|
||||
class SBusExecuteDatagram(SBusDatagram):
|
||||
_required_fdtypes = [sbus_fd.SBUS_FD_SERVICE_OUT,
|
||||
sbus_fd.SBUS_FD_INPUT_OBJECT,
|
||||
sbus_fd.SBUS_FD_OUTPUT_OBJECT,
|
||||
sbus_fd.SBUS_FD_OUTPUT_OBJECT_METADATA,
|
||||
sbus_fd.SBUS_FD_LOGGER]
|
||||
|
||||
@property
|
||||
def _required_fdtypes(self):
|
||||
return [
|
||||
sbus_fd.SBUS_FD_SERVICE_OUT,
|
||||
sbus_fd.SBUS_FD_INPUT_OBJECT,
|
||||
sbus_fd.SBUS_FD_OUTPUT_OBJECT,
|
||||
sbus_fd.SBUS_FD_OUTPUT_OBJECT_METADATA,
|
||||
sbus_fd.SBUS_FD_LOGGER
|
||||
]
|
||||
|
||||
def __init__(self, command, sfds, params=None, task_id=None):
|
||||
# TODO(kota_): the args command is not used in ExecuteDatagram
|
||||
|
@ -16,7 +16,7 @@
|
||||
import json
|
||||
import unittest
|
||||
import storlets.sbus.file_description as sbus_fd
|
||||
from storlets.sbus.datagram import SBusFileDescriptor, SBusDatagram, \
|
||||
from storlets.sbus.datagram import SBusFileDescriptor, \
|
||||
SBusServiceDatagram, SBusExecuteDatagram, build_datagram, \
|
||||
build_datagram_from_raw_message
|
||||
from storlets.sbus.command import SBUS_CMD_PING, SBUS_CMD_EXECUTE
|
||||
@ -53,27 +53,6 @@ class TestSBusFileDescriptor(unittest.TestCase):
|
||||
fd.storage_metadata)
|
||||
|
||||
|
||||
class TestSBusDatagram(unittest.TestCase):
|
||||
def test_check_required_fdtypes_not_implemented(self):
|
||||
# SBusDatagram designed not to be called independently
|
||||
with self.assertRaises(NotImplementedError) as err:
|
||||
SBusDatagram('', [], [])
|
||||
self.assertEqual(
|
||||
'SBusDatagram class should not be initialized as bare',
|
||||
err.exception.args[0])
|
||||
|
||||
def test_invalid_child_class_definition(self):
|
||||
# no definition for _required_fdtypes
|
||||
class InvalidSBusDatagram(SBusDatagram):
|
||||
pass
|
||||
|
||||
with self.assertRaises(NotImplementedError) as err:
|
||||
InvalidSBusDatagram('', [], [])
|
||||
self.assertEqual(
|
||||
'SBusDatagram class should define _required_fdtypes',
|
||||
err.exception.args[0])
|
||||
|
||||
|
||||
class SBusDatagramTestMixin(object):
|
||||
def setUp(self):
|
||||
self.params = {'param1': 'paramvalue1'}
|
||||
|
Loading…
Reference in New Issue
Block a user