Merge pull request #5702 from guerler/select_to_text

Relax validation condition for dynamic parameters
This commit is contained in:
Nicola Soranzo
2018-03-27 15:35:48 +01:00
committed by GitHub
4 changed files with 78 additions and 46 deletions
@@ -84,23 +84,10 @@ export default Backbone.Model.extend({
}
// identify display type
var SelectClass = Ui.Select;
switch (input_def.display) {
case "checkboxes":
SelectClass = Ui.Checkbox;
break;
case "radio":
SelectClass = Ui.Radio;
break;
case "radiobutton":
SelectClass = Ui.RadioButton;
break;
}
// create select field
return new SelectClass.View({
return new Ui.TextSelect({
id: `field-${input_def.id}`,
data: data,
display: input_def.display,
error_text: input_def.error_text || "No options available",
readonly: input_def.readonly,
multiple: input_def.multiple,
+30
View File
@@ -184,6 +184,35 @@ export var Hidden = Backbone.View.extend({
}
});
/** Creates an input element which switches between select and text field */
export var TextSelect = Backbone.View.extend({
initialize: function(options) {
this.text = new Input(options);
var classes = {
"checkboxes": Checkbox,
"radio": Radio,
"radiobutton": RadioButton
}
var SelectClass = classes[options.display] || Select;
this.select = new SelectClass.View(options);
this.setElement($("<div/>").append(this.select.$el)
.append(this.text.$el));
this.update(options.data);
},
value: function(new_val) {
var element = this.textmode ? this.text : this.select;
return element.value(new_val);
},
update: function(options) {
var v = this.value();
this.textmode = !$.isArray(options) || options.length === 0;
this.text.$el[this.textmode ? "show" : "hide"]();
this.select.$el[this.textmode ? "hide" : "show"]();
this.select.update(options);
this.value(v);
}
});
/** Creates a upload element input field */
export var Upload = Backbone.View.extend({
initialize: function(options) {
@@ -266,6 +295,7 @@ export default {
Checkbox: Options.Checkbox,
Radio: Options.Radio,
Select: Select,
TextSelect: TextSelect,
Hidden: Hidden,
Slider: Slider,
Drilldown: Drilldown
+40 -30
View File
@@ -43,8 +43,6 @@ workflow_building_modes = Bunch(DISABLED=False, ENABLED=True, USE_HISTORY=1)
WORKFLOW_PARAMETER_REGULAR_EXPRESSION = re.compile('''\$\{.+?\}''')
MAX_DEFAULT_COLUMNS = 999
def contains_workflow_parameter(value, search=False):
if not isinstance(value, string_types):
@@ -57,7 +55,17 @@ def contains_workflow_parameter(value, search=False):
def is_runtime_value(value):
return isinstance(value, RuntimeValue) or (isinstance(value, dict) and value.get('__class__') == 'RuntimeValue')
return isinstance(value, RuntimeValue) or (isinstance(value, dict)
and value.get("__class__") == "RuntimeValue")
def has_runtime_datasets(trans, value):
for v in util.listify(value):
if isinstance(v, trans.app.model.HistoryDatasetAssociation) and \
((hasattr(v, "state") and v.state != galaxy.model.Dataset.states.OK) or
hasattr(v, "implicit_conversion")):
return True
return False
def parse_dynamic_options(param, input_source):
@@ -848,10 +856,12 @@ class SelectToolParameter(ToolParameter):
legal_values = self.get_legal_values(trans, other_values)
workflow_building_mode = trans.workflow_building_mode
for context_value in other_values.values():
if is_runtime_value(context_value):
if is_runtime_value(context_value) or has_runtime_datasets(trans, context_value):
workflow_building_mode = workflow_building_modes.ENABLED
break
if len(list(legal_values)) == 0 and workflow_building_mode:
if not legal_values:
if not workflow_building_mode:
raise ValueError("Parameter %s requires a value, but has no legal values defined." % self.name)
if self.multiple:
# While it is generally allowed that a select value can be '',
# we do not allow this to be the case in a dynamically
@@ -866,10 +876,10 @@ class SelectToolParameter(ToolParameter):
# use \r\n to separate lines.
value = value.split()
return value
if (not legal_values or value is None) and self.optional:
return None
if not legal_values:
raise ValueError("Parameter %s requires a value, but has no legal values defined." % self.name)
elif value is None:
if self.optional:
return None
raise ValueError("An invalid option was selected for %s, please verify." % (self.name))
if isinstance(value, list):
if not self.multiple:
raise ValueError("Multiple values provided but parameter %s is not expecting multiple values." % self.name)
@@ -914,7 +924,7 @@ class SelectToolParameter(ToolParameter):
def get_initial_value(self, trans, other_values):
options = list(self.get_options(trans, other_values))
if len(options) == 0 and trans.workflow_building_mode:
if not options:
return None
value = [optval for _, optval, selected in options if selected]
if len(value) == 0:
@@ -1114,7 +1124,7 @@ class ColumnListParameter(SelectToolParameter):
dataset (if found).
"""
# Get the value of the associated data reference (a dataset)
dataset = other_values.get(self.data_ref, None)
dataset = other_values.get(self.data_ref)
# Check if a dataset is selected
if not dataset:
return []
@@ -1123,16 +1133,14 @@ class ColumnListParameter(SelectToolParameter):
# Use representative dataset if a dataset collection is parsed
if isinstance(dataset, trans.app.model.HistoryDatasetCollectionAssociation):
dataset = dataset.to_hda_representative()
# Columns can only be identified if metadata is available
if not hasattr(dataset, 'metadata') or not hasattr(dataset.metadata, 'columns'):
# Columns can only be identified if the dataset is ready and metadata is available
if not hasattr(dataset, 'metadata') or \
not hasattr(dataset.metadata, 'columns') or \
not dataset.metadata.columns:
return []
# Build up possible columns for this dataset
this_column_list = []
# Valid column-based datasets contain at least 1 column if that column has not been
# specified we prepopulate the selector assuming that the datasets is not ready yet.
if dataset.metadata.columns is None:
this_column_list = [str(i) for i in range(1, MAX_DEFAULT_COLUMNS + 1)]
elif self.numerical:
if self.numerical:
# If numerical was requested, filter columns based on metadata
for i, col in enumerate(dataset.metadata.column_types):
if col == 'int' or col == 'float':
@@ -1319,24 +1327,24 @@ class DrillDownSelectToolParameter(SelectToolParameter):
def from_json(self, value, trans, other_values={}):
legal_values = self.get_legal_values(trans, other_values)
if len(list(legal_values)) == 0 and trans.workflow_building_mode:
if not legal_values:
if not trans.workflow_building_mode:
raise ValueError("Parameter %s requires a value, but has no legal values defined." % self.name)
if self.multiple:
if value == '': # No option selected
value = None
else:
value = value.split("\n")
return value
if not value and not self.optional:
elif value is None:
if self.optional:
return None
raise ValueError("An invalid option was selected for %s, please verify." % (self.name))
if not value:
return None
if not isinstance(value, list):
value = [value]
if len(value) > 1 and not self.multiple:
raise ValueError("Multiple values provided but parameter %s is not expecting multiple values." % self.name)
rval = []
if not legal_values:
raise ValueError("Parameter %s requires a value, but has no legal values defined." % self.name)
for val in value:
if val not in legal_values:
raise ValueError("An invalid option was selected for %s, %r, please verify" % (self.name, val))
@@ -1391,7 +1399,7 @@ class DrillDownSelectToolParameter(SelectToolParameter):
recurse_options(initial_values, option['options'])
# More working around dynamic options for workflow
options = self.get_options(trans=trans, other_values=other_values)
if len(list(options)) == 0 and trans.workflow_building_mode:
if not options:
return None
initial_values = []
recurse_options(initial_values, options)
@@ -1685,16 +1693,18 @@ class DataToolParameter(BaseDataToolParameter):
rval = value
else:
rval = trans.sa_session.query(trans.app.model.HistoryDatasetAssociation).get(value)
if isinstance(rval, list):
values = rval
else:
values = [rval]
values = util.listify(rval)
dataset_matcher = DatasetMatcher(trans, self, None, other_values)
for v in values:
if v:
if v.deleted:
raise ValueError("The previously selected dataset has been deleted.")
if hasattr(v, "dataset") and v.dataset.state in [galaxy.model.Dataset.states.ERROR, galaxy.model.Dataset.states.DISCARDED]:
elif hasattr(v, "dataset") and v.dataset.state in [galaxy.model.Dataset.states.ERROR, galaxy.model.Dataset.states.DISCARDED]:
raise ValueError("The previously selected dataset has entered an unusable state")
elif hasattr(v, "dataset"):
match = dataset_matcher.hda_match(v, check_security=False)
if match and match.implicit_conversion:
v.implicit_conversion = True
if not self.multiple:
if len(values) > 1:
raise ValueError("More than one dataset supplied to single input dataset parameter.")
+6 -1
View File
@@ -466,7 +466,12 @@ class ToolsTestCase(api.ApiTestCase):
'col': "' ; echo 'moo",
}
response = self._run("column_param", history_id, inputs)
assert response.status_code != 200
# This needs to either fail at submit time or at job prepare time, but we have
# to make sure the job doesn't run.
if response.status_code == 200:
job = response.json()["jobs"][0]
final_job_state = self.dataset_populator.wait_for_job(job["id"])
assert final_job_state == "error"
@skip_without_tool("collection_paired_test")
def test_collection_parameter(self):