mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #5702 from guerler/select_to_text
Relax validation condition for dynamic parameters
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.")
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user