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 ecflow_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)