Source code for libsolace.plugin

__author__ = 'Kegan Holtzhausen <Kegan.Holtzhausen@unibet.com>'

"""
The plugin system
"""

import functools
import logging
from collections import OrderedDict

from libsolace.util import get_calling_module


[docs]class PluginClass(type): """This is a metaclass for construction only, see Plugin rather""" def __new__(cls, clsname, bases, dct): new_object = super(PluginClass, cls).__new__(cls, clsname, bases, dct) return new_object
[docs]class Plugin(object): """This is the plugin core object where all plugins should extend from and register too. Plugin Example: .. doctest:: :options: +SKIP >>> import pprint >>> import libsolace >>> from libsolace.plugin import Plugin >>> @libsolace.plugin_registry.register >>> class Bar(Plugin): >>> plugin_name = "BarPlugin" >>> def __init__(self): >>> pass >>> # Instance methods work! >>> def hello(self, name): >>> print("Hello %s from %s" % (name, self)) >>> # Static methods work too! >>> @staticmethod >>> def gbye(): >>> print("Cheers!") >>> libsolace.plugin_registry('BarPlugin').hello("dude") >>> libsolace.plugin_registry('BarPlugin').gbye() >>> pprint.pprint(dir(libsolace.plugin_registry('BarPlugin'))) Plugin Instantiation: >>> import libsolace.settingsloader as settings >>> from libsolace.SolaceAPI import SolaceAPI >>> api = SolaceAPI("dev") >>> my_plugin = api.manage("NullPlugin") >>> type(my_plugin) <class 'libsolace.items.NullPlugin.NullPlugin'> Direct Instantiation: >>> import libsolace.settingsloader as settings >>> import libsolace >>> my_clazz = libsolace.plugin_registry("NullPlugin", settings=settings) >>> my_instance = my_clazz(settings=settings) """ __metaclass__ = PluginClass plugins = [] plugins_dict = OrderedDict() plugin_name = "Plugin" """ the plugin's name, override this in the derived class!""" exists = False def __init__(self, *args, **kwargs): logging.debug("Plugin Init: %s, %s" % (args, kwargs))
[docs] def register(self, object_class, *args, **kwargs): """ Registers a object with the plugin registry, typically used as a decorator. :param object_class: the class to register as a plugin Example: .. doctest:: :options: +SKIP >>> @libsolace.plugin_registry.register >>> class Foo(Plugin) >>> ... """ logging.info("Registering Plugin id: %s from class: %s " % (object_class.plugin_name, object_class)) o = object_class self.plugins.append(o) self.plugins_dict[object_class.plugin_name] = o def _d(fn): logging.info("CALL CALL CALL CALL CALL CALL") return functools.update_wrapper(object_class(fn), fn) functools.update_wrapper(_d, object_class) return _d
def __call__(self, *args, **kwargs): """ When you call the registry with the name of a plugin eg: 'NullPlugin', as the first arg, this returns the class from the plugin_registry. You can then instantiate the class in any way you need to. Example >>> import libsolace >>> from libsolace.plugin import Plugin >>> a = libsolace.plugin_registry("NullPlugin") >>> type(a) "" :param args: name of Plugin to return :param kwargs: :return: class """ try: module = get_calling_module(point=2) except: module = "Unknown" try: module_parent = get_calling_module(point=3) except: module_parent = "Unknown" logging.debug(self.plugins_dict) logging.info("Module %s->%s->%s" % (module_parent, module, args[0])) logging.debug("Plugin Request: args: %s, kwargs: %s" % (args, kwargs)) try: logging.debug("Class: %s" % self.plugins_dict[args[0]]) return self.plugins_dict[args[0]] except: logging.warn("No plugin named: %s found, available plugins are: %s" % (args[0], self.plugins_dict)) logging.warn( "Please check the plugin is listed in the yaml config and that you have @libsolace.plugin_registry.register in the class") raise
[docs] def set_exists(self, state): """set_exists is used as caching in order to cut down on SEMP queries to validate existence of items. For example, if you create a new VPN in "batch" mode, After the "create-vpn" XML is generated, set_exists is set to True so subsequent requests decorated with the `only_if_exists` will function correctly since set_exists states that the object will exist. :param state: the existence state of the object :type state: bool :return: """ module = get_calling_module(point=3) logging.info("Calling module: %s, Setting Exists bit: %s" % (module, state)) self.exists = state
[docs]class PluginResponse(object): """ Encapsulating class for holding SEMP requests and their accompanying kwargs. Example: >>> request = PluginResponse('<rpc semp-version="soltr/7_1_1"><show><memory/></show></rpc>', primaryOnly=True) >>> request.xml '<rpc semp-version="soltr/7_1_1"><show><memory/></show></rpc>' """ def __init__(self, xml, **kwargs): self.xml = xml """ the XML """ self.kwargs = kwargs """ the kwargs """