Helper Functionality
pyflow aims to contain not just a collection of ecflow functionality, but also helper functionality to assist in building suites. Where idiomatic uses of ecFlow result in the same mechanisms being built repeatedly, pyflow can incorporate these to help generate clearer suites.
The ecflow_name() functionality converts an arbitrary string into a name which meets the character restrictions for ecflow nodes. This is very useful for converting strings such as hostnames or the names of various data sets into a form that can be used as the name of a Family or Task.
[2]:
print(pf.ecflow_name('hyphenated-name'))
hyphenated_name
The all_complete() and sequence() functions facilitate working with generated sequences of python tasks. all_complete() generates an expression suitable for use in triggers (or completes). sequence() generates triggers such that all of the tasks will run sequentially.
[3]:
with CourseSuite('sequences') as s:
tasks = [pf.Task('t_{}'.format(i)) for i in range(10)]
pf.Task('done', triggers=pf.all_complete(tasks))
pf.sequence(tasks)
s
[3]:
suite sequences defstatus suspended edit ECF_FILES '/path/to/scratch/files/sequences' edit ECF_HOME '/path/to/scratch/out' edit ECF_JOB_CMD 'bash -c 'export ECF_PORT=%ECF_PORT%; export ECF_HOST=%ECF_HOST%; export ECF_NAME=%ECF_NAME%; export ECF_PASS=%ECF_PASS%; export ECF_TRYNO=%ECF_TRYNO%; export PATH=/usr/local/apps/ecflow/%ECF_VERSION%/bin:$PATH; ecflow_client --init="$$" && %ECF_JOB% && ecflow_client --complete || ecflow_client --abort ' 1> %ECF_JOBOUT% 2>&1 &' edit ECF_KILL_CMD 'pkill -15 -P %ECF_RID%' edit ECF_STATUS_CMD 'true' edit ECF_OUT '%ECF_HOME%' label exec_host "localhost" task t_0 task t_1 trigger t_0 eq complete task t_2 trigger t_1 eq complete task t_3 trigger t_2 eq complete task t_4 trigger t_3 eq complete task t_5 trigger t_4 eq complete task t_6 trigger t_5 eq complete task t_7 trigger t_6 eq complete task t_8 trigger t_7 eq complete task t_9 trigger t_8 eq complete task done trigger ((((((((t_0 eq complete and t_1 eq complete) and t_2 eq complete) and t_3 eq complete) and t_4 eq complete) and t_5 eq complete) and t_6 eq complete) and t_7 eq complete) and t_8 eq complete) and t_9 eq complete endsuite
A common idiom in looping suites is to have two suites that both loop on dates/times, one which runs behind the other. For example the lag family running after the forecast has completed. This idiom can be expressed more clearly by encapsulating its functionality.
[ ]:
with pf.Suite('follow') as s:
with pf.Family('leader') as leader:
pf.RepeatDate("YMD", datetime.date(2019, 1, 1), datetime.date(2019, 12, 31))
with pf.Family('follower') as follower:
pf.RepeatDate("YMD", datetime.date(2019, 1, 1), datetime.date(2019, 12, 31))
follower.follow = leader
s
suite follow edit ECF_JOB_CMD 'bash -c 'export ECF_PORT=%ECF_PORT%; export ECF_HOST=%ECF_HOST%; export ECF_NAME=%ECF_NAME%; export ECF_PASS=%ECF_PASS%; export ECF_TRYNO=%ECF_TRYNO%; export PATH=/usr/local/apps/ecflow/%ECF_VERSION%/bin:$PATH; ecflow_client --init="$$" && %ECF_JOB% && ecflow_client --complete || ecflow_client --abort ' 1> %ECF_JOBOUT% 2>&1 &' edit ECF_KILL_CMD 'pkill -15 -P %ECF_RID%' edit ECF_STATUS_CMD 'true' edit ECF_OUT '%ECF_HOME%' label exec_host "default" family leader repeat date YMD 20190101 20191231 1 endfamily family follower trigger leader eq complete or follower:YMD lt leader:YMD repeat date YMD 20190101 20191231 1 endfamily endsuite
This collection of utility functionality is (perpetually) in progress, and will be updated to account for useful idioms as they emerge.