Skip to content

Commit

Permalink
Implement min/max for multiple data input parameters.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmchilton committed Sep 21, 2015
1 parent 2bfc12d commit 87d5063
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 6 deletions.
44 changes: 39 additions & 5 deletions lib/galaxy/tools/parameters/basic.py
Expand Up @@ -1764,6 +1764,22 @@ def __init__( self, tool, input_source, trans=None):
self.validators.append( validation.MetadataValidator() )
self._parse_formats( trans, tool, input_source )
self.multiple = input_source.get_bool('multiple', False)
self.min = input_source.get( 'min' )
self.max = input_source.get( 'max' )
if self.min:
try:
self.min = int( self.min )
except:
raise ValueError( "An integer is required for min property." )
if self.max:
try:
self.max = int( self.max )
except:
raise ValueError( "An integer is required for max property." )
if not self.multiple and (self.min is not None):
raise ValueError( "Cannot specify min property on single data parameter '%s'. Set multiple=\"true\" to enable this option." % self.name )
if not self.multiple and (self.max is not None):
raise ValueError( "Cannot specify max property on single data parameter '%s'. Set multiple=\"true\" to enable this option." % self.name )
self.is_dynamic = True
self._parse_options( input_source )
# Load conversions required for the dataset input
Expand Down Expand Up @@ -2052,17 +2068,31 @@ def value_to_display_text( self, value, app ):
return "No dataset"

def validate( self, value, history=None ):
dataset_count = 0
for validator in self.validators:
if value and self.multiple:
if isinstance(value, list):
for v in value:
validator.validate( v, history )
elif isinstance(value, galaxy.model.HistoryDatasetCollectionAssociation):
for v in value.collection.dataset_instances:
if not isinstance( value, list ):
value = [ value ]
for v in value:
if isinstance(v, galaxy.model.HistoryDatasetCollectionAssociation):
for dataset_instance in v.collection.dataset_instances:
dataset_count += 1
validator.validate( dataset_instance, history )
else:
dataset_count += 1
validator.validate( v, history )
else:
if value:
dataset_count += 1
validator.validate( value, history )

if self.min is not None:
if self.min > dataset_count:
raise ValueError( "At least %d datasets are required." % self.min )
if self.max is not None:
if self.max < dataset_count:
raise ValueError( "At most %d datasets are required." % self.max )

def get_dependencies( self ):
"""
Get the *names* of the other params this param depends on.
Expand Down Expand Up @@ -2124,6 +2154,10 @@ def to_dict( self, trans, view='collection', value_mapper=None, other_values=Non
d['extensions'] = extensions
d['edam_formats'] = edam_formats
d['multiple'] = self.multiple
if self.multiple:
# For consistency, should these just always be in the dict?
d['min'] = self.min
d['max'] = self.max
d['options'] = {'hda': [], 'hdca': []}

# return default content if context is not available
Expand Down
13 changes: 13 additions & 0 deletions test/api/test_tools.py
Expand Up @@ -62,6 +62,19 @@ def test_show_conditional( self ):
self._assert_has_keys( case2_inputs[ 0 ], 'name', 'type', 'label', 'help', 'argument' )
assert case2_inputs[ 0 ][ "name" ] == "seed"

@skip_without_tool( "multi_data_param" )
def test_show_multi_data( self ):
tool_info = self._show_valid_tool( "multi_data_param" )

f1_info, f2_info = tool_info[ "inputs" ][ 0 ], tool_info[ "inputs" ][ 1 ]
self._assert_has_keys( f1_info, "min", "max" )
assert f1_info["min"] == 1
assert f1_info["max"] == 1235

self._assert_has_keys( f2_info, "min", "max" )
assert f2_info["min"] is None
assert f2_info["max"] is None

def _show_valid_tool( self, tool_id ):
tool_show_response = self._get( "tools/%s" % tool_id, data=dict( io_details=True ) )
self._assert_status_code_is( tool_show_response, 200 )
Expand Down
2 changes: 1 addition & 1 deletion test/functional/tools/multi_data_param.xml
Expand Up @@ -6,7 +6,7 @@
cat ${" ".join(map(str, $f2))} >> $out2
</command>
<inputs>
<param name="f1" type="data" format="txt" multiple="true" label="Data 1" />
<param name="f1" type="data" format="txt" multiple="true" label="Data 1" min="1" max="1235" />
<param name="f2" type="data" format="txt" multiple="true" label="Data 2" />
<conditional name="advanced">
<param name="full" type="select" label="Parameter Settings">
Expand Down

0 comments on commit 87d5063

Please sign in to comment.