Merge "Formalize base service classes"
This commit is contained in:
@@ -106,7 +106,8 @@ class ExtensionDescriptor(object):
|
||||
def get_plugin_interface(self):
|
||||
"""Returns an abstract class which defines contract for the plugin.
|
||||
|
||||
The abstract class should inherit from extensions.PluginInterface,
|
||||
The abstract class should inherit from
|
||||
neutron_lib.services.base.ServicePluginBase.
|
||||
Methods in this abstract class should be decorated as abstractmethod
|
||||
"""
|
||||
|
||||
|
@@ -15,32 +15,7 @@ import abc
|
||||
import six
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class _PluginInterface(object):
|
||||
|
||||
@classmethod
|
||||
def __subclasshook__(cls, klass):
|
||||
"""Checking plugin class.
|
||||
|
||||
The __subclasshook__ method is a class method
|
||||
that will be called every time a class is tested
|
||||
using issubclass(klass, _PluginInterface).
|
||||
In that case, it will check that every method
|
||||
marked with the abstractmethod decorator is
|
||||
provided by the plugin class.
|
||||
"""
|
||||
|
||||
if not cls.__abstractmethods__:
|
||||
return NotImplemented
|
||||
|
||||
for method in cls.__abstractmethods__:
|
||||
if any(method in base.__dict__ for base in klass.__mro__):
|
||||
continue
|
||||
return NotImplemented
|
||||
return True
|
||||
|
||||
|
||||
class _WorkerSupportServiceMixin(object):
|
||||
class WorkerBase(object):
|
||||
|
||||
@property
|
||||
def _workers(self):
|
||||
@@ -74,11 +49,31 @@ class _WorkerSupportServiceMixin(object):
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class ServicePluginBase(_PluginInterface,
|
||||
_WorkerSupportServiceMixin):
|
||||
class ServicePluginBase(WorkerBase):
|
||||
"""Define base interface for any Advanced Service plugin."""
|
||||
supported_extension_aliases = []
|
||||
|
||||
@classmethod
|
||||
def __subclasshook__(cls, klass):
|
||||
"""Checking plugin class.
|
||||
|
||||
The __subclasshook__ method is a class method
|
||||
that will be called every time a class is tested
|
||||
using issubclass(klass, ServicePluginBase).
|
||||
In that case, it will check that every method
|
||||
marked with the abstractmethod decorator is
|
||||
provided by the plugin class.
|
||||
"""
|
||||
|
||||
if not cls.__abstractmethods__:
|
||||
return NotImplemented
|
||||
|
||||
for method in cls.__abstractmethods__:
|
||||
if any(method in base.__dict__ for base in klass.__mro__):
|
||||
continue
|
||||
return NotImplemented
|
||||
return True
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_plugin_type(self):
|
||||
"""Return one of predefined service types.
|
||||
|
@@ -16,7 +16,7 @@ from neutron_lib.services import base
|
||||
from neutron_lib.tests import _base as test_base
|
||||
|
||||
|
||||
class _Worker(base._WorkerSupportServiceMixin):
|
||||
class _Worker(base.WorkerBase):
|
||||
pass
|
||||
|
||||
|
||||
@@ -43,14 +43,21 @@ class Test_WorkerSupportServiceMixin(test_base.BaseTestCase):
|
||||
self.assertSequenceEqual(workers, self.worker.get_workers())
|
||||
|
||||
|
||||
class Test_PluginInterface(test_base.BaseTestCase):
|
||||
class TestPluginInterface(test_base.BaseTestCase):
|
||||
|
||||
class ServicePluginStub(base.ServicePluginBase):
|
||||
def get_plugin_type(self):
|
||||
pass
|
||||
|
||||
def get_plugin_description(self):
|
||||
pass
|
||||
|
||||
def test_issubclass_hook(self):
|
||||
class A(object):
|
||||
class A(TestPluginInterface.ServicePluginStub):
|
||||
def f(self):
|
||||
pass
|
||||
|
||||
class B(base._PluginInterface):
|
||||
class B(base.ServicePluginBase):
|
||||
@abc.abstractmethod
|
||||
def f(self):
|
||||
pass
|
||||
@@ -62,18 +69,18 @@ class Test_PluginInterface(test_base.BaseTestCase):
|
||||
def f(self):
|
||||
pass
|
||||
|
||||
class B(base._PluginInterface):
|
||||
class B(base.ServicePluginBase):
|
||||
def f(self):
|
||||
pass
|
||||
|
||||
self.assertFalse(issubclass(A, B))
|
||||
|
||||
def test_issubclass_hook_not_all_methods_implemented(self):
|
||||
class A(object):
|
||||
class A(TestPluginInterface.ServicePluginStub):
|
||||
def f(self):
|
||||
pass
|
||||
|
||||
class B(base._PluginInterface):
|
||||
class B(base.ServicePluginBase):
|
||||
@abc.abstractmethod
|
||||
def f(self):
|
||||
pass
|
||||
|
@@ -0,0 +1,10 @@
|
||||
---
|
||||
features:
|
||||
- The ``neutron_lib.api.extensions.ExtensionDescriptor`` class's
|
||||
``get_plugin_interface`` method now formally only supports
|
||||
``neutron_lib.services.base.ServicePluginBase``. This change reflects
|
||||
the existing usage by consumers as almost all are returning
|
||||
instances of ``ServicePluginBase`` already.
|
||||
- The class ``WorkerBase`` is now available and provides the same
|
||||
functionality that's provided by
|
||||
``neutron.worker.WorkerSupportServiceMixin``.
|
Reference in New Issue
Block a user