]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Deepak/Vinkesh | Added an base abstract class which can be inherited by PluginInterfa...
authorDeepak N <deepak.n@thoughtworks.com>
Tue, 19 Jul 2011 05:55:31 +0000 (11:25 +0530)
committerDeepak N <deepak.n@thoughtworks.com>
Tue, 19 Jul 2011 05:55:31 +0000 (11:25 +0530)
quantum/common/extensions.py
tests/unit/test_extensions.py

index 1d9d38bbb827c64f1305483464badba6bc88ce8b..5d24a3d816cd1ed47e116c226ec444efc093109c 100644 (file)
@@ -23,15 +23,36 @@ import routes
 import logging
 import webob.dec
 import webob.exc
+from gettext import gettext as _
+from abc import ABCMeta, abstractmethod
 
 from quantum.manager import QuantumManager
 from quantum.common import exceptions
 from quantum.common import wsgi
-from gettext import gettext as _
 
 LOG = logging.getLogger('quantum.common.extensions')
 
 
+class PluginInterface(object):
+    __metaclass__ = ABCMeta
+
+    @classmethod
+    def __subclasshook__(cls, klass):
+        """
+        The __subclasshook__ method is a class method
+        that will be called everytime 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.
+        """
+        for method in cls.__abstractmethods__:
+            if any(method in base.__dict__ for base in klass.__mro__):
+                continue
+            return NotImplemented
+        return True
+
+
 class ExtensionDescriptor(object):
     """Base class that defines the contract for extensions.
 
@@ -108,6 +129,14 @@ class ExtensionDescriptor(object):
         request_exts = []
         return request_exts
 
+    def get_plugin_interface(self):
+        """
+        Returns an abstract class which defines contract for the plugin.
+        The abstract class should inherit from extesnions.PluginInterface,
+        Methods in this abstract class  should be decorated as abstractmethod
+        """
+        return None
+
 
 class ActionExtensionController(wsgi.Controller):
 
@@ -363,13 +392,10 @@ class ExtensionManager(object):
                 self.plugin.supports_extension(extension))
 
     def _plugin_implements_interface(self, extension):
-        if not hasattr(extension, "get_plugin_interface"):
+        if(not hasattr(extension, "get_plugin_interface") or
+           extension.get_plugin_interface() is None):
             return True
-        interface = extension.get_plugin_interface()
-        expected_methods = self._get_public_methods(interface)
-        implemented_methods = self._get_public_methods(self.plugin.__class__)
-        missing_methods = set(expected_methods) - set(implemented_methods)
-        return not missing_methods
+        return isinstance(self.plugin, extension.get_plugin_interface())
 
     def _get_public_methods(self, klass):
         return filter(lambda name: not(name.startswith("_")),
index 591a494169660d3fbed953fd144b6c79c46f7c6a..4472d2377a43b750680ccdeea17eea44c8d92b8a 100644 (file)
@@ -18,6 +18,7 @@ import unittest
 import routes
 import os.path
 from tests.unit import BaseTest
+from abc import  abstractmethod
 
 from webtest import TestApp
 from quantum.common import extensions
@@ -104,15 +105,16 @@ class StubPlugin(object):
 class ExtensionExpectingPluginInterface(StubExtension):
     """
     This extension expects plugin to implement all the methods defined
-    in PluginInterface
+    in StubPluginInterface
     """
 
     def get_plugin_interface(self):
-        return PluginInterface
+        return StubPluginInterface
 
 
-class PluginInterface(object):
+class StubPluginInterface(extensions.PluginInterface):
 
+    @abstractmethod
     def get_foo(self, bar=None):
         pass
 
@@ -207,6 +209,20 @@ class ExtensionManagerTest(unittest.TestCase):
 
         self.assertTrue("e1" in self.ext_mgr.extensions)
 
+    def test_extensions_without_need_for__plugin_interface_are_loaded(self):
+        class ExtensionWithNoNeedForPluginInterface(StubExtension):
+            """
+            This Extension does not need any plugin interface.
+            This will work with any plugin implementing QuantumPluginBase
+            """
+            def get_plugin_interface(self):
+                return None
+
+        self.ext_mgr.plugin = StubPlugin(supported_extensions=["e1"])
+        self.ext_mgr.add_extension(ExtensionWithNoNeedForPluginInterface("e1"))
+
+        self.assertTrue("e1" in self.ext_mgr.extensions)
+
 
 class ActionExtensionTest(unittest.TestCase):