gavo.rscdef.executing module

The execute element and related stuff.

class gavo.rscdef.executing.CronJob(parent, **kwargs)[source]

Bases: ProcApp

Python code for use within execute.

The resource descriptor this runs at is available as rd, the execute definition (having such attributes as title, job, plus any properties given in the RD) as execDef.

Note that no I/O capturing takes place (that’s impossible since in general the jobs run within the server). To have actual cron jobs, use execDef.spawn(["cmd", "arg1"...]). This will send a mail on failed execution and also raise a ReportableError in that case.

In the frequent use case of a resdir-relative python program, you can use the execDef.spawnPython(modulePath) function.

If you must stay within the server process, you can do something like:

mod, _ = utils.loadPythonModule(rd.getAbsPath("bin/coverageplot"))
mod.makePlot()

– in that way, your code can sit safely within the resource directory and you still don’t have to manipulate the module path.

attrSeq = [<gavo.base.complexattrs.StructListAttribute object>, <gavo.base.attrdef.UnicodeAttribute object>, <gavo.base.attrdef.UnicodeAttribute object>, <gavo.base.attrdef.UnicodeAttribute object>, <gavo.base.parsecontext.IdAttribute object>, <gavo.base.attrdef.UnicodeAttribute object>, <gavo.base.parsecontext.OriginalAttribute object>, <gavo.base.parsecontext.ReferenceAttribute object>, <gavo.base.complexattrs.StructListAttribute object>, <gavo.base.attrdef.EnumeratedUnicodeAttribute object>]
completedCallbacks = []
formalArgs = 'rd, execDef'
managedAttrs = {'bind': <gavo.base.complexattrs.StructListAttribute object>, 'bindings': <gavo.base.complexattrs.StructListAttribute object>, 'code': <gavo.base.attrdef.UnicodeAttribute object>, 'deprecated': <gavo.base.attrdef.UnicodeAttribute object>, 'doc': <gavo.base.attrdef.UnicodeAttribute object>, 'id': <gavo.base.parsecontext.IdAttribute object>, 'name': <gavo.base.attrdef.UnicodeAttribute object>, 'original': <gavo.base.parsecontext.OriginalAttribute object>, 'procDef': <gavo.base.parsecontext.ReferenceAttribute object>, 'setup': <gavo.base.complexattrs.StructListAttribute object>, 'setups': <gavo.base.complexattrs.StructListAttribute object>, 'type': <gavo.base.attrdef.EnumeratedUnicodeAttribute object>}
name_ = 'job'
class gavo.rscdef.executing.Execute(parent, **kwargs)[source]

Bases: Structure, ExpansionDelegator

a container for calling code.

This is a cron-like functionality. The jobs are run in separate threads, so they need to be thread-safe with respect to the rest of DaCHS. DaCHS serializes calls, though, so that your code should never run twice at the same time.

At least on CPython, you must make sure your code does not block with the GIL held; this is still in the server process. If you do daring things, fork off (note that you must not use any database connections you may have after forking, which means you can’t safely use the RD passed in). See the docs on `Element job`_.

Then testing/debugging such code, use gavo admin execute rd#id to immediately run the jobs.

attrSeq = [<gavo.base.attrdef.StringListAttribute object>, <gavo.base.attrdef.BooleanAttribute object>, <gavo.base.attrdef.IntAttribute object>, <gavo.base.parsecontext.IdAttribute object>, <gavo.base.complexattrs.StructAttribute object>, <gavo.base.complexattrs.PropertyAttribute object>, <gavo.rscdef.common.RDAttribute object>, <gavo.base.attrdef.UnicodeAttribute object>]
clearProperty(name)
completeElement(ctx)[source]
completedCallbacks = []
getFullId()
getProperty(name, default=<Undefined>)
hasProperty(name)
managedAttrs = {'at': <gavo.base.attrdef.StringListAttribute object>, 'debug': <gavo.base.attrdef.BooleanAttribute object>, 'every': <gavo.base.attrdef.IntAttribute object>, 'id': <gavo.base.parsecontext.IdAttribute object>, 'job': <gavo.base.complexattrs.StructAttribute object>, 'properties': <gavo.base.complexattrs.PropertyAttribute object>, 'property': <gavo.base.complexattrs.PropertyAttribute object>, 'rd': <gavo.rscdef.common.RDAttribute object>, 'title': <gavo.base.attrdef.UnicodeAttribute object>}
name_ = 'execute'
onElementComplete()[source]
property rd
setProperty(name, value)
spawn(cliList)[source]

spawns an external command, capturing the output and mailing it to the admin if it failed.

Output is buffered and mailed, so it shouldn’t be too large.

This does not raise an exception if the command fails (in normal usage, this would cause two mails to be sent). Instead, it returns the returncode of the spawned process; if that’s 0, you’re ok. But in general, you wouldn’t want to check it, as on failure you’ll already receive a (more informative) mail.

spawnPython(pythonFile)[source]

spawns a new python interpreter executing pythonFile.

pythonFile may be resdir-relative.

class gavo.rscdef.executing.GuardedFunctionFactory[source]

Bases: object

a class for making functions safe for cron-like executions.

The main method is makeGuarded. It introduces a lock protecting against double execution (if that were to happen, the execution is suppressed with a warning; of course, if you fork something into the background, that mechanism no longer works). The stuff is run in a thread, and exceptions caught. If anything goes wrong during execution, a mail is sent to the administrator.

Note that, in contrast to cron, I/O is not captured (that would be difficult for threads; we don’t want processes because of the potential trouble with database connections).

There’s a module-private instance of this that’s used by Execute.

makeGuardedThreaded(callable, execDef)[source]

returns callable ready for safe cron-like execution.

execDef is an Execute instance.