Use built-in abc module

... to detect any missing interface implementation in subclasses.

Change-Id: I8c9cae3e155c8c76ab1a2a1502f9b0bf6fbeb8fe
This commit is contained in:
Takashi Kajinami 2024-09-25 12:13:22 +09:00
parent afabbf34c2
commit 96db0c2a0a
3 changed files with 28 additions and 44 deletions

View File

@ -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

View File

@ -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

View File

@ -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'}