summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Sivak <msivak@redhat.com>2008-01-02 10:54:03 +0100
committerMartin Sivak <msivak@redhat.com>2008-01-02 10:54:03 +0100
commit2a4335b0c2e5e071190afe24d24e5ea99c7553b5 (patch)
tree29f88afd281ae48e2ede4e428f0c92b387353bd5
parent5b1aab4ce3ceaf7075f620083078eaa32b59d7df (diff)
downloadfirstaidkit-2a4335b0c2e5e071190afe24d24e5ea99c7553b5.tar.gz
firstaidkit-2a4335b0c2e5e071190afe24d24e5ea99c7553b5.tar.xz
firstaidkit-2a4335b0c2e5e071190afe24d24e5ea99c7553b5.zip
Add dependency system into plugins. Use the require/provide model to control it.
-rw-r--r--tasker/interpret.py39
-rw-r--r--tasker/plugins.py34
2 files changed, 61 insertions, 12 deletions
diff --git a/tasker/interpret.py b/tasker/interpret.py
index b7a2339..7bd0061 100644
--- a/tasker/interpret.py
+++ b/tasker/interpret.py
@@ -17,15 +17,31 @@
from log import Logger
from plugins import PluginSystem
-from reporting import Reports
+from reporting import Reports, TASKER
+import logging
+import copy
+
+class RunDependencies(object):
+ """Encapsulate flags used to control the dependencies between plugins"""
+ def __init__(self):
+ self._provide = set()
+
+ def provide(self, id):
+ """Add flag"""
+ self._provide.add(id)
+
+ def require(self, id):
+ """Return True if flag is present, otherwise false"""
+ return id in self._provide
class Tasker:
"""The main interpret of tasks described in Config object"""
def __init__(self, cfg):
+ self._provide = RunDependencies()
self._config = cfg
self._reporting = Reports()
- self.pluginSystem = PluginSystem(reporting = self._reporting)
+ self.pluginSystem = PluginSystem(reporting = self._reporting, dependencies = self._provide)
def reporting(self):
return self._reporting
@@ -41,12 +57,23 @@ class Tasker:
pluginSystem = self.pluginSystem
if self._config.operation.mode == "auto":
- for plugin in pluginSystem.list():
- pluginSystem.autorun(plugin)
+ oldlist = set()
+ actlist = set(pluginSystem.list())
+ #iterate through plugins until there is no plugin left or no action performed during whole iteration
+ while len(actlist)>0 and oldlist!=actlist:
+ oldlist = copy.copy(actlist)
+ for plugin in oldlist:
+ if pluginSystem.autorun(plugin): #False when dependencies are not met
+ actlist.remove(plugin)
+ for plugin in aclist:
+ self._reporting.info("Plugin %s was not called because of unsatisfied dependencies" % (plugin,), origin = TASKER, importance = logging.WARNING)
elif self._config.operation.mode == "flow":
- pluginSystem.autorun(self._config.operation.plugin, flow = self._config.operation.flow)
+ try:
+ pluginSystem.autorun(self._config.operation.plugin, flow = self._config.operation.flow, dependencies = False)
+ except InvalidFlowNameException, e:
+ pass
elif self._config.operation.mode == "plugin":
- pluginSystem.autorun(self._config.operation.plugin)
+ pluginSystem.autorun(self._config.operation.plugin, dependencies = False)
elif self._config.operation.mode == "task":
pass
else:
diff --git a/tasker/plugins.py b/tasker/plugins.py
index 251cc43..53d8c79 100644
--- a/tasker/plugins.py
+++ b/tasker/plugins.py
@@ -79,11 +79,12 @@ class Plugin(object):
"clean" : {ReturnValueTrue: final}
}, description="The default, fully automated, fixing sequence")
- def __init__(self, flow, reporting):
+ def __init__(self, flow, reporting, dependencies):
""" Initialize the instance.
flow -- Name of the flow to be used with this instance.
reporting -- object used to report information to the user
+ dependencies -- object encapsulating the inter-plugin dependency API (require, provide)
The flow is defined in the __init__ so we don't have to worry about changing it.
"""
@@ -137,6 +138,11 @@ class Plugin(object):
raise InvalidFlowNameException(flow)
@classmethod
+ def getDeps(cls):
+ """Return list of conditions required to be set before automated run can be done"""
+ return set()
+
+ @classmethod
def getFlows(cls):
"""Return a set with the names of all possible flows."""
fatherf = Plugin._defflows.keys()
@@ -253,9 +259,10 @@ class Plugin(object):
class PluginSystem(object):
"""Encapsulate all plugin detection and import stuff"""
- def __init__(self, reporting, config = Config):
+ def __init__(self, reporting, dependencies, config = Config):
self._path = Config.plugin.path
self._reporting = reporting
+ self._deps = dependencies
self._plugins = {}
#create list of potential modules in the path
@@ -293,11 +300,16 @@ class PluginSystem(object):
"""Return the list of imported plugins"""
return self._plugins.keys()
- def autorun(self, plugin, flow = None):
- """Perform automated run of plugin"""
+ def autorun(self, plugin, flow = None, dependencies = True):
+ """Perform automated run of plugin with condition checking
+returns - True if conditions are fully satisfied
+ False if there is something missing
+ exception when some other error happens"""
+
pklass = self._plugins[plugin].get_plugin() #get top level class of plugin
Logger.info("Plugin information...")
Logger.info("name:%s , version:%s , author:%s " % pklass.info())
+
flows = pklass.getFlows()
Logger.info("Provided flows : %s " % flows)
if flow==None:
@@ -308,13 +320,23 @@ class PluginSystem(object):
Logger.info("Using %s flow" % flowName)
if flowName not in flows:
Logger.error("Flow %s does not exist in plugin %s", flowName, plugin)
- return
+ raise InvalidFlowNameException(d)
+
+ if dependencies:
+ deps = pklass.getDeps()
+ Logger.info("depends on: %s" % (", ".join(deps),))
+ for d in deps:
+ if not self._deps.require(d):
+ Logger.info("depends on usatisfied condition: %s" % (d,))
+ return False
- p = pklass(flowName, reporting = self._reporting)
+ p = pklass(flowName, reporting = self._reporting, dependencies = self._deps)
for (step, rv) in p: #autorun all the needed steps
Logger.info("Running step %s in plugin %s ...", step, plugin)
Logger.info("%s is current step and %s is result of that step." % (step, rv))
+ return True
+
def getplugin(self, plugin):
"""Get instance of plugin, so we can call the steps manually"""
return self._plugins[plugin].get_plugin()