Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
HTML
<div class="section" id="object-oriented-suites">
<span id="index-0"></span>
<p>Python&#8217;s object oriented design features allows considerable flexibility
in how we design and structure our <a class="reference internal" href="/wiki/display/ECFLOW/Glossary#term-suite-definition"><em class="xref std std-term">suite definition</em></a>.</p>
<p>Each suite will have a different set of forces which determine how it should
be designed.</p>
<p>Lets consider how we would design the tutorial examples in a more object oriented manner.
We start with some design criteria we must meet.</p>
<ul class="simple">
<li>The default variables (ECF_HOME,etc) must be configurable and independent of the suites</li>
<li>New suites must enable automatic job creation checking</li>
<li>We need to write out definition as a separate file</li>
<li>New suites should be able to re-use the &#8220;boiler plate&#8221; code defined by the above requirements</li>
</ul>
<p>Here is possible design, that uses inheritance and the template design pattern:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c">#!/usr/bin/env python2.7</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">ecflow</span>  

<span class="k">class</span> <span class="nc">DefaultVariables</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Provide the setup variables for each suite&quot;&quot;&quot;</span>
    <span class="k">def</span> <span class="nf">add_to</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">node</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Adds ECF_INCLUDE,ECF_HOME to the input node&quot;&quot;&quot;</span>
        <span class="n">node</span><span class="o">.</span><span class="n">add_variable</span><span class="p">(</span><span class="s">&quot;ECF_INCLUDE&quot;</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">getenv</span><span class="p">(</span><span class="s">&quot;HOME&quot;</span><span class="p">)</span> <span class="o">+</span> <span class="s">&quot;/course&quot;</span><span class="p">)</span>
        <span class="n">node</span><span class="o">.</span><span class="n">add_variable</span><span class="p">(</span><span class="s">&quot;ECF_HOME&quot;</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">getenv</span><span class="p">(</span><span class="s">&quot;HOME&quot;</span><span class="p">)</span> <span class="o">+</span> <span class="s">&quot;/course&quot;</span><span class="p">)</span>


<span class="k">class</span> <span class="nc">BaseSuiteBuilder</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Abstract class. Add default variables to suite and enable job creation </span>
<span class="sd">       checking for any derived suite</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default_variables</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">defs</span> <span class="o">=</span> <span class="n">ecflow</span><span class="o">.</span><span class="n">Defs</span><span class="p">()</span>
        <span class="c"># use derived class name as suite name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">suite</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">defs</span><span class="o">.</span><span class="n">add_suite</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__name__</span><span class="p">)</span> 
        <span class="n">default_variables</span><span class="o">.</span><span class="n">add_to</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">suite</span><span class="p">)</span>
        
    <span class="k">def</span> <span class="nf">_build_definition_hook</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Derived suite should override this function to build the suite</span>
<span class="sd">           Should not be called explicitly. How could we enforce this ?</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">pass</span>
    
    <span class="k">def</span> <span class="nf">setup</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Template/skeleton function. </span>
<span class="sd">           Provides common algorithm for *all* derivatives</span>
<span class="sd">           Uses Holly wood principle.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        
        <span class="c"># Build the suite</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_build_definition_hook</span><span class="p">()</span>
        
        <span class="c"># check job creation. Could use an assert</span>
        <span class="n">job_check_result</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">defs</span><span class="o">.</span><span class="n">check_job_creation</span><span class="p">()</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">job_check_result</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">print</span> <span class="s">&quot;Job creation failed</span><span class="se">\n</span><span class="s">&quot;</span> <span class="o">+</span> <span class="n">job_check_result</span>
 
        <span class="c"># Check trigger expressions and limit references&quot;</span>
        <span class="k">print</span> <span class="bp">self</span><span class="o">.</span><span class="n">defs</span><span class="o">.</span><span class="n">check</span><span class="p">()</span>
                   
        <span class="c"># Allows definition creation to be separated from the load</span>
        <span class="c"># Use the class name as the name of the definition file</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">defs</span><span class="o">.</span><span class="n">save_as_defs</span><span class="p">(</span> <span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__name__</span> <span class="o">+</span> <span class="s">&quot;.def&quot;</span><span class="p">)</span>
        
        
<span class="k">class</span> <span class="nc">SuiteBuilder</span><span class="p">(</span><span class="n">BaseSuiteBuilder</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;My example suite.  Generates SuiteBuilder.def&quot;&quot;&quot;</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default_variables</span><span class="p">):</span>
        <span class="n">BaseSuiteBuilder</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default_variables</span><span class="p">)</span>
        
    <span class="k">def</span> <span class="nf">_build_definition_hook</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">f1</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">suite</span><span class="o">.</span><span class="n">add_family</span><span class="p">(</span><span class="s">&quot;family&quot;</span><span class="p">)</span>
        <span class="n">f1</span><span class="o">.</span><span class="n">add_task</span><span class="p">(</span><span class="s">&quot;task1&quot;</span><span class="p">)</span>           
        <span class="n">f1</span><span class="o">.</span><span class="n">add_task</span><span class="p">(</span><span class="s">&quot;task2&quot;</span><span class="p">)</span> 
        

<span class="k">class</span> <span class="nc">TestSuite</span><span class="p">(</span><span class="n">BaseSuiteBuilder</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;My test suite. Generates TestSuite.def&quot;&quot;&quot;</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default_variables</span><span class="p">):</span>
        <span class="n">BaseSuiteBuilder</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default_variables</span><span class="p">)</span>
        
    <span class="k">def</span> <span class="nf">_build_definition_hook</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">suite</span><span class="o">.</span><span class="n">add_task</span><span class="p">(</span><span class="s">&quot;task1&quot;</span><span class="p">)</span>


<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span>

    <span class="n">my_suite</span> <span class="o">=</span> <span class="n">SuiteBuilder</span><span class="p">(</span><span class="n">DefaultVariables</span><span class="p">())</span>
    <span class="n">my_suite</span><span class="o">.</span><span class="n">setup</span><span class="p">()</span>

    <span class="n">my_test_suite</span> <span class="o">=</span> <span class="n">TestSuite</span><span class="p">(</span><span class="n">DefaultVariables</span><span class="p">())</span>
    <span class="n">my_test_suite</span><span class="o">.</span><span class="n">setup</span><span class="p">()</span>
            
</pre></div>
</div>
</div>