Merge "Formalize base service classes"

This commit is contained in:
Jenkins
2017-03-07 21:54:58 +00:00
committed by Gerrit Code Review
4 changed files with 49 additions and 36 deletions

View File

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

View File

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

View File

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

View File

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