Skip to content

Commit

Permalink
refactoring of commands callbacks. Implemented "moa run -r" [#4 state…
Browse files Browse the repository at this point in the history
…:resolved]
  • Loading branch information
mfiers committed Apr 6, 2011
1 parent a5f7792 commit aafec65
Show file tree
Hide file tree
Showing 21 changed files with 302 additions and 256 deletions.
186 changes: 108 additions & 78 deletions bin/moa
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import moa.project
import moa.plugin
import moa.commands

#the system configuration is available as a global from the
#sysConf module
from moa.sysConf import sysConf

## Initialize the logger
Expand All @@ -49,35 +51,25 @@ if '-v' in sys.argv:
## Initialze the plugins
plugins = moa.plugin.PluginHandler(sysConf)


### Determine project root (if there is one)
#projectRoot = moa.project.findProjectRoot(job)
#if projectRoot:
# l.debug('Project root is %s' % projectRoot)
# job.projectRoot = projectRoot
# plugins.register(projectRoot = projectRoot)

## Command definitions
moaCommands = moa.commands.Commands()
plugins.register(commands = moaCommands)
sysConf.commands = moa.commands.Commands()
plugins.run('defineCommands')


## start defining the command line interface
## defining a usage message
USAGE = "Usage: {{bold}}{{green}}%prog {{blue}}[options] COMMAND ARGUMENTS{{reset}}\n\n"
moaCommandNames = moaCommands.keys()
moaCommandNames = sysConf.commands.keys()
moaCommandNames.sort()

commandsG = []
commandsJ = []

for _c in moaCommandNames:
if moaCommands[_c].get('private', False):
if sysConf.commands[_c].get('private', False):
continue
if moaCommands[_c].get('needsJob', True):
commandsJ.append([_c, moaCommands[_c]['desc']])
if sysConf.commands[_c].get('needsJob', True):
commandsJ.append([_c, sysConf.commands[_c]['desc']])
else:
commandsG.append([_c, moaCommands[_c]['desc']])
commandsG.append([_c, sysConf.commands[_c]['desc']])

commandsG.sort()
commandsJ.sort()
Expand Down Expand Up @@ -120,15 +112,42 @@ parser.add_option(
parser.add_option("-r", "--recursive", dest="recursive",
help="Perfom action recursively", action='store_true')

## See if the plugins have anything to add to the optparse instance:
sysConf.parser = parser
plugins.run('defineOptions')

def run2(job, command):

if command in sysConf.commands:
if not sysConf.commands[command].has_key('call'):
moa.ui.exitError("Invalid command - no callback %s" % command)

l.debug("using a callback for moa %s" % command)
try:
plugins.runCallback(job, command)
rc = 0
except:
#this should not happen!!
rc = -1
sysConf.rc = rc
raise

return rc

#No callback, defer this to the backend
rc = job.execute(command,
verbose = options.verbose,
silent = options.silent)

return rc

def run(job, command):

## Ask the job if it's is ok with
## the command provided (might want to change order, or insert
## stuff

execList = job.checkCommands(command)
plugins.register(executeCommand=execList)

sysConf.executeCommand = execList

l.debug("Run moa commands: %s" % ",".join(execList))
l.debug("with args %s" % newargs)
Expand All @@ -149,74 +168,38 @@ def run(job, command):
l.debug("Executing %s" % execNow)
plugins.run("pre%s" % execNow.capitalize())

if execNow in moaCommands:
if moaCommands[execNow].has_key('call'):
l.debug("using a callback for moa %s" % execNow)
try:
plugins.runCallback(moaCommands[execNow])
rc = 0
except:
rc = -1
plugins.register(rc = rc)
raise
else:
#No callback, defer this to the backend

#first see if we need to fork - if this is a background job
if options.background:
options.silent = True
child = os.fork()
if child != 0:
# This is the parent thread - exit now - all
plugins.register(childPid = child)
plugins.run("bgParentExit")
moa.ui.fprint("Running in the background")
sys.exit(0)

rc = job.execute(
execNow,
verbose = options.verbose,
silent = options.silent)

plugins.register(rc = rc)
plugins.run("post%s" % execNow.capitalize())
rc = run2(job, execNow)

if command not in execList:
plugins.run("post%s" % command.capitalize())
sysConf.rc = rc
plugins.run("post%s" % execNow.capitalize(), reverse=True)

plugins.run("postCommand")
if command not in execList:
plugins.run("post%s" % command.capitalize(), reverse=True)

plugins.run("finish")
sys.exit(rc)
plugins.run("postCommand", reverse=True)
plugins.run("finish", reverse=True)
return rc

## Main dispatcher
if __name__ == "__main__":
try:
wd = os.getcwd()

plugins.register(sysConf = sysConf)
plugins.register(wd = wd)
plugins.register(cwd = wd)

## See if the plugins have anything to add to the optparse instance:
plugins.register(parser=parser)
plugins.register(commands=moaCommands)
plugins.run('defineOptions')
#sysConf.wd = wd
#sysConf.cwd = wd #deprecated...

job = moa.job.Job(wd)
job.sysConf = sysConf

## Aks the job & backend if they want to add to the options
job.defineOptions(parser)
plugins.register(job = job)


## Parse the options
(options, args) = parser.parse_args()

## make sure that the options are accessible to the plugins
plugins.register(options = options, args = args)

#job.options = options
#job.args = args
sysConf.options = options
sysConf.args = args
sysConf.job = job

## Proper setting of verbosity - after parsing of the command line
if options.verbose:
Expand All @@ -230,16 +213,63 @@ if __name__ == "__main__":
command = 'status'
newargs

plugins.register(newargs = newargs)
#job.args = newargs
sysConf.newargs = newargs
sysConf.originalCommand = command
moa.version.fixOld(wd)

plugins.register(originalCommand=command)
#first see if we need to fork - if this is a background job
if options.background:
options.silent = True
child = os.fork()
if child != 0:
# This is the parent thread - exit now - all
sysConf.childPid = child
plugins.run("bgParentExit")
moa.ui.fprint("starting background run")
sys.exit(0)


def _recursiveRun(job, command):
#turn of recursive - no recursively run recursive jobs
sysConf.options.recursive = False
rc = 0
for path, dirs, files in os.walk(job.wd):
if '.moa' in dirs:
rjob = moa.job.Job(path)
moa.ui.fprint("Executing 'moa %s' in %s" % (
command, path))
rc += abs(run(rjob, command))

#remove all '.' directories -
drem = [ x for x in dirs if x[0] == '.' ]
[ dirs.remove(t) for t in drem]
return rc


if sysConf.options.recursive:
if command in sysConf.commands:
rcmode = sysConf.commands[command].get('recursive', 'none')
if rcmode == 'local':
#local recursive mode - recursive operation
#is implemented at the command level
run(job, command)
elif rcmode == 'none':
moa.ui.exitError("Cannot run recursive run 'moa %s'")
else:
moa.ui.fprint("Start recursive 'moa %s'" % command,
f='jinja')
rc = _recursiveRun(job, command)
else:
#not command in sysConf.commands - it is not a callback
#but will be deferred to the backend -
#always recusively:
rc = _recursiveRun(job, command)
else:
#non recursive - just run the command
rc = run(job, command)

moa.version.fixOld(wd)
run(job, command)

except KeyboardInterrupt:
plugins.register(rc = -1)
sysConf.rc = -1
plugins.run("postInterrupt")
moa.ui.warn("Interrupted")
sys.exit(-1)
6 changes: 5 additions & 1 deletion bin/moainit
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ function _moa_prompt_2 {
stopseq=`date -d "${tstop}" +%s`
tdiff=$(($stopseq - $startseq))
pstart=`echo ${tstart} | sed "s/\.[^\.]*$//" | sed "s/T/ /" `
minute_secs=60 hour_secs=$((60 * minute_secs)) day_secs=$((24 * hour_secs))

minute_secs=60
hour_secs=$((60 * minute_secs))
day_secs=$((24 * hour_secs))

# parse
days=$((tdiff / day_secs))
hours=$((tdiff % day_secs / hour_secs))
Expand Down
4 changes: 1 addition & 3 deletions etc/config
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ plugins:
- help
- status
- template
- prompt
- pack
- info
- extraCommands
- parameterCheck
- moautil
- extraCommands
mancommand: "nroff -c -mandoc 2>/dev/null | less -is"
pandocbin: pandoc
use_ansi: True
5 changes: 4 additions & 1 deletion lib/python/moa/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
import moa.template
import moa.jobConf

from moa.sysConf import sysConf


def newJob(wd, template, title, parameters=[]):
"""
Create a new job in the wd and return the proper job object
Expand All @@ -43,7 +46,7 @@ def newJob(wd, template, title, parameters=[]):
:rtype: instance of :class:`moa.job.Job`
"""

job = Job(wd)
job.setTemplate(template)
job.conf.title = title
Expand Down
29 changes: 13 additions & 16 deletions lib/python/moa/plugin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,11 @@ def __init__(self, sysConf):
"""
## Determine what plugins are loaded
self.sysConf = sysConf
plugins = sysConf.getPlugins()
self.pluginList = sysConf.getPlugins()
self.plugins = {}
self.sysConf.plugins = self
self.allPlugins = plugins

l.debug("Plugins %s" % ", ".join(self.allPlugins))
l.debug("Plugins %s" % ", ".join(self.pluginList))
## load the plugins as seperate modules. A plugin does not need to
self.initialize()

Expand All @@ -42,7 +41,7 @@ def initialize(self):
"""
## do we have a python module??
l.debug('Start plugin init')
for plugin in self.allPlugins:
for plugin in self.pluginList:
pyModule = 'moa.plugin.%s' % plugin
try:
_m = __import__( pyModule, globals(), locals(), ['git'], -1)
Expand All @@ -52,12 +51,6 @@ def initialize(self):
if not str(e) == "No module named %s" % plugin:
raise
#l.debug("No python plugin module found for %s" % plugin)

newOrder = []
for plugin in self.keys():
newOrder.append((getattr(self[plugin], 'order', 100), plugin))
newOrder.sort()
self.allPlugins = [x[1] for x in newOrder]

def register(self, **kwargs):
"""
Expand All @@ -68,27 +61,31 @@ def register(self, **kwargs):
for k in kwargs:
self.sysConf[k] = kwargs[k]

def run(self, command):
def run(self, command, reverse=False):
rv = {}
for p in self.allPlugins:
toRun = self.pluginList
if reverse:
toRun.reverse()
for p in toRun:
if not command in dir(self[p]):
continue
l.debug("plugin executing hook %s for %s" % (command, p))
rv['p'] = getattr(self[p], command)(self.sysConf)
return rv

def runCallback(self, command):
def runCallback(self, job, command):
"""
Run a plugin callback
Run a command callback
"""
command['call'](self.sysConf)
commandInfo = self.sysConf.commands[command]
commandInfo['call'](job)

def getAttr(self, attribute):
"""
A generator that returns all plugins and the
requested attribute
"""
for p in self.allPlugins:
for p in self.pluginList:
a = getattr(self[p], attribute, None)
if a: yield p, a

Expand Down

0 comments on commit aafec65

Please sign in to comment.