Source code for octo.manager
import octo
import octo.exceptions
import signal
import logging
from yapsy.PluginManager import PluginManager
try:
import configparser
except ImportError:
import ConfigParser as configparser # Python 2
[docs]def exit_handler(signal, frame):
"""Called by `run` upon receiving SIGINT"""
logging.info("Interrupt received, shutting down")
octo.manager.stop()
[docs]def run(plugin_dirs=[], block=False):
"""
Runs the ``octo`` application.
Calling this function will initialize the `Manager` class and make it
available as `octo.instance` so that plugins may import and interact with
it.
If block=True, this function will block until a SIGINT is received, either
by the user hitting Ctrl+C or another process sending a SIGINT signal. If
block=False then applications must ensure to call stop() appropriately
themselves.
"""
if octo.instance is not None:
raise octo.exceptions.AlreadyStartedError("main() can only be called once")
octo.instance = Manager(plugin_dirs=plugin_dirs)
octo.instance.start()
if block:
signal.signal(signal.SIGINT, exit_handler)
signal.pause()
[docs]def stop():
"""
Stops the ``octo`` application.
Calling this function will stop and cleanup `octo.instance`
"""
if octo.instance is None:
raise octo.exceptions.NotStartedError("Octo does not seem to be started")
octo.instance.stop()
octo.instance = None
[docs]class Manager(object):
"""
This is the main ``octo`` application class.
Normally, you would call `octo.main` instead of creating an instance of this
class directly, as `octo.main` will make it available globally as `octo.instance`
so plugins may interact with it.
"""
def __init__(self, plugin_dirs=[]):
logging.info("Initializing with plugin directories: {!r}".format(plugin_dirs))
self.plugin_manager = PluginManager(directories_list=plugin_dirs, plugin_info_ext='plugin')
self.plugin_manager.collectPlugins()
[docs] def get_plugins(self, include_inactive=False):
"""
Return a dictionary of loaded plugins
Keys will consist of plugin names, with their values being the plugin
instances (yapsy.PluginInfo.PluginInfo objects).
When ``include_inactive`` is True, all collected plugins will be
returned, otherwise only the activated plugins will be returned.
"""
if include_inactive:
plugins = self.plugin_manager.getAllPlugins()
else:
plugins = [plugin for plugin in self.plugin_manager.getAllPlugins()
if hasattr(plugin, 'is_activated') and plugin.is_activated]
return dict(zip([plugin.name for plugin in plugins], plugins))
[docs] def activate_plugin(self, plugin_name):
"""
Activate the given plugin
plugin_name should be the name of the plugin to be activated.
"""
self.plugin_manager.activatePluginByName(plugin_name)
[docs] def deactivate_plugin(self, plugin_name):
"""
Deactivate the given plugin
plugin_name should be the name of the plugin to be deactivated.
"""
self.plugin_manager.deactivatePluginByName(plugin_name)
[docs] def call(self, plugin_name, func, args=[], kwargs={}):
"""
Call the given function on the given plugin object (specifed by plugin name)
"""
for plugin in self.get_plugins().values():
if plugin.name == plugin_name:
return getattr(plugin.plugin_object, func)(*args, **kwargs)
raise octo.exceptions.NoSuchPluginError("The specified plugin isn't active or doesn't exist")
[docs] def call_many(self, func, args=[], kwargs={}):
"""
Call the given function on all active plugins and return results as a dictionary
The returned dictionary will have the form of {'plugin name': <function_result>}
"""
results = {}
for plugin in self.get_plugins().values():
try:
logging.debug("Calling {} on plugin '{}'".format(func, plugin.name))
results[plugin.name] = getattr(plugin.plugin_object, func)(*args, **kwargs)
except AttributeError as e:
logging.debug("'{}' has no attribute {}".format(plugin.name, func))
except Exception as e:
logging.exception("Exception while calling '{}' on '{}'".format(func, plugin.name))
results[plugin.name] = e
return results
[docs] def start(self):
"""Start and activate collected plugins
A plugin will be activated when it has a config item 'Enable'
under the section 'Config' with a value of True"""
logging.debug("Activating plugins")
for plugin in self.get_plugins(include_inactive=True).values():
try:
should_activate = plugin.details.getboolean('Config', 'Enable')
except configparser.NoSectionError:
should_activate = False
if should_activate:
logging.debug("Activating plugin {}".format(plugin.name))
self.activate_plugin(plugin.name)
else:
logging.debug("Plugin {} not activated because config item Enable "
"is not True".format(plugin.name))
logging.debug("Plugin activation done")
return self
[docs] def stop(self):
"""Stop and deactivate loaded plugins"""
logging.debug("Deactivating plugins")
for plugin in self.get_plugins().values():
logging.debug("Deactivating plugin {}".format(plugin.name))
self.deactivate_plugin(plugin.name)
logging.debug("Plugin deactivation done")
return self