Tree-like input specification in tool XML file.

Allow nestable <repeat> and <conditional> statements in test tool definitions.

For instance, imagine a tool with a repeat statement like:

  <repeat name="rinst" title="Repeat Parameter">
    <param name="int_param" type="integer" value="1" />
    <param name="float_param" type="float" value="2.0" />
  </repeat>

3 test instances overidding int_param default in all three, but leaving the float_param default in place for the first and last can specified as follows:

  <repeat name="rinst">
    <param name="rinst|int_param" value="4" />
  </repeat>
  <repeat name="rinst">
    <param name="rinst|int_param" value="5" />
    <param name="rinst|float_param" value="4.0" />
  </repeat>
  <repeat name="rinst">
    <param name="rinst|int_param" value="6" />
  </repeat>

Likewise, <conditional name="cinst"> can be used analogously though this is for grouping and disambiguation - does not allow multiple instances to specified obviously.
This commit is contained in:
John Chilton
2013-11-21 19:17:13 -06:00
parent 1a6fbc5456
commit bf75275a61
2 changed files with 64 additions and 0 deletions
+47
View File
@@ -127,6 +127,7 @@ class ToolTestBuilder( object ):
# features or workarounds.
self.interactor = test_elem.get( 'interactor', default_interactor )
self.__preprocess_input_elems( test_elem )
self.__parse_inputs_elems( test_elem, i )
self.__parse_output_elems( test_elem )
@@ -134,6 +135,9 @@ class ToolTestBuilder( object ):
self.error = True
self.exception = e
def __preprocess_input_elems( self, test_elem ):
expand_input_elems( test_elem )
def __parse_inputs_elems( self, test_elem, i ):
# Composite datasets need a unique name: each test occurs in a fresh
# history, but we'll keep it unique per set of tests - use i (test #)
@@ -385,3 +389,46 @@ class RootParamContext(object):
def get_index( self ):
return 0
def expand_input_elems( root_elem, prefix="" ):
__append_prefix_to_params( root_elem, prefix )
repeat_elems = root_elem.findall( 'repeat' )
indices = {}
for repeat_elem in repeat_elems:
name = repeat_elem.get( "name" )
if name not in indices:
indices[ name ] = 0
index = 0
else:
index = indices[ name ] + 1
indices[ name ] = index
new_prefix = __prefix_join( prefix, name, index=index )
expand_input_elems( repeat_elem, new_prefix )
__pull_up_params( root_elem, repeat_elem )
root_elem.remove( repeat_elem )
cond_elems = root_elem.findall( 'conditional' )
for cond_elem in cond_elems:
new_prefix = __prefix_join( prefix, cond_elem.get( "name" ) )
expand_input_elems( cond_elem, new_prefix )
__pull_up_params( root_elem, cond_elem )
root_elem.remove( cond_elem )
def __append_prefix_to_params( elem, prefix ):
for param_elem in elem.findall( 'param' ):
param_elem.set( "name", __prefix_join( prefix, param_elem.get( "name" ) ) )
def __pull_up_params( parent_elem, child_elem ):
for param_elem in child_elem.findall( 'param' ):
parent_elem.append( param_elem )
child_elem.remove( param_elem )
def __prefix_join( prefix, name, index=None ):
name = name if index is None else "%s_%d" % ( name, index )
return name if not prefix else "%s|%s" % ( prefix, name )
@@ -24,5 +24,22 @@
<output name="out_file1" file="simple_lines_interleaved.txt"/>
</test>
<test>
<repeat name="queries">
<param name="input" value="simple_line.txt"/>
</repeat>
<repeat name="queries">
<param name="input" value="simple_line_alternative.txt"/>
</repeat>
<repeat name="more_queries">
<param name="input" value="simple_line.txt"/>
</repeat>
<repeat name="more_queries">
<param name="input" value="simple_line_alternative.txt"/>
</repeat>
<output name="out_file1" file="simple_lines_interleaved.txt"/>
</test>
</tests>
</tool>