The scenario is as follows:
I'm building a framework that will use external scripts as plugins. People will be able to create "adapters" to the scripts that conform to some interface. These adapters will be used either integrated into the framework (thus plugin registration is required) or "loosely" by a simple import.
In other words, the adapters are meant for script usage standardization.
I might be thinking too complex but the solution I'm currently on involves creating an abstract class defining the interface (and some utility methods). The module of the abstract class will be loaded only once and the framework will be loading a version with a self registering metaclass while the plugin itself will load a simpler version (The first one registering the abstract class wins).
This forces the plugin to have a file that defines the abstract class and therefore the "contract". I don't see a problem with that.
I'm not really going to have two different abstract classes but a single one in a module file that behaves differently depending from where it gets loaded (framework or plugin itself). But that shouldn't be relevant (I think).
So this is how the abstract class / metaclass looks like
#imp/plugin.py
import abc
class PluginAbstract(object):
class __metaclass__(abc.ABCMeta):
def __init__(self, name, bases, namespace):
if name != 'PluginAbstract':
pass #We can register the new "sub-class" if required
return abc.ABCMeta.__init__(abc.ABCMeta, name, bases, namespace)
And the implementation would be something like:
#impl/MyPlugin.py
if 'plugin' not in locals():
from impl import plugin
class MyPlugin(plugin.PluginAbstract):
pass #rest of the implementation....
So if the framework already registered PluginAbstract
that one would be inherited, if not the one from the contract file impl/plugin.py
will be used.
I don't want the adapters to require the framework to be installed, therefore the single file with the interface.
Does this strategy makes sense? Are there other options?