As you have already seen, ecFlow has a ecFlow Python Api:
#!/usr/bin/env python2.5
import ecflow
This allows the suite definition to be built with python.
It also allows communication with the ecf_server.
This is a very powerful feature, that helps to define very complex suites in a relatively compact way.
Consider the following suite
suite test
family f1
task a
task b
task c
task d
task e
endfamily
family f2
task a
task b
task c
task d
task e
endfamily
family f3
task a
task b
task c
task d
task e
endfamily
family f4
task a
task b
task c
task d
task e
endfamily
family f5
task a
task b
task c
task d
task e
endfamily
family f6
task a
task b
task c
task d
task e
endfamily
endsuite
This can be written in python as:
def create_suite(name) :
suite = ecflow.Suite(name)
for i in range(1,7) :
fam = suite.add_family("f" + str(i))
for t in ( "a", "b", "c", "d", "e" ) :
fam.add_task(t);
return suite
Python variables can be used to generate trigger dependencies.
Imagine that we want to chain the families f1 to f6, so that f2 runs after f1, f3 after f2 and so on.
The following will do the trick:
def create_seqeuntial_suite(name) :
suite = ecflow.Suite(name)
for i in range(1,7) :
fam = suite.add_family("f" + str(i))
if i != 1:
fam.add_trigger("f" + str(i-1) + " == complete") # or fam.add_family( "f%d == complete" % (i-1) )
for t in ( "a", "b", "c", "d", "e" ) :
fam.add_task(t)
return suite
The following python code shows examples of adding the various attributes to a node tree.
For a detailed explanation please consult the user manual.
# provides *examples* of add adding node attributes using the python API
# hence does *not* represent a real suite definition
from ecflow import *
def list_to_int_vec( thePythonList ):
"""Converts a python list to a C++ IntVec in ecflow extension """
intvec = IntVec()
for theInt in thePythonList:
IntVec.append(intvec,theInt)
return intvec
def list_to_str_vec( theList ):
"""Converts a python list to a C++ StrVec in ecflow extension"""
strvec = StrVec()
for theStr in theList:
StrVec.append(strvec,theStr)
return strvec;
if __name__ == "__main__":
# adding variables
suite = Suite("s1");
suite.add_variable(Variable("ECF_HOME","/tmp/"))
suite.add_variable("ECF_URL_CMD", "${BROWSER:=firefox} -remote 'openURL(%ECF_URL_BASE%/%ECF_URL%)'")
# adding limits
suite.add_limit( Limit("limitName1", 10) )
suite.add_limit( "limitName3", 10 )
# adding inlimits
suite.add_inlimit( InLimit("limitName1","/s1/f1",2) )
suite.add_inlimit( "limitName3","/s1/f1",2)
# add short triggers and complete
task = Task("task")
task.add_trigger( "t2 == active" )
task.add_complete( "t2 == complete" )
# add long triggers and complete, in example below 'True' mean AND and 'False' means OR
task = Task("trigger")
task.add_part_trigger( "t1 == complete" )
task.add_part_trigger( "t2 == active",True ) # for long and/or expressions, subsequent expr must be and/or
task.add_part_complete( "t3 == complete" )
task.add_part_complete( "t4 == active",False) # for long and/or expressions, subsequent expr must be and/or
# add events
task.add_event( Event(1) )
task.add_event( 2 )
task.add_event( Event(10,"Eventname") )
task.add_event( 10,"Eventname2" )
task.add_event( "fred" )
# add meter
task.add_meter( Meter("metername1",0,100,50) )
task.add_meter( "metername3",0,100 )
# add label
task.add_label( Label("label_name1", "value") )
task.add_label( "label_name3", "value" )
# add Repeat. A node can only have one repeat, hence we delete the repeat before, adding another
task.add_repeat( RepeatInteger("integer",0,100,2) );
task.delete_repeat();
task.add_repeat( RepeatEnumerated("enum",list_to_str_vec( ["red", "green", "blue" ] )) );
task.delete_repeat();
task.add_repeat( RepeatDate("date",20100111,20100115,2) )
task.delete_repeat();
task.add_repeat( RepeatString("string", list_to_str_vec( ["a", "b", "c" ] )) )
task.delete_repeat();
# create a time series, used for adding time and today and cron
start = TimeSlot(0,0)
finish = TimeSlot(23,0)
incr = TimeSlot(0,30)
time_series = TimeSeries( start, finish, incr, True); # True means relative to suite start
# add a today
task.add_today( "00:30" )
task.add_today( "+00:30" )
task.add_today( "+00:30 20:00 01:00" )
task.add_today( Today( time_series) )
task.add_today( Today( 0,10 ))
task.add_today( 0, 59, True )
task.add_today( Today(TimeSlot(20,10)) )
task.add_today( Today(TimeSlot(20,20),False))
# add time
task.add_time( "00:30" )
task.add_time( "+00:30" )
task.add_time( "+00:30 20:00 01:00" )
task.add_time( Time(time_series ))
task.add_time( Time( 0,10 ))
task.add_time( 0, 59, True)
task.add_time( Time(TimeSlot(20,10)) )
task.add_time( Time(TimeSlot(20,20),False))
# add date
for i in [ 1,2,4,8,16 ] :
task.add_date( i,0,0) # day,month,year, where corresponding 0 means any possible day,month, year
task.add_date( Date(1,1,2010))
# add day
task.add_day( Day(Days.sunday))
task.add_day( Days.monday)
task.add_day( "tuesday")
# create cron, showing different ways adding the time, to a cron attribute
cron = Cron()
cron.set_week_days( list_to_int_vec( [0,1,2,3,4,5,6] ) )
cron.set_days_of_month( list_to_int_vec( [1,2,3,4,5,6] ) )
cron.set_months( list_to_int_vec( [1,2,3,4,5,6] ) )
start = TimeSlot(0,0)
finish = TimeSlot(23,0)
incr = TimeSlot(0,30)
ts = TimeSeries( start, finish, incr, True); # True means relative to suite start
cron.set_time_series( ts )
cron1 = Cron()
cron1.set_week_days( list_to_int_vec( [0,1,2,3,4,5,6] ) )
cron1.set_time_series( 1,30, True )
cron2 = Cron()
cron2.set_week_days( list_to_int_vec( [0,1,2,3,4,5,6] ) )
cron2.set_time_series( "00:30 01:30 00:01" )
cron3 = Cron()
cron3.set_week_days( list_to_int_vec( [0,1,2,3,4,5,6] ) )
cron3.set_time_series( "+00:30" )
# add auto cancel
t1 = Task("t1");
t3 = Task("t3")
t4 = Task("t4")
t5 = Task("t5")
t1.add_autocancel( 3 ) # 3 days
t3.add_autocancel( 20,10,True ) # hour,minutes,relative
t4.add_autocancel( TimeSlot(10,10),True ) # hour,minutes,relative
t5.add_autocancel( Autocancel(1,10,True) ) # hour,minutes,relative
# add late
late = Late()
late.submitted( TimeSlot(20,10) )
late.active( TimeSlot(20,10))
late.complete( TimeSlot(20,10),True)
task.add_late( late )
late = Late()
late.submitted( 20,10 )
late.active( 20,10 )
late.complete( 20,10,True)
t1.add_late( late )
# add defstatus, last one set takes effect
task.add_defstatus( DState.complete )
task.add_defstatus( DState.queued )
task.add_defstatus( DState.aborted )
task.add_defstatus( DState.submitted )
task.add_defstatus( DState.suspended )
task.add_defstatus( DState.active )
# add clock,
clock = Clock(1,1,2010,False); # day,month, year, hybrid(true), real(False)
clock.set_gain(1,10,True); # True means positive gain
suite = Suite("suite")
suite.add_clock(clock);
clock = Clock(1,1,2011,True); # day,month,year,hybrid
clock.set_gain_in_seconds(12,True);
s1 = Suite("s1")
s1.add_clock(clock)