galaxy-commits
Threads by month
- ----- 2026 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions
commit/galaxy-central: jmchilton: Merged in martenson/galaxy-stable-pr/stable (pull request #520)
by commits-noreply@bitbucket.org 08 Oct '14
by commits-noreply@bitbucket.org 08 Oct '14
08 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bde1c35ef8e5/
Changeset: bde1c35ef8e5
Branch: stable
User: jmchilton
Date: 2014-10-08 20:21:35+00:00
Summary: Merged in martenson/galaxy-stable-pr/stable (pull request #520)
[STABLE] missing import
Affected #: 1 file
diff -r e98b33105381ac94f590edee1859ab550d328833 -r bde1c35ef8e53d0436507c48ed9b08b1dc5b06a3 lib/tool_shed/metadata/repository_metadata_manager.py
--- a/lib/tool_shed/metadata/repository_metadata_manager.py
+++ b/lib/tool_shed/metadata/repository_metadata_manager.py
@@ -5,6 +5,7 @@
from galaxy import util
from galaxy.util import inflector
from galaxy.web.form_builder import SelectField
+from galaxy.model.orm import or_
from tool_shed.metadata import metadata_generator
from tool_shed.repository_types.metadata import TipOnly
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/3a193ffba363/
Changeset: 3a193ffba363
Branch: stable
User: martenson
Date: 2014-10-08 18:27:41+00:00
Summary: missing import
Affected #: 1 file
diff -r 007f6a80629a74650b72d67821a9505932d284f3 -r 3a193ffba363cf10224568986c2c1c192bc8bca1 lib/tool_shed/metadata/repository_metadata_manager.py
--- a/lib/tool_shed/metadata/repository_metadata_manager.py
+++ b/lib/tool_shed/metadata/repository_metadata_manager.py
@@ -5,6 +5,7 @@
from galaxy import util
from galaxy.util import inflector
from galaxy.web.form_builder import SelectField
+from galaxy.model.orm import or_
from tool_shed.metadata import metadata_generator
from tool_shed.repository_types.metadata import TipOnly
https://bitbucket.org/galaxy/galaxy-central/commits/bde1c35ef8e5/
Changeset: bde1c35ef8e5
Branch: stable
User: jmchilton
Date: 2014-10-08 20:21:35+00:00
Summary: Merged in martenson/galaxy-stable-pr/stable (pull request #520)
[STABLE] missing import
Affected #: 1 file
diff -r e98b33105381ac94f590edee1859ab550d328833 -r bde1c35ef8e53d0436507c48ed9b08b1dc5b06a3 lib/tool_shed/metadata/repository_metadata_manager.py
--- a/lib/tool_shed/metadata/repository_metadata_manager.py
+++ b/lib/tool_shed/metadata/repository_metadata_manager.py
@@ -5,6 +5,7 @@
from galaxy import util
from galaxy.util import inflector
from galaxy.web.form_builder import SelectField
+from galaxy.model.orm import or_
from tool_shed.metadata import metadata_generator
from tool_shed.repository_types.metadata import TipOnly
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: ToolForm: Temporary tool form activation.
by commits-noreply@bitbucket.org 08 Oct '14
by commits-noreply@bitbucket.org 08 Oct '14
08 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/05f112a611b6/
Changeset: 05f112a611b6
User: guerler
Date: 2014-10-08 19:50:57+00:00
Summary: ToolForm: Temporary tool form activation.
Affected #: 2 files
diff -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa -r 05f112a611b683c82acd6f5c4918cff299daf2c5 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -1235,7 +1235,7 @@
requires_setting_metadata = True
default_tool_action = DefaultToolAction
dict_collection_visible_keys = ( 'id', 'name', 'version', 'description' )
- default_template = 'tool_form.mako'
+ default_template = 'tool_form.api.mako'
def __init__( self, config_file, root, app, guid=None, repository_id=None ):
"""Load a tool from the config named by `config_file`"""
diff -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa -r 05f112a611b683c82acd6f5c4918cff299daf2c5 templates/webapps/galaxy/tool_form.mako
--- a/templates/webapps/galaxy/tool_form.mako
+++ b/templates/webapps/galaxy/tool_form.mako
@@ -1,4 +1,4 @@
-<%inherit file="/base.mako"/>
+##<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /><%namespace file="/base_panels.mako" import="overlay" />
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: ToolForm: Improve collection handling
by commits-noreply@bitbucket.org 08 Oct '14
by commits-noreply@bitbucket.org 08 Oct '14
08 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a979bd1bb194/
Changeset: a979bd1bb194
User: guerler
Date: 2014-10-08 18:32:48+00:00
Summary: ToolForm: Improve collection handling
Affected #: 18 files
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa client/galaxy/scripts/mvc/tools/tools-content.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/tools/tools-content.js
@@ -0,0 +1,132 @@
+define(['utils/utils'], function(Utils){
+ return Backbone.Model.extend({
+ // initialize
+ initialize: function(options) {
+ // backup basic url
+ this.base_url = galaxy_config.root + 'api/histories/' + options.history_id + '/contents';
+
+ // prepare content obects
+ this.datatypes = {};
+ this.summary = {};
+
+ // link this
+ var self = this;
+
+ // request datatypes
+ Utils.get({
+ url : galaxy_config.root + 'api/datatypes/mapping',
+ cache : true,
+ success : function(response) {
+ // backup datatype dictionary
+ self.datatypes = response;
+
+ // get history summary
+ Utils.get({
+ url : self.base_url + '?deleted=false',
+ success : function(response) {
+ // backup summary
+ self.summary = response;
+
+ // log
+ console.debug('tools-content::initialize() - Completed.');
+
+ // callback
+ options.success && options.success();
+ },
+ error : function(response) {
+ // log request failure
+ console.debug('tools-content::initialize() - Ajax request for summary failed.');
+ console.debug(response);
+ }
+ });
+ },
+ error : function(response) {
+ // log request failure
+ console.debug('tools-content::initialize() - Ajax request for datatypes failed.');
+ console.debug(response);
+ }
+ });
+ },
+
+ /**
+ * Filters contents by data type.
+ */
+ filterType: function(options) {
+ // initialize parameters
+ options = options || {};
+ var result = [];
+
+ // identify content type
+ var history_content_type = 'dataset';
+ if (options.src== 'hdca') {
+ history_content_type = 'dataset_collection';
+ }
+
+ // search in summary
+ for (var i in this.summary) {
+ var content = this.summary[i];
+
+ // match datatypes
+ var found = false;
+ for (var i in options.extensions) {
+ if (this._matchType(options.extensions[i], content.extension)) {
+ found = true;
+ break;
+ }
+ }
+
+ // final match result
+ if ((content.history_content_type === history_content_type) && (found || !options.extensions)) {
+ result.push(content);
+ }
+ }
+ return result;
+ },
+
+ /** Get details of a content by id.
+ */
+ getDetails: function(options) {
+ var api_url = this.base_url + '/datasets/' + options.id;
+ if (options.src == 'hdca') {
+ api_url = this.base_url + '/dataset_collections/' + options.id;
+ }
+ Utils.get({
+ url : api_url,
+ success : function(response) {
+ options.success && options.success(response);
+ },
+ error : function(response) {
+ console.debug('tools-content::getDetails() - Ajax request for content failed.');
+ console.debug(response);
+ }
+ });
+ },
+
+ /** Check if datatypes match
+ */
+ _matchType: function(target, reference) {
+ // check if target class is available
+ var target_class = this.datatypes.ext_to_class_name[target];
+ if (!target_class) {
+ console.debug('tools-content::_matchType() - Specific target class unavailable. Accepting all formats.');
+ return true;
+ }
+
+ // check if reference class is available
+ var reference_class = this.datatypes.ext_to_class_name[reference];
+ if (!reference_class) {
+ console.debug('tools-content::_matchType() - Specific reference class unavailable. Accepting all formats.');
+ return true;
+ }
+
+ // check reference group
+ var reference_group = this.datatypes.class_to_classes[reference_class];
+ if (reference_group[target_class]) {
+ return true;
+ }
+
+ // classes do not match
+ return false;
+ }
+ });
+});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa client/galaxy/scripts/mvc/tools/tools-datasets.js
--- a/client/galaxy/scripts/mvc/tools/tools-datasets.js
+++ /dev/null
@@ -1,117 +0,0 @@
-define(['utils/utils'], function(Utils){
- return Backbone.Model.extend({
- // initialize
- initialize: function(options) {
- // prepare datasets obects
- this.datatypes = {};
- this.summary = {};
-
- // link this
- var self = this;
-
- // request datatypes
- Utils.get({
- url : galaxy_config.root + 'api/datatypes/mapping',
- cache : true,
- success : function(response) {
- // backup datatype dictionary
- self.datatypes = response;
-
- // get history summary
- Utils.get({
- url : galaxy_config.root + 'api/histories/' + options.history_id + '/contents?deleted=false',
- success : function(response) {
- // backup summary
- self.summary = response;
-
- // log
- console.debug('tools-datasets::initialize() - Completed.');
-
- // callback
- options.success && options.success();
- },
- error : function(response) {
- // log request failure
- console.debug('tools-datasets::initialize() - Ajax request for summary failed.');
- console.debug(response);
- }
- });
- },
- error : function(response) {
- // log request failure
- console.debug('tools-datasets::initialize() - Ajax request for datatypes failed.');
- console.debug(response);
- }
- });
- },
-
- /**
- * Filters datasets by data type.
- */
- filterType: function(options) {
- options = options || {};
- var result = [];
- for (var i in this.summary) {
- var dataset = this.summary[i];
-
- // match datatypes
- var found = false;
- for (var i in options.data_types) {
- if (this._matchType(options.data_types[i], dataset.extension)) {
- found = true;
- break;
- }
- }
-
- // final match result
- if ((dataset.history_content_type === options.content_type || !options.content_type) && (found || !options.data_types)) {
- result.push(dataset);
- }
- }
- return result;
- },
-
- /** Get details of a dataset by id.
- * @param{String} Dataset id
- */
- getDetails: function(dataset_id, callback) {
- Utils.get({
- url : galaxy_config.root + 'api/datasets/' + dataset_id,
- success : function(response) {
- callback && callback(response);
- },
- error : function(response) {
- console.debug('tools-datasets::getDetails() - Ajax request for dataset failed.');
- console.debug(response);
- }
- });
- },
-
- /** Check if datatypes match
- */
- _matchType: function(target, reference) {
- // check if target class is available
- var target_class = this.datatypes.ext_to_class_name[target];
- if (!target_class) {
- console.debug('tools-datasets::_matchType() - Specific target class unavailable. Accepting all formats.');
- return true;
- }
-
- // check if reference class is available
- var reference_class = this.datatypes.ext_to_class_name[reference];
- if (!reference_class) {
- console.debug('tools-datasets::_matchType() - Specific reference class unavailable. Accepting all formats.');
- return true;
- }
-
- // check reference group
- var reference_group = this.datatypes.class_to_classes[reference_class];
- if (reference_group[target_class]) {
- return true;
- }
-
- // classes do not match
- return false;
- }
- });
-});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa client/galaxy/scripts/mvc/tools/tools-form.js
--- a/client/galaxy/scripts/mvc/tools/tools-form.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form.js
@@ -3,9 +3,9 @@
*/
define(['mvc/ui/ui-portlet', 'mvc/ui/ui-misc',
'mvc/citation/citation-model', 'mvc/citation/citation-view',
- 'mvc/tools', 'mvc/tools/tools-template', 'mvc/tools/tools-datasets', 'mvc/tools/tools-section', 'mvc/tools/tools-tree', 'mvc/tools/tools-jobs'],
+ 'mvc/tools', 'mvc/tools/tools-template', 'mvc/tools/tools-content', 'mvc/tools/tools-section', 'mvc/tools/tools-tree', 'mvc/tools/tools-jobs'],
function(Portlet, Ui, CitationModel, CitationView,
- Tools, ToolTemplate, ToolDatasets, ToolSection, ToolTree, ToolJobs) {
+ Tools, ToolTemplate, ToolContent, ToolSection, ToolTree, ToolJobs) {
// create tool model
var Model = Backbone.Model.extend({
@@ -61,8 +61,8 @@
// reset input element list, which contains the dom elements of each input element (includes also the input field)
this.element_list = {};
- // initialize datasets
- this.datasets = new ToolDatasets({
+ // initialize contents
+ this.content = new ToolContent({
history_id : this.options.history_id,
success : function() {
self._initializeToolForm();
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa client/galaxy/scripts/mvc/tools/tools-section.js
--- a/client/galaxy/scripts/mvc/tools/tools-section.js
+++ b/client/galaxy/scripts/mvc/tools/tools-section.js
@@ -1,8 +1,8 @@
/**
This class creates a tool form section and populates it with input elements. It also handles repeat blocks and conditionals by recursively creating new sub sections. New input elements can be plugged in by adding cases to the switch block defined in the _addRow() function.
*/
-define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/tools/tools-repeat', 'mvc/tools/tools-select-dataset'],
- function(Utils, Table, Ui, Repeat, SelectDataset) {
+define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/tools/tools-repeat', 'mvc/tools/tools-select-content'],
+ function(Utils, Table, Ui, Repeat, SelectContent) {
// input field element wrapper
var InputElement = Backbone.View.extend({
@@ -268,12 +268,12 @@
field = this._fieldSelect(input_def);
break;
- // dataset
+ // data selector
case 'data':
field = this._fieldData(input_def);
break;
- // dataset column
+ // data column
case 'data_column':
field = this._fieldSelect(input_def);
break;
@@ -417,13 +417,15 @@
var id = input_def.id;
// select field
- return new SelectDataset.View(this.app, {
+ return new SelectContent.View(this.app, {
id : 'field-' + id,
extensions : input_def.extensions,
multiple : input_def.multiple,
onchange : function(dict) {
- // pick the first dataset only (todo: maybe collect multiple meta information)
- var value = dict.values[0].id;
+ // pick the first content only (todo: maybe collect multiple meta information)
+ var content_def = dict.values[0];
+ var content_id = content_def.id;
+ var content_src = content_def.src;
// get referenced columns
var column_list = self.app.tree.references(id, 'data_column');
@@ -440,71 +442,80 @@
column_field.wait && column_field.wait();
}
- // find selected dataset
- self.app.datasets.getDetails(value, function(dataset) {
- // meta data
- var meta = null;
-
- // check dataset
- if (dataset) {
- // log selection
- console.debug('tool-form::field_data() - Selected dataset ' + value + '.');
-
- // get meta data
- meta = dataset.metadata_column_types;
-
- // check meta data
- if (!meta) {
- console.debug('tool-form::field_data() - FAILED: Could not find metadata for dataset ' + value + '.');
+ // find selected content
+ self.app.content.getDetails({
+ id : content_id,
+ src : content_src,
+ success : function(content) {
+ // select the first dataset to represent collections
+ if (content_src == 'hdca' && content.elements && content.elements.length > 0) {
+ content = content.elements[0].object;
}
- } else {
- console.debug('tool-form::field_data() - FAILED: Could not find dataset ' + value + '.');
- }
-
- // update referenced columns
- for (var i in column_list) {
- // get column input/field
- var column_input = self.app.input_list[column_list[i]];
- var column_field = self.app.field_list[column_list[i]];
- if (!column_input || !column_field) {
- console.debug('tool-form::field_data() - FAILED: Column not found.');
+
+ // meta data
+ var meta = null;
+
+ // check content
+ if (content) {
+ // log selection
+ console.debug('tool-form::field_data() - Selected content ' + content_id + '.');
+
+ // get meta data
+ meta = content.metadata_column_types;
+
+ // check meta data
+ if (!meta) {
+ console.debug('tool-form::field_data() - FAILED: Could not find metadata for content ' + content_id + '.');
+ }
+ } else {
+ console.debug('tool-form::field_data() - FAILED: Could not find content ' + content_id + '.');
}
-
- // is numerical?
- var numerical = column_input.numerical;
- // identify column options
- var columns = [];
- for (var key in meta) {
- // get column type
- var column_type = meta[key];
+ // update referenced columns
+ for (var i in column_list) {
+ // get column input/field
+ var column_input = self.app.input_list[column_list[i]];
+ var column_field = self.app.field_list[column_list[i]];
+ if (!column_input || !column_field) {
+ console.debug('tool-form::field_data() - FAILED: Column not found.');
+ }
+
+ // is numerical?
+ var numerical = column_input.numerical;
- // column index
- var column_index = (parseInt(key) + 1);
-
- // column type label
- var column_label = 'Text';
- if (column_type == 'int' || column_type == 'float') {
- column_label = 'Number';
+ // identify column options
+ var columns = [];
+ for (var key in meta) {
+ // get column type
+ var column_type = meta[key];
+
+ // column index
+ var column_index = (parseInt(key) + 1);
+
+ // column type label
+ var column_label = 'Text';
+ if (column_type == 'int' || column_type == 'float') {
+ column_label = 'Number';
+ }
+
+ // add to selection
+ if (column_type == 'int' || column_type == 'float' || !numerical) {
+ columns.push({
+ 'label' : 'Column: ' + column_index + ' [' + column_label + ']',
+ 'value' : column_index
+ });
+ }
}
- // add to selection
- if (column_type == 'int' || column_type == 'float' || !numerical) {
- columns.push({
- 'label' : 'Column: ' + column_index + ' [' + column_label + ']',
- 'value' : column_index
- });
+ // update field
+ if (column_field) {
+ column_field.update(columns);
+ if (!column_field.exists(column_field.value())) {
+ column_field.value(column_field.first());
+ }
+ column_field.show();
}
}
-
- // update field
- if (column_field) {
- column_field.update(columns);
- if (!column_field.exists(column_field.value())) {
- column_field.value(column_field.first());
- }
- column_field.show();
- }
}
});
}
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa client/galaxy/scripts/mvc/tools/tools-select-content.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/tools/tools-select-content.js
@@ -0,0 +1,172 @@
+// dependencies
+define(['utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs', 'mvc/tools/tools-template'], function(Utils, Ui, Tabs, ToolTemplate) {
+
+var View = Backbone.View.extend({
+ // initialize
+ initialize : function(app, options) {
+ // configure options
+ this.options = options;
+
+ // link this
+ var self = this;
+
+ // add element
+ this.setElement('<div/>');
+
+ // current selection
+ this.current = 'hda';
+
+ // create button
+ this.button_new = new Ui.RadioButton.View({
+ value : this.current,
+ data : [ { icon: 'fa-file-o', label : 'Select datasets', value : 'hda' },
+ { icon: 'fa-files-o', label : 'Select a collection', value : 'hdca' }],
+ onchange: function(value) {
+ self.current = value;
+ self.refresh();
+ self.trigger('change');
+ }
+ });
+
+ //
+ // datasets
+ //
+ var datasets = app.content.filterType({
+ src : 'hda',
+ extensions : options.extensions
+ });
+
+ // configure options fields
+ var dataset_options = [];
+ for (var i in datasets) {
+ dataset_options.push({
+ label: datasets[i].name,
+ value: datasets[i].id
+ });
+ }
+
+ // select field
+ this.select_datasets = new Ui.Select.View({
+ multiple : true,
+ data : dataset_options,
+ value : dataset_options[0] && dataset_options[0].value,
+ onchange : function() {
+ self.trigger('change');
+ }
+ });
+
+ //
+ // collections
+ //
+ var collections = app.content.filterType({
+ src : 'hdca',
+ extensions : options.extensions
+ });
+
+ // configure options fields
+ var collection_options = [];
+ for (var i in collections) {
+ collection_options.push({
+ label: collections[i].name,
+ value: collections[i].id
+ });
+ }
+
+ // create select field for collections
+ this.select_collection = new Ui.Select.View({
+ data : collection_options,
+ value : collection_options[0] && collection_options[0].value,
+ onchange : function() {
+ self.trigger('change');
+ }
+ });
+
+ // add elements to dom
+ this.$el.append(Utils.wrap(this.button_new.$el));
+ this.$el.append(this.select_datasets.$el);
+ this.$el.append(this.select_collection.$el);
+
+ // check for batch mode
+ if (!this.options.multiple) {
+ this.$el.append(ToolTemplate.batchMode());
+ }
+
+ // refresh view
+ this.refresh();
+
+ // add change event. fires on trigger
+ this.on('change', function() {
+ if (options.onchange) {
+ options.onchange(self.value());
+ }
+ });
+ },
+
+ /** Return the currently selected dataset values */
+ value : function () {
+ // identify select element
+ var select = null;
+ switch(this.current) {
+ case 'hda':
+ select = this.select_datasets;
+ break;
+ case 'hdca':
+ select = this.select_collection;
+ break;
+ }
+
+ // transform into an array
+ var id_list = select.value();
+ if (!(id_list instanceof Array)) {
+ id_list = [id_list];
+ }
+
+ // prepare result dict
+ var result = {
+ batch : !this.options.multiple,
+ values : []
+ }
+
+ // append to dataset ids
+ for (var i in id_list) {
+ result.values.push({
+ id : id_list[i],
+ src : this.current
+ });
+ }
+
+ // return
+ return result;
+ },
+
+ /** Validate current selection
+ */
+ validate: function() {
+ switch(this.current) {
+ case 'hda':
+ return this.select_datasets.validate();
+ case 'hdca':
+ return this.select_collection.validate();
+ }
+ },
+
+ /** Refreshes data selection view */
+ refresh: function() {
+ switch (this.current) {
+ case 'hda':
+ this.select_datasets.$el.fadeIn();
+ this.select_collection.$el.hide();
+ break;
+ case 'hdca':
+ this.select_datasets.$el.hide();
+ this.select_collection.$el.fadeIn();
+ break;
+ }
+ }
+});
+
+return {
+ View: View
+}
+
+});
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa client/galaxy/scripts/mvc/tools/tools-select-dataset.js
--- a/client/galaxy/scripts/mvc/tools/tools-select-dataset.js
+++ /dev/null
@@ -1,172 +0,0 @@
-// dependencies
-define(['utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs', 'mvc/tools/tools-template'], function(Utils, Ui, Tabs, ToolTemplate) {
-
-var View = Backbone.View.extend({
- // initialize
- initialize : function(app, options) {
- // configure options
- this.options = options;
-
- // link this
- var self = this;
-
- // add element
- this.setElement('<div/>');
-
- // current selection
- this.current = 'hda';
-
- // create button
- this.button_new = new Ui.RadioButton.View({
- value : this.current,
- data : [ { icon: 'fa-file-o', label : 'Select datasets', value : 'hda' },
- { icon: 'fa-files-o', label : 'Select a collection', value : 'hdca' }],
- onchange: function(value) {
- self.current = value;
- self.refresh();
- self.trigger('change');
- }
- });
-
- //
- // datasets
- //
- var datasets = app.datasets.filterType({
- content_type : 'dataset',
- data_types : options.extensions
- });
-
- // configure options fields
- var dataset_options = [];
- for (var i in datasets) {
- dataset_options.push({
- label: datasets[i].name,
- value: datasets[i].id
- });
- }
-
- // select field
- this.select_datasets = new Ui.Select.View({
- multiple : true,
- data : dataset_options,
- value : dataset_options[0] && dataset_options[0].value,
- onchange : function() {
- self.trigger('change');
- }
- });
-
- //
- // collections
- //
- var collections = app.datasets.filterType({
- content_type : 'collection',
- data_types : options.extensions
- });
-
- // configure options fields
- var collection_options = [];
- for (var i in collections) {
- collection_options.push({
- label: collections[i].name,
- value: collections[i].id
- });
- }
-
- // create select field for collections
- this.select_collection = new Ui.Select.View({
- data : collection_options,
- value : collection_options[0] && collection_options[0].value,
- onchange : function() {
- self.trigger('change');
- }
- });
-
- // add elements to dom
- this.$el.append(Utils.wrap(this.button_new.$el));
- this.$el.append(this.select_datasets.$el);
- this.$el.append(this.select_collection.$el);
-
- // check for batch mode
- if (!this.options.multiple) {
- this.$el.append(ToolTemplate.batchMode());
- }
-
- // refresh view
- this.refresh();
-
- // add change event. fires on trigger
- this.on('change', function() {
- if (options.onchange) {
- options.onchange(self.value());
- }
- });
- },
-
- /** Return the currently selected dataset values */
- value : function () {
- // identify select element
- var select = null;
- switch(this.current) {
- case 'hda':
- select = this.select_datasets;
- break;
- case 'hdca':
- select = this.select_collection;
- break;
- }
-
- // transform into an array
- var id_list = select.value();
- if (!(id_list instanceof Array)) {
- id_list = [id_list];
- }
-
- // prepare result dict
- var result = {
- batch : !this.options.multiple,
- values : []
- }
-
- // append to dataset ids
- for (var i in id_list) {
- result.values.push({
- id : id_list[i],
- src : this.current
- });
- }
-
- // return
- return result;
- },
-
- /** Validate current selection
- */
- validate: function() {
- switch(this.current) {
- case 'hda':
- return this.select_datasets.validate();
- case 'hdca':
- return this.select_collection.validate();
- }
- },
-
- /** Refreshes data selection view */
- refresh: function() {
- switch (this.current) {
- case 'hda':
- this.select_datasets.$el.fadeIn();
- this.select_collection.$el.hide();
- break;
- case 'hdca':
- this.select_datasets.$el.hide();
- this.select_collection.$el.fadeIn();
- break;
- }
- }
-});
-
-return {
- View: View
-}
-
-});
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/mvc/tools/tools-content.js
--- /dev/null
+++ b/static/scripts/mvc/tools/tools-content.js
@@ -0,0 +1,132 @@
+define(['utils/utils'], function(Utils){
+ return Backbone.Model.extend({
+ // initialize
+ initialize: function(options) {
+ // backup basic url
+ this.base_url = galaxy_config.root + 'api/histories/' + options.history_id + '/contents';
+
+ // prepare content obects
+ this.datatypes = {};
+ this.summary = {};
+
+ // link this
+ var self = this;
+
+ // request datatypes
+ Utils.get({
+ url : galaxy_config.root + 'api/datatypes/mapping',
+ cache : true,
+ success : function(response) {
+ // backup datatype dictionary
+ self.datatypes = response;
+
+ // get history summary
+ Utils.get({
+ url : self.base_url + '?deleted=false',
+ success : function(response) {
+ // backup summary
+ self.summary = response;
+
+ // log
+ console.debug('tools-content::initialize() - Completed.');
+
+ // callback
+ options.success && options.success();
+ },
+ error : function(response) {
+ // log request failure
+ console.debug('tools-content::initialize() - Ajax request for summary failed.');
+ console.debug(response);
+ }
+ });
+ },
+ error : function(response) {
+ // log request failure
+ console.debug('tools-content::initialize() - Ajax request for datatypes failed.');
+ console.debug(response);
+ }
+ });
+ },
+
+ /**
+ * Filters contents by data type.
+ */
+ filterType: function(options) {
+ // initialize parameters
+ options = options || {};
+ var result = [];
+
+ // identify content type
+ var history_content_type = 'dataset';
+ if (options.src== 'hdca') {
+ history_content_type = 'dataset_collection';
+ }
+
+ // search in summary
+ for (var i in this.summary) {
+ var content = this.summary[i];
+
+ // match datatypes
+ var found = false;
+ for (var i in options.extensions) {
+ if (this._matchType(options.extensions[i], content.extension)) {
+ found = true;
+ break;
+ }
+ }
+
+ // final match result
+ if ((content.history_content_type === history_content_type) && (found || !options.extensions)) {
+ result.push(content);
+ }
+ }
+ return result;
+ },
+
+ /** Get details of a content by id.
+ */
+ getDetails: function(options) {
+ var api_url = this.base_url + '/datasets/' + options.id;
+ if (options.src == 'hdca') {
+ api_url = this.base_url + '/dataset_collections/' + options.id;
+ }
+ Utils.get({
+ url : api_url,
+ success : function(response) {
+ options.success && options.success(response);
+ },
+ error : function(response) {
+ console.debug('tools-content::getDetails() - Ajax request for content failed.');
+ console.debug(response);
+ }
+ });
+ },
+
+ /** Check if datatypes match
+ */
+ _matchType: function(target, reference) {
+ // check if target class is available
+ var target_class = this.datatypes.ext_to_class_name[target];
+ if (!target_class) {
+ console.debug('tools-content::_matchType() - Specific target class unavailable. Accepting all formats.');
+ return true;
+ }
+
+ // check if reference class is available
+ var reference_class = this.datatypes.ext_to_class_name[reference];
+ if (!reference_class) {
+ console.debug('tools-content::_matchType() - Specific reference class unavailable. Accepting all formats.');
+ return true;
+ }
+
+ // check reference group
+ var reference_group = this.datatypes.class_to_classes[reference_class];
+ if (reference_group[target_class]) {
+ return true;
+ }
+
+ // classes do not match
+ return false;
+ }
+ });
+});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/mvc/tools/tools-datasets.js
--- a/static/scripts/mvc/tools/tools-datasets.js
+++ /dev/null
@@ -1,117 +0,0 @@
-define(['utils/utils'], function(Utils){
- return Backbone.Model.extend({
- // initialize
- initialize: function(options) {
- // prepare datasets obects
- this.datatypes = {};
- this.summary = {};
-
- // link this
- var self = this;
-
- // request datatypes
- Utils.get({
- url : galaxy_config.root + 'api/datatypes/mapping',
- cache : true,
- success : function(response) {
- // backup datatype dictionary
- self.datatypes = response;
-
- // get history summary
- Utils.get({
- url : galaxy_config.root + 'api/histories/' + options.history_id + '/contents?deleted=false',
- success : function(response) {
- // backup summary
- self.summary = response;
-
- // log
- console.debug('tools-datasets::initialize() - Completed.');
-
- // callback
- options.success && options.success();
- },
- error : function(response) {
- // log request failure
- console.debug('tools-datasets::initialize() - Ajax request for summary failed.');
- console.debug(response);
- }
- });
- },
- error : function(response) {
- // log request failure
- console.debug('tools-datasets::initialize() - Ajax request for datatypes failed.');
- console.debug(response);
- }
- });
- },
-
- /**
- * Filters datasets by data type.
- */
- filterType: function(options) {
- options = options || {};
- var result = [];
- for (var i in this.summary) {
- var dataset = this.summary[i];
-
- // match datatypes
- var found = false;
- for (var i in options.data_types) {
- if (this._matchType(options.data_types[i], dataset.extension)) {
- found = true;
- break;
- }
- }
-
- // final match result
- if ((dataset.history_content_type === options.content_type || !options.content_type) && (found || !options.data_types)) {
- result.push(dataset);
- }
- }
- return result;
- },
-
- /** Get details of a dataset by id.
- * @param{String} Dataset id
- */
- getDetails: function(dataset_id, callback) {
- Utils.get({
- url : galaxy_config.root + 'api/datasets/' + dataset_id,
- success : function(response) {
- callback && callback(response);
- },
- error : function(response) {
- console.debug('tools-datasets::getDetails() - Ajax request for dataset failed.');
- console.debug(response);
- }
- });
- },
-
- /** Check if datatypes match
- */
- _matchType: function(target, reference) {
- // check if target class is available
- var target_class = this.datatypes.ext_to_class_name[target];
- if (!target_class) {
- console.debug('tools-datasets::_matchType() - Specific target class unavailable. Accepting all formats.');
- return true;
- }
-
- // check if reference class is available
- var reference_class = this.datatypes.ext_to_class_name[reference];
- if (!reference_class) {
- console.debug('tools-datasets::_matchType() - Specific reference class unavailable. Accepting all formats.');
- return true;
- }
-
- // check reference group
- var reference_group = this.datatypes.class_to_classes[reference_class];
- if (reference_group[target_class]) {
- return true;
- }
-
- // classes do not match
- return false;
- }
- });
-});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/mvc/tools/tools-form.js
--- a/static/scripts/mvc/tools/tools-form.js
+++ b/static/scripts/mvc/tools/tools-form.js
@@ -3,9 +3,9 @@
*/
define(['mvc/ui/ui-portlet', 'mvc/ui/ui-misc',
'mvc/citation/citation-model', 'mvc/citation/citation-view',
- 'mvc/tools', 'mvc/tools/tools-template', 'mvc/tools/tools-datasets', 'mvc/tools/tools-section', 'mvc/tools/tools-tree', 'mvc/tools/tools-jobs'],
+ 'mvc/tools', 'mvc/tools/tools-template', 'mvc/tools/tools-content', 'mvc/tools/tools-section', 'mvc/tools/tools-tree', 'mvc/tools/tools-jobs'],
function(Portlet, Ui, CitationModel, CitationView,
- Tools, ToolTemplate, ToolDatasets, ToolSection, ToolTree, ToolJobs) {
+ Tools, ToolTemplate, ToolContent, ToolSection, ToolTree, ToolJobs) {
// create tool model
var Model = Backbone.Model.extend({
@@ -61,8 +61,8 @@
// reset input element list, which contains the dom elements of each input element (includes also the input field)
this.element_list = {};
- // initialize datasets
- this.datasets = new ToolDatasets({
+ // initialize contents
+ this.content = new ToolContent({
history_id : this.options.history_id,
success : function() {
self._initializeToolForm();
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/mvc/tools/tools-section.js
--- a/static/scripts/mvc/tools/tools-section.js
+++ b/static/scripts/mvc/tools/tools-section.js
@@ -1,8 +1,8 @@
/**
This class creates a tool form section and populates it with input elements. It also handles repeat blocks and conditionals by recursively creating new sub sections. New input elements can be plugged in by adding cases to the switch block defined in the _addRow() function.
*/
-define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/tools/tools-repeat', 'mvc/tools/tools-select-dataset'],
- function(Utils, Table, Ui, Repeat, SelectDataset) {
+define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/tools/tools-repeat', 'mvc/tools/tools-select-content'],
+ function(Utils, Table, Ui, Repeat, SelectContent) {
// input field element wrapper
var InputElement = Backbone.View.extend({
@@ -268,12 +268,12 @@
field = this._fieldSelect(input_def);
break;
- // dataset
+ // data selector
case 'data':
field = this._fieldData(input_def);
break;
- // dataset column
+ // data column
case 'data_column':
field = this._fieldSelect(input_def);
break;
@@ -417,13 +417,15 @@
var id = input_def.id;
// select field
- return new SelectDataset.View(this.app, {
+ return new SelectContent.View(this.app, {
id : 'field-' + id,
extensions : input_def.extensions,
multiple : input_def.multiple,
onchange : function(dict) {
- // pick the first dataset only (todo: maybe collect multiple meta information)
- var value = dict.values[0].id;
+ // pick the first content only (todo: maybe collect multiple meta information)
+ var content_def = dict.values[0];
+ var content_id = content_def.id;
+ var content_src = content_def.src;
// get referenced columns
var column_list = self.app.tree.references(id, 'data_column');
@@ -440,71 +442,80 @@
column_field.wait && column_field.wait();
}
- // find selected dataset
- self.app.datasets.getDetails(value, function(dataset) {
- // meta data
- var meta = null;
-
- // check dataset
- if (dataset) {
- // log selection
- console.debug('tool-form::field_data() - Selected dataset ' + value + '.');
-
- // get meta data
- meta = dataset.metadata_column_types;
-
- // check meta data
- if (!meta) {
- console.debug('tool-form::field_data() - FAILED: Could not find metadata for dataset ' + value + '.');
+ // find selected content
+ self.app.content.getDetails({
+ id : content_id,
+ src : content_src,
+ success : function(content) {
+ // select the first dataset to represent collections
+ if (content_src == 'hdca' && content.elements && content.elements.length > 0) {
+ content = content.elements[0].object;
}
- } else {
- console.debug('tool-form::field_data() - FAILED: Could not find dataset ' + value + '.');
- }
-
- // update referenced columns
- for (var i in column_list) {
- // get column input/field
- var column_input = self.app.input_list[column_list[i]];
- var column_field = self.app.field_list[column_list[i]];
- if (!column_input || !column_field) {
- console.debug('tool-form::field_data() - FAILED: Column not found.');
+
+ // meta data
+ var meta = null;
+
+ // check content
+ if (content) {
+ // log selection
+ console.debug('tool-form::field_data() - Selected content ' + content_id + '.');
+
+ // get meta data
+ meta = content.metadata_column_types;
+
+ // check meta data
+ if (!meta) {
+ console.debug('tool-form::field_data() - FAILED: Could not find metadata for content ' + content_id + '.');
+ }
+ } else {
+ console.debug('tool-form::field_data() - FAILED: Could not find content ' + content_id + '.');
}
-
- // is numerical?
- var numerical = column_input.numerical;
- // identify column options
- var columns = [];
- for (var key in meta) {
- // get column type
- var column_type = meta[key];
+ // update referenced columns
+ for (var i in column_list) {
+ // get column input/field
+ var column_input = self.app.input_list[column_list[i]];
+ var column_field = self.app.field_list[column_list[i]];
+ if (!column_input || !column_field) {
+ console.debug('tool-form::field_data() - FAILED: Column not found.');
+ }
+
+ // is numerical?
+ var numerical = column_input.numerical;
- // column index
- var column_index = (parseInt(key) + 1);
-
- // column type label
- var column_label = 'Text';
- if (column_type == 'int' || column_type == 'float') {
- column_label = 'Number';
+ // identify column options
+ var columns = [];
+ for (var key in meta) {
+ // get column type
+ var column_type = meta[key];
+
+ // column index
+ var column_index = (parseInt(key) + 1);
+
+ // column type label
+ var column_label = 'Text';
+ if (column_type == 'int' || column_type == 'float') {
+ column_label = 'Number';
+ }
+
+ // add to selection
+ if (column_type == 'int' || column_type == 'float' || !numerical) {
+ columns.push({
+ 'label' : 'Column: ' + column_index + ' [' + column_label + ']',
+ 'value' : column_index
+ });
+ }
}
- // add to selection
- if (column_type == 'int' || column_type == 'float' || !numerical) {
- columns.push({
- 'label' : 'Column: ' + column_index + ' [' + column_label + ']',
- 'value' : column_index
- });
+ // update field
+ if (column_field) {
+ column_field.update(columns);
+ if (!column_field.exists(column_field.value())) {
+ column_field.value(column_field.first());
+ }
+ column_field.show();
}
}
-
- // update field
- if (column_field) {
- column_field.update(columns);
- if (!column_field.exists(column_field.value())) {
- column_field.value(column_field.first());
- }
- column_field.show();
- }
}
});
}
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/mvc/tools/tools-select-content.js
--- /dev/null
+++ b/static/scripts/mvc/tools/tools-select-content.js
@@ -0,0 +1,172 @@
+// dependencies
+define(['utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs', 'mvc/tools/tools-template'], function(Utils, Ui, Tabs, ToolTemplate) {
+
+var View = Backbone.View.extend({
+ // initialize
+ initialize : function(app, options) {
+ // configure options
+ this.options = options;
+
+ // link this
+ var self = this;
+
+ // add element
+ this.setElement('<div/>');
+
+ // current selection
+ this.current = 'hda';
+
+ // create button
+ this.button_new = new Ui.RadioButton.View({
+ value : this.current,
+ data : [ { icon: 'fa-file-o', label : 'Select datasets', value : 'hda' },
+ { icon: 'fa-files-o', label : 'Select a collection', value : 'hdca' }],
+ onchange: function(value) {
+ self.current = value;
+ self.refresh();
+ self.trigger('change');
+ }
+ });
+
+ //
+ // datasets
+ //
+ var datasets = app.content.filterType({
+ src : 'hda',
+ extensions : options.extensions
+ });
+
+ // configure options fields
+ var dataset_options = [];
+ for (var i in datasets) {
+ dataset_options.push({
+ label: datasets[i].name,
+ value: datasets[i].id
+ });
+ }
+
+ // select field
+ this.select_datasets = new Ui.Select.View({
+ multiple : true,
+ data : dataset_options,
+ value : dataset_options[0] && dataset_options[0].value,
+ onchange : function() {
+ self.trigger('change');
+ }
+ });
+
+ //
+ // collections
+ //
+ var collections = app.content.filterType({
+ src : 'hdca',
+ extensions : options.extensions
+ });
+
+ // configure options fields
+ var collection_options = [];
+ for (var i in collections) {
+ collection_options.push({
+ label: collections[i].name,
+ value: collections[i].id
+ });
+ }
+
+ // create select field for collections
+ this.select_collection = new Ui.Select.View({
+ data : collection_options,
+ value : collection_options[0] && collection_options[0].value,
+ onchange : function() {
+ self.trigger('change');
+ }
+ });
+
+ // add elements to dom
+ this.$el.append(Utils.wrap(this.button_new.$el));
+ this.$el.append(this.select_datasets.$el);
+ this.$el.append(this.select_collection.$el);
+
+ // check for batch mode
+ if (!this.options.multiple) {
+ this.$el.append(ToolTemplate.batchMode());
+ }
+
+ // refresh view
+ this.refresh();
+
+ // add change event. fires on trigger
+ this.on('change', function() {
+ if (options.onchange) {
+ options.onchange(self.value());
+ }
+ });
+ },
+
+ /** Return the currently selected dataset values */
+ value : function () {
+ // identify select element
+ var select = null;
+ switch(this.current) {
+ case 'hda':
+ select = this.select_datasets;
+ break;
+ case 'hdca':
+ select = this.select_collection;
+ break;
+ }
+
+ // transform into an array
+ var id_list = select.value();
+ if (!(id_list instanceof Array)) {
+ id_list = [id_list];
+ }
+
+ // prepare result dict
+ var result = {
+ batch : !this.options.multiple,
+ values : []
+ }
+
+ // append to dataset ids
+ for (var i in id_list) {
+ result.values.push({
+ id : id_list[i],
+ src : this.current
+ });
+ }
+
+ // return
+ return result;
+ },
+
+ /** Validate current selection
+ */
+ validate: function() {
+ switch(this.current) {
+ case 'hda':
+ return this.select_datasets.validate();
+ case 'hdca':
+ return this.select_collection.validate();
+ }
+ },
+
+ /** Refreshes data selection view */
+ refresh: function() {
+ switch (this.current) {
+ case 'hda':
+ this.select_datasets.$el.fadeIn();
+ this.select_collection.$el.hide();
+ break;
+ case 'hdca':
+ this.select_datasets.$el.hide();
+ this.select_collection.$el.fadeIn();
+ break;
+ }
+ }
+});
+
+return {
+ View: View
+}
+
+});
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/mvc/tools/tools-select-dataset.js
--- a/static/scripts/mvc/tools/tools-select-dataset.js
+++ /dev/null
@@ -1,172 +0,0 @@
-// dependencies
-define(['utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs', 'mvc/tools/tools-template'], function(Utils, Ui, Tabs, ToolTemplate) {
-
-var View = Backbone.View.extend({
- // initialize
- initialize : function(app, options) {
- // configure options
- this.options = options;
-
- // link this
- var self = this;
-
- // add element
- this.setElement('<div/>');
-
- // current selection
- this.current = 'hda';
-
- // create button
- this.button_new = new Ui.RadioButton.View({
- value : this.current,
- data : [ { icon: 'fa-file-o', label : 'Select datasets', value : 'hda' },
- { icon: 'fa-files-o', label : 'Select a collection', value : 'hdca' }],
- onchange: function(value) {
- self.current = value;
- self.refresh();
- self.trigger('change');
- }
- });
-
- //
- // datasets
- //
- var datasets = app.datasets.filterType({
- content_type : 'dataset',
- data_types : options.extensions
- });
-
- // configure options fields
- var dataset_options = [];
- for (var i in datasets) {
- dataset_options.push({
- label: datasets[i].name,
- value: datasets[i].id
- });
- }
-
- // select field
- this.select_datasets = new Ui.Select.View({
- multiple : true,
- data : dataset_options,
- value : dataset_options[0] && dataset_options[0].value,
- onchange : function() {
- self.trigger('change');
- }
- });
-
- //
- // collections
- //
- var collections = app.datasets.filterType({
- content_type : 'collection',
- data_types : options.extensions
- });
-
- // configure options fields
- var collection_options = [];
- for (var i in collections) {
- collection_options.push({
- label: collections[i].name,
- value: collections[i].id
- });
- }
-
- // create select field for collections
- this.select_collection = new Ui.Select.View({
- data : collection_options,
- value : collection_options[0] && collection_options[0].value,
- onchange : function() {
- self.trigger('change');
- }
- });
-
- // add elements to dom
- this.$el.append(Utils.wrap(this.button_new.$el));
- this.$el.append(this.select_datasets.$el);
- this.$el.append(this.select_collection.$el);
-
- // check for batch mode
- if (!this.options.multiple) {
- this.$el.append(ToolTemplate.batchMode());
- }
-
- // refresh view
- this.refresh();
-
- // add change event. fires on trigger
- this.on('change', function() {
- if (options.onchange) {
- options.onchange(self.value());
- }
- });
- },
-
- /** Return the currently selected dataset values */
- value : function () {
- // identify select element
- var select = null;
- switch(this.current) {
- case 'hda':
- select = this.select_datasets;
- break;
- case 'hdca':
- select = this.select_collection;
- break;
- }
-
- // transform into an array
- var id_list = select.value();
- if (!(id_list instanceof Array)) {
- id_list = [id_list];
- }
-
- // prepare result dict
- var result = {
- batch : !this.options.multiple,
- values : []
- }
-
- // append to dataset ids
- for (var i in id_list) {
- result.values.push({
- id : id_list[i],
- src : this.current
- });
- }
-
- // return
- return result;
- },
-
- /** Validate current selection
- */
- validate: function() {
- switch(this.current) {
- case 'hda':
- return this.select_datasets.validate();
- case 'hdca':
- return this.select_collection.validate();
- }
- },
-
- /** Refreshes data selection view */
- refresh: function() {
- switch (this.current) {
- case 'hda':
- this.select_datasets.$el.fadeIn();
- this.select_collection.$el.hide();
- break;
- case 'hdca':
- this.select_datasets.$el.hide();
- this.select_collection.$el.fadeIn();
- break;
- }
- }
-});
-
-return {
- View: View
-}
-
-});
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/packed/mvc/tools/tools-content.js
--- /dev/null
+++ b/static/scripts/packed/mvc/tools/tools-content.js
@@ -0,0 +1,1 @@
+define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(c){this.base_url=galaxy_config.root+"api/histories/"+c.history_id+"/contents";this.datatypes={};this.summary={};var b=this;a.get({url:galaxy_config.root+"api/datatypes/mapping",cache:true,success:function(d){b.datatypes=d;a.get({url:b.base_url+"?deleted=false",success:function(e){b.summary=e;console.debug("tools-content::initialize() - Completed.");c.success&&c.success()},error:function(e){console.debug("tools-content::initialize() - Ajax request for summary failed.");console.debug(e)}})},error:function(d){console.debug("tools-content::initialize() - Ajax request for datatypes failed.");console.debug(d)}})},filterType:function(c){c=c||{};var b=[];var g="dataset";if(c.src=="hdca"){g="dataset_collection"}for(var d in this.summary){var e=this.summary[d];var f=false;for(var d in c.extensions){if(this._matchType(c.extensions[d],e.extension)){f=true;break}}if((e.history_content_type===g)&&(f||!c.extensions)){b.push(e)}}return b},getDetails:function(b){var c=this.base_url+"/datasets/"+b.id;if(b.src=="hdca"){c=this.base_url+"/dataset_collections/"+b.id}a.get({url:c,success:function(d){b.success&&b.success(d)},error:function(d){console.debug("tools-content::getDetails() - Ajax request for content failed.");console.debug(d)}})},_matchType:function(f,b){var c=this.datatypes.ext_to_class_name[f];if(!c){console.debug("tools-content::_matchType() - Specific target class unavailable. Accepting all formats.");return true}var d=this.datatypes.ext_to_class_name[b];if(!d){console.debug("tools-content::_matchType() - Specific reference class unavailable. Accepting all formats.");return true}var e=this.datatypes.class_to_classes[d];if(e[c]){return true}return false}})});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/packed/mvc/tools/tools-datasets.js
--- a/static/scripts/packed/mvc/tools/tools-datasets.js
+++ /dev/null
@@ -1,1 +0,0 @@
-define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(c){this.datatypes={};this.summary={};var b=this;a.get({url:galaxy_config.root+"api/datatypes/mapping",cache:true,success:function(d){b.datatypes=d;a.get({url:galaxy_config.root+"api/histories/"+c.history_id+"/contents?deleted=false",success:function(e){b.summary=e;console.debug("tools-datasets::initialize() - Completed.");c.success&&c.success()},error:function(e){console.debug("tools-datasets::initialize() - Ajax request for summary failed.");console.debug(e)}})},error:function(d){console.debug("tools-datasets::initialize() - Ajax request for datatypes failed.");console.debug(d)}})},filterType:function(c){c=c||{};var b=[];for(var d in this.summary){var f=this.summary[d];var e=false;for(var d in c.data_types){if(this._matchType(c.data_types[d],f.extension)){e=true;break}}if((f.history_content_type===c.content_type||!c.content_type)&&(e||!c.data_types)){b.push(f)}}return b},getDetails:function(b,c){a.get({url:galaxy_config.root+"api/datasets/"+b,success:function(d){c&&c(d)},error:function(d){console.debug("tools-datasets::getDetails() - Ajax request for dataset failed.");console.debug(d)}})},_matchType:function(f,b){var c=this.datatypes.ext_to_class_name[f];if(!c){console.debug("tools-datasets::_matchType() - Specific target class unavailable. Accepting all formats.");return true}var d=this.datatypes.ext_to_class_name[b];if(!d){console.debug("tools-datasets::_matchType() - Specific reference class unavailable. Accepting all formats.");return true}var e=this.datatypes.class_to_classes[d];if(e[c]){return true}return false}})});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/packed/mvc/tools/tools-form.js
--- a/static/scripts/packed/mvc/tools/tools-form.js
+++ b/static/scripts/packed/mvc/tools/tools-form.js
@@ -1,1 +1,1 @@
-define(["mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-datasets","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(h,l,j,a,f,d,i,k,c,g){var e=Backbone.Model.extend({initialize:function(m){this.url=galaxy_config.root+"api/tools/"+m.id+"?io_details=true"}});var b=Backbone.View.extend({container:"body",initialize:function(n){var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.setElement("<div/>");$(this.container).append(this.$el);this.model=new e({id:n.id,job_id:n.job_id});this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.datasets=new i({history_id:this.options.history_id,success:function(){m._initializeToolForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_initializeToolForm:function(){var n=this;var p=new l.ButtonIcon({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});var q=new l.ButtonIcon({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}});var m=new l.ButtonIcon({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",galaxy_config.root+"root?tool_id="+n.options.id)}});var o={button_question:p,button_search:q,button_share:m};if(Galaxy.currUser.get("is_admin")){o.button_download=new l.ButtonIcon({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.model.fetch({error:function(r){console.debug("tools-form::_initializeToolForm() : Attempt to fetch tool model failed.")},success:function(){n.section=new k.View(n,{inputs:n.model.get("inputs"),cls:"ui-table-plain"});if(n.incompatible){n.$el.hide();$("#tool-form-classic").show();return}n.portlet=new h.View({icon:"fa-wrench",title:"<b>"+n.model.get("name")+"</b> "+n.model.get("description"),operations:o,buttons:{execute:new l.ButtonIcon({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",floating:"clear",onclick:function(){n.job_handler.submit()}})}});if(!n.options.biostar_url){p.$el.hide();q.$el.hide()}n.$el.append(n.portlet.$el);if(n.options.help!=""){n.$el.append(d.help(n.options.help))}if(n.options.citations){n.$el.append(d.citations());var r=new j.ToolCitationCollection();r.tool_id=n.options.id;var s=new a.CitationListView({collection:r});s.render();r.fetch()}n.portlet.append(n.section.$el);n.refresh()}})}});return{View:b}});
\ No newline at end of file
+define(["mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(i,l,j,a,f,d,g,k,c,h){var e=Backbone.Model.extend({initialize:function(m){this.url=galaxy_config.root+"api/tools/"+m.id+"?io_details=true"}});var b=Backbone.View.extend({container:"body",initialize:function(n){var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.setElement("<div/>");$(this.container).append(this.$el);this.model=new e({id:n.id,job_id:n.job_id});this.tree=new c(this);this.job_handler=new h(this);this.field_list={};this.input_list={};this.element_list={};this.content=new g({history_id:this.options.history_id,success:function(){m._initializeToolForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_initializeToolForm:function(){var n=this;var p=new l.ButtonIcon({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});var q=new l.ButtonIcon({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}});var m=new l.ButtonIcon({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",galaxy_config.root+"root?tool_id="+n.options.id)}});var o={button_question:p,button_search:q,button_share:m};if(Galaxy.currUser.get("is_admin")){o.button_download=new l.ButtonIcon({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.model.fetch({error:function(r){console.debug("tools-form::_initializeToolForm() : Attempt to fetch tool model failed.")},success:function(){n.section=new k.View(n,{inputs:n.model.get("inputs"),cls:"ui-table-plain"});if(n.incompatible){n.$el.hide();$("#tool-form-classic").show();return}n.portlet=new i.View({icon:"fa-wrench",title:"<b>"+n.model.get("name")+"</b> "+n.model.get("description"),operations:o,buttons:{execute:new l.ButtonIcon({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",floating:"clear",onclick:function(){n.job_handler.submit()}})}});if(!n.options.biostar_url){p.$el.hide();q.$el.hide()}n.$el.append(n.portlet.$el);if(n.options.help!=""){n.$el.append(d.help(n.options.help))}if(n.options.citations){n.$el.append(d.citations());var r=new j.ToolCitationCollection();r.tool_id=n.options.id;var s=new a.CitationListView({collection:r});s.render();r.fetch()}n.portlet.append(n.section.$el);n.refresh()}})}});return{View:b}});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/packed/mvc/tools/tools-section.js
--- a/static/scripts/packed/mvc/tools/tools-section.js
+++ b/static/scripts/packed/mvc/tools/tools-section.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/ui/ui-table","mvc/ui/ui-misc","mvc/tools/tools-repeat","mvc/tools/tools-select-dataset"],function(d,a,g,c,b){var e=Backbone.View.extend({initialize:function(h){this.setElement(this._template(h))},error:function(h){this.$el.find(".ui-table-form-error-text").html(h);this.$el.find(".ui-table-form-error").fadeIn();this.$el.addClass("ui-error")},reset:function(){this.$el.find(".ui-table-form-error").hide();this.$el.removeClass("ui-error")},_template:function(h){var i=$('<div class="ui-table-element"/>');i.append('<div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"></div>');if(h.label){i.append('<div class="ui-table-form-title-strong">'+h.label+"</div>")}i.append(h.$el);if(h.help){i.append('<div class="ui-table-form-info">'+h.help+"</div>")}return i}});var f=Backbone.View.extend({initialize:function(i,h){this.app=i;this.inputs=h.inputs;h.cls_tr="section-row";this.table=new a.View(h);this.setElement(this.table.$el);this.render()},render:function(){this.table.delAll();for(var h in this.inputs){this._add(this.inputs[h])}},_add:function(j){var i=this;var h=jQuery.extend(true,{},j);h.id=d.uuid();this.app.input_list[h.id]=h;var k=h.type;switch(k){case"conditional":this._addConditional(h);break;case"repeat":this._addRepeat(h);break;default:this._addRow(k,h)}},_addConditional:function(h){h.label=h.test_param.label;h.value=h.test_param.value;var j=this._addRow("conditional",h);for(var l in h.cases){var k=h.id+"-section-"+l;var m=new f(this.app,{inputs:h.cases[l].inputs,cls:"ui-table-plain"});m.$el.addClass("ui-table-form-section");this.table.add(m.$el);this.table.append(k)}},_addRepeat:function(h){var j=this;var n=0;var m=new c.View({title_new:h.title,max:h.max,onnew:function(){var i=h.id+"-section-"+(n++);var q=new f(j.app,{inputs:h.inputs,cls:"ui-table-plain"});m.add({id:i,title:h.title,$el:q.$el,ondel:function(){m.del(i);m.retitle(h.title);j.app.refresh()}});m.retitle(h.title);j.app.refresh()}});for(var l=0;l<h.min;l++){var k=h.id+"-section-"+(n++);var p=new f(j.app,{inputs:h.inputs,cls:"ui-table-plain"});m.add({id:k,title:h.title,$el:p.$el})}m.retitle(h.title);var o=new e({label:h.title,help:h.help,$el:m.$el});o.$el.addClass("ui-table-form-section");this.table.add(o.$el);this.table.append(h.id)},_addRow:function(j,h){var l=h.id;var i=null;switch(j){case"text":i=this._fieldText(h);break;case"select":i=this._fieldSelect(h);break;case"data":i=this._fieldData(h);break;case"data_column":i=this._fieldSelect(h);break;case"conditional":i=this._fieldConditional(h);break;case"hidden":i=this._fieldHidden(h);break;case"integer":i=this._fieldSlider(h);break;case"float":i=this._fieldSlider(h);break;case"boolean":i=this._fieldBoolean(h);break;case"genomebuild":i=this._fieldSelect(h);break;default:this.app.incompatible=true;if(h.options){i=this._fieldSelect(h)}else{i=this._fieldText(h)}console.debug("tools-form::_addRow() : Auto matched field type ("+j+").")}if(h.value!==undefined){i.value(h.value)}this.app.field_list[l]=i;var k=new e({label:h.label,help:h.help,$el:i.$el});this.app.element_list[l]=k;this.table.add(k.$el);this.table.append(l);return this.table.get(l)},_fieldConditional:function(h){var j=this;var k=[];for(var l in h.test_param.options){var m=h.test_param.options[l];k.push({label:m[0],value:m[1]})}return new g.Select.View({id:"field-"+h.id,data:k,onchange:function(u){for(var s in h.cases){var o=h.cases[s];var r=h.id+"-section-"+s;var n=j.table.get(r);var q=false;for(var p in o.inputs){var t=o.inputs[p].type;if(t&&t!=="hidden"){q=true;break}}if(o.value==u&&q){n.fadeIn("fast")}else{n.hide()}}}})},_fieldData:function(h){var i=this;var j=h.id;return new b.View(this.app,{id:"field-"+j,extensions:h.extensions,multiple:h.multiple,onchange:function(o){var n=o.values[0].id;var l=i.app.tree.references(j,"data_column");if(l.length<=0){console.debug("tool-form::field_data() - Data column parameters unavailable.");return}for(var m in l){var k=i.app.field_list[l[m]];k.wait&&k.wait()}i.app.datasets.getDetails(n,function(r){var z=null;if(r){console.debug("tool-form::field_data() - Selected dataset "+n+".");z=r.metadata_column_types;if(!z){console.debug("tool-form::field_data() - FAILED: Could not find metadata for dataset "+n+".")}}else{console.debug("tool-form::field_data() - FAILED: Could not find dataset "+n+".")}for(var t in l){var v=i.app.input_list[l[t]];var w=i.app.field_list[l[t]];if(!v||!w){console.debug("tool-form::field_data() - FAILED: Column not found.")}var s=v.numerical;var q=[];for(var y in z){var x=z[y];var p=(parseInt(y)+1);var u="Text";if(x=="int"||x=="float"){u="Number"}if(x=="int"||x=="float"||!s){q.push({label:"Column: "+p+" ["+u+"]",value:p})}}if(w){w.update(q);if(!w.exists(w.value())){w.value(w.first())}w.show()}}})}})},_fieldSelect:function(h){var j=[];for(var k in h.options){var l=h.options[k];j.push({label:l[0],value:l[1]})}var m=g.Select;switch(h.display){case"checkboxes":m=g.Checkbox;break;case"radio":m=g.Radio;break}return new m.View({id:"field-"+h.id,data:j,multiple:h.multiple})},_fieldText:function(h){return new g.Input({id:"field-"+h.id,area:h.area})},_fieldSlider:function(h){h.min=h.min||0;h.max=h.max||100000;var i=1;if(h.type=="float"){i=(h.max-h.min)/10000}return new g.Slider.View({id:"field-"+h.id,min:h.min,max:h.max,step:i})},_fieldHidden:function(h){return new g.Hidden({id:"field-"+h.id})},_fieldBoolean:function(h){return new g.RadioButton.View({id:"field-"+h.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]})}});return{View:f}});
\ No newline at end of file
+define(["utils/utils","mvc/ui/ui-table","mvc/ui/ui-misc","mvc/tools/tools-repeat","mvc/tools/tools-select-content"],function(d,b,g,c,a){var e=Backbone.View.extend({initialize:function(h){this.setElement(this._template(h))},error:function(h){this.$el.find(".ui-table-form-error-text").html(h);this.$el.find(".ui-table-form-error").fadeIn();this.$el.addClass("ui-error")},reset:function(){this.$el.find(".ui-table-form-error").hide();this.$el.removeClass("ui-error")},_template:function(h){var i=$('<div class="ui-table-element"/>');i.append('<div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"></div>');if(h.label){i.append('<div class="ui-table-form-title-strong">'+h.label+"</div>")}i.append(h.$el);if(h.help){i.append('<div class="ui-table-form-info">'+h.help+"</div>")}return i}});var f=Backbone.View.extend({initialize:function(i,h){this.app=i;this.inputs=h.inputs;h.cls_tr="section-row";this.table=new b.View(h);this.setElement(this.table.$el);this.render()},render:function(){this.table.delAll();for(var h in this.inputs){this._add(this.inputs[h])}},_add:function(j){var i=this;var h=jQuery.extend(true,{},j);h.id=d.uuid();this.app.input_list[h.id]=h;var k=h.type;switch(k){case"conditional":this._addConditional(h);break;case"repeat":this._addRepeat(h);break;default:this._addRow(k,h)}},_addConditional:function(h){h.label=h.test_param.label;h.value=h.test_param.value;var j=this._addRow("conditional",h);for(var l in h.cases){var k=h.id+"-section-"+l;var m=new f(this.app,{inputs:h.cases[l].inputs,cls:"ui-table-plain"});m.$el.addClass("ui-table-form-section");this.table.add(m.$el);this.table.append(k)}},_addRepeat:function(h){var j=this;var n=0;var m=new c.View({title_new:h.title,max:h.max,onnew:function(){var i=h.id+"-section-"+(n++);var q=new f(j.app,{inputs:h.inputs,cls:"ui-table-plain"});m.add({id:i,title:h.title,$el:q.$el,ondel:function(){m.del(i);m.retitle(h.title);j.app.refresh()}});m.retitle(h.title);j.app.refresh()}});for(var l=0;l<h.min;l++){var k=h.id+"-section-"+(n++);var p=new f(j.app,{inputs:h.inputs,cls:"ui-table-plain"});m.add({id:k,title:h.title,$el:p.$el})}m.retitle(h.title);var o=new e({label:h.title,help:h.help,$el:m.$el});o.$el.addClass("ui-table-form-section");this.table.add(o.$el);this.table.append(h.id)},_addRow:function(j,h){var l=h.id;var i=null;switch(j){case"text":i=this._fieldText(h);break;case"select":i=this._fieldSelect(h);break;case"data":i=this._fieldData(h);break;case"data_column":i=this._fieldSelect(h);break;case"conditional":i=this._fieldConditional(h);break;case"hidden":i=this._fieldHidden(h);break;case"integer":i=this._fieldSlider(h);break;case"float":i=this._fieldSlider(h);break;case"boolean":i=this._fieldBoolean(h);break;case"genomebuild":i=this._fieldSelect(h);break;default:this.app.incompatible=true;if(h.options){i=this._fieldSelect(h)}else{i=this._fieldText(h)}console.debug("tools-form::_addRow() : Auto matched field type ("+j+").")}if(h.value!==undefined){i.value(h.value)}this.app.field_list[l]=i;var k=new e({label:h.label,help:h.help,$el:i.$el});this.app.element_list[l]=k;this.table.add(k.$el);this.table.append(l);return this.table.get(l)},_fieldConditional:function(h){var j=this;var k=[];for(var l in h.test_param.options){var m=h.test_param.options[l];k.push({label:m[0],value:m[1]})}return new g.Select.View({id:"field-"+h.id,data:k,onchange:function(u){for(var s in h.cases){var o=h.cases[s];var r=h.id+"-section-"+s;var n=j.table.get(r);var q=false;for(var p in o.inputs){var t=o.inputs[p].type;if(t&&t!=="hidden"){q=true;break}}if(o.value==u&&q){n.fadeIn("fast")}else{n.hide()}}}})},_fieldData:function(h){var i=this;var j=h.id;return new a.View(this.app,{id:"field-"+j,extensions:h.extensions,multiple:h.multiple,onchange:function(q){var o=q.values[0];var m=o.id;var p=o.src;var l=i.app.tree.references(j,"data_column");if(l.length<=0){console.debug("tool-form::field_data() - Data column parameters unavailable.");return}for(var n in l){var k=i.app.field_list[l[n]];k.wait&&k.wait()}i.app.content.getDetails({id:m,src:p,success:function(y){if(p=="hdca"&&y.elements&&y.elements.length>0){y=y.elements[0].object}var B=null;if(y){console.debug("tool-form::field_data() - Selected content "+m+".");B=y.metadata_column_types;if(!B){console.debug("tool-form::field_data() - FAILED: Could not find metadata for content "+m+".")}}else{console.debug("tool-form::field_data() - FAILED: Could not find content "+m+".")}for(var u in l){var w=i.app.input_list[l[u]];var x=i.app.field_list[l[u]];if(!w||!x){console.debug("tool-form::field_data() - FAILED: Column not found.")}var t=w.numerical;var s=[];for(var A in B){var z=B[A];var r=(parseInt(A)+1);var v="Text";if(z=="int"||z=="float"){v="Number"}if(z=="int"||z=="float"||!t){s.push({label:"Column: "+r+" ["+v+"]",value:r})}}if(x){x.update(s);if(!x.exists(x.value())){x.value(x.first())}x.show()}}}})}})},_fieldSelect:function(h){var j=[];for(var k in h.options){var l=h.options[k];j.push({label:l[0],value:l[1]})}var m=g.Select;switch(h.display){case"checkboxes":m=g.Checkbox;break;case"radio":m=g.Radio;break}return new m.View({id:"field-"+h.id,data:j,multiple:h.multiple})},_fieldText:function(h){return new g.Input({id:"field-"+h.id,area:h.area})},_fieldSlider:function(h){h.min=h.min||0;h.max=h.max||100000;var i=1;if(h.type=="float"){i=(h.max-h.min)/10000}return new g.Slider.View({id:"field-"+h.id,min:h.min,max:h.max,step:i})},_fieldHidden:function(h){return new g.Hidden({id:"field-"+h.id})},_fieldBoolean:function(h){return new g.RadioButton.View({id:"field-"+h.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]})}});return{View:f}});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/packed/mvc/tools/tools-select-content.js
--- /dev/null
+++ b/static/scripts/packed/mvc/tools/tools-select-content.js
@@ -0,0 +1,1 @@
+define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-tabs","mvc/tools/tools-template"],function(c,e,b,a){var d=Backbone.View.extend({initialize:function(n,h){this.options=h;var g=this;this.setElement("<div/>");this.current="hda";this.button_new=new e.RadioButton.View({value:this.current,data:[{icon:"fa-file-o",label:"Select datasets",value:"hda"},{icon:"fa-files-o",label:"Select a collection",value:"hdca"}],onchange:function(i){g.current=i;g.refresh();g.trigger("change")}});var l=n.content.filterType({src:"hda",extensions:h.extensions});var k=[];for(var j in l){k.push({label:l[j].name,value:l[j].id})}this.select_datasets=new e.Select.View({multiple:true,data:k,value:k[0]&&k[0].value,onchange:function(){g.trigger("change")}});var m=n.content.filterType({src:"hdca",extensions:h.extensions});var f=[];for(var j in m){f.push({label:m[j].name,value:m[j].id})}this.select_collection=new e.Select.View({data:f,value:f[0]&&f[0].value,onchange:function(){g.trigger("change")}});this.$el.append(c.wrap(this.button_new.$el));this.$el.append(this.select_datasets.$el);this.$el.append(this.select_collection.$el);if(!this.options.multiple){this.$el.append(a.batchMode())}this.refresh();this.on("change",function(){if(h.onchange){h.onchange(g.value())}})},value:function(){var g=null;switch(this.current){case"hda":g=this.select_datasets;break;case"hdca":g=this.select_collection;break}var j=g.value();if(!(j instanceof Array)){j=[j]}var f={batch:!this.options.multiple,values:[]};for(var h in j){f.values.push({id:j[h],src:this.current})}return f},validate:function(){switch(this.current){case"hda":return this.select_datasets.validate();case"hdca":return this.select_collection.validate()}},refresh:function(){switch(this.current){case"hda":this.select_datasets.$el.fadeIn();this.select_collection.$el.hide();break;case"hdca":this.select_datasets.$el.hide();this.select_collection.$el.fadeIn();break}}});return{View:d}});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/packed/mvc/tools/tools-select-dataset.js
--- a/static/scripts/packed/mvc/tools/tools-select-dataset.js
+++ /dev/null
@@ -1,1 +0,0 @@
-define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-tabs","mvc/tools/tools-template"],function(c,e,b,a){var d=Backbone.View.extend({initialize:function(n,h){this.options=h;var g=this;this.setElement("<div/>");this.current="hda";this.button_new=new e.RadioButton.View({value:this.current,data:[{icon:"fa-file-o",label:"Select datasets",value:"hda"},{icon:"fa-files-o",label:"Select a collection",value:"hdca"}],onchange:function(i){g.current=i;g.refresh();g.trigger("change")}});var l=n.datasets.filterType({content_type:"dataset",data_types:h.extensions});var k=[];for(var j in l){k.push({label:l[j].name,value:l[j].id})}this.select_datasets=new e.Select.View({multiple:true,data:k,value:k[0]&&k[0].value,onchange:function(){g.trigger("change")}});var m=n.datasets.filterType({content_type:"collection",data_types:h.extensions});var f=[];for(var j in m){f.push({label:m[j].name,value:m[j].id})}this.select_collection=new e.Select.View({data:f,value:f[0]&&f[0].value,onchange:function(){g.trigger("change")}});this.$el.append(c.wrap(this.button_new.$el));this.$el.append(this.select_datasets.$el);this.$el.append(this.select_collection.$el);if(!this.options.multiple){this.$el.append(a.batchMode())}this.refresh();this.on("change",function(){if(h.onchange){h.onchange(g.value())}})},value:function(){var g=null;switch(this.current){case"hda":g=this.select_datasets;break;case"hdca":g=this.select_collection;break}var j=g.value();if(!(j instanceof Array)){j=[j]}var f={batch:!this.options.multiple,values:[]};for(var h in j){f.values.push({id:j[h],src:this.current})}return f},validate:function(){switch(this.current){case"hda":return this.select_datasets.validate();case"hdca":return this.select_collection.validate()}},refresh:function(){switch(this.current){case"hda":this.select_datasets.$el.fadeIn();this.select_collection.$el.hide();break;case"hdca":this.select_datasets.$el.hide();this.select_collection.$el.fadeIn();break}}});return{View:d}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: ToolForm: Fix automated form switching
by commits-noreply@bitbucket.org 07 Oct '14
by commits-noreply@bitbucket.org 07 Oct '14
07 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0e99c30878af/
Changeset: 0e99c30878af
User: guerler
Date: 2014-10-07 18:39:33+00:00
Summary: ToolForm: Fix automated form switching
Affected #: 3 files
diff -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 -r 0e99c30878af56e23f447854a7ae70b412a9d627 client/galaxy/scripts/mvc/tools/tools-form.js
--- a/client/galaxy/scripts/mvc/tools/tools-form.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form.js
@@ -217,9 +217,6 @@
citations.fetch();
}
- // configure portlet and form table
- self.setElement(self.portlet.content());
-
// append tool section
self.portlet.append(self.section.$el);
diff -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 -r 0e99c30878af56e23f447854a7ae70b412a9d627 static/scripts/mvc/tools/tools-form.js
--- a/static/scripts/mvc/tools/tools-form.js
+++ b/static/scripts/mvc/tools/tools-form.js
@@ -217,9 +217,6 @@
citations.fetch();
}
- // configure portlet and form table
- self.setElement(self.portlet.content());
-
// append tool section
self.portlet.append(self.section.$el);
diff -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 -r 0e99c30878af56e23f447854a7ae70b412a9d627 static/scripts/packed/mvc/tools/tools-form.js
--- a/static/scripts/packed/mvc/tools/tools-form.js
+++ b/static/scripts/packed/mvc/tools/tools-form.js
@@ -1,1 +1,1 @@
-define(["mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-datasets","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(h,l,j,a,f,d,i,k,c,g){var e=Backbone.Model.extend({initialize:function(m){this.url=galaxy_config.root+"api/tools/"+m.id+"?io_details=true"}});var b=Backbone.View.extend({container:"body",initialize:function(n){var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.setElement("<div/>");$(this.container).append(this.$el);this.model=new e({id:n.id,job_id:n.job_id});this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.datasets=new i({history_id:this.options.history_id,success:function(){m._initializeToolForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_initializeToolForm:function(){var n=this;var p=new l.ButtonIcon({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});var q=new l.ButtonIcon({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}});var m=new l.ButtonIcon({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",galaxy_config.root+"root?tool_id="+n.options.id)}});var o={button_question:p,button_search:q,button_share:m};if(Galaxy.currUser.get("is_admin")){o.button_download=new l.ButtonIcon({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.model.fetch({error:function(r){console.debug("tools-form::_initializeToolForm() : Attempt to fetch tool model failed.")},success:function(){n.section=new k.View(n,{inputs:n.model.get("inputs"),cls:"ui-table-plain"});if(n.incompatible){n.$el.hide();$("#tool-form-classic").show();return}n.portlet=new h.View({icon:"fa-wrench",title:"<b>"+n.model.get("name")+"</b> "+n.model.get("description"),operations:o,buttons:{execute:new l.ButtonIcon({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",floating:"clear",onclick:function(){n.job_handler.submit()}})}});if(!n.options.biostar_url){p.$el.hide();q.$el.hide()}n.$el.append(n.portlet.$el);if(n.options.help!=""){n.$el.append(d.help(n.options.help))}if(n.options.citations){n.$el.append(d.citations());var r=new j.ToolCitationCollection();r.tool_id=n.options.id;var s=new a.CitationListView({collection:r});s.render();r.fetch()}n.setElement(n.portlet.content());n.portlet.append(n.section.$el);n.refresh()}})}});return{View:b}});
\ No newline at end of file
+define(["mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-datasets","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(h,l,j,a,f,d,i,k,c,g){var e=Backbone.Model.extend({initialize:function(m){this.url=galaxy_config.root+"api/tools/"+m.id+"?io_details=true"}});var b=Backbone.View.extend({container:"body",initialize:function(n){var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.setElement("<div/>");$(this.container).append(this.$el);this.model=new e({id:n.id,job_id:n.job_id});this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.datasets=new i({history_id:this.options.history_id,success:function(){m._initializeToolForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_initializeToolForm:function(){var n=this;var p=new l.ButtonIcon({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});var q=new l.ButtonIcon({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}});var m=new l.ButtonIcon({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",galaxy_config.root+"root?tool_id="+n.options.id)}});var o={button_question:p,button_search:q,button_share:m};if(Galaxy.currUser.get("is_admin")){o.button_download=new l.ButtonIcon({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.model.fetch({error:function(r){console.debug("tools-form::_initializeToolForm() : Attempt to fetch tool model failed.")},success:function(){n.section=new k.View(n,{inputs:n.model.get("inputs"),cls:"ui-table-plain"});if(n.incompatible){n.$el.hide();$("#tool-form-classic").show();return}n.portlet=new h.View({icon:"fa-wrench",title:"<b>"+n.model.get("name")+"</b> "+n.model.get("description"),operations:o,buttons:{execute:new l.ButtonIcon({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",floating:"clear",onclick:function(){n.job_handler.submit()}})}});if(!n.options.biostar_url){p.$el.hide();q.$el.hide()}n.$el.append(n.portlet.$el);if(n.options.help!=""){n.$el.append(d.help(n.options.help))}if(n.options.citations){n.$el.append(d.citations());var r=new j.ToolCitationCollection();r.tool_id=n.options.id;var s=new a.CitationListView({collection:r});s.render();r.fetch()}n.portlet.append(n.section.$el);n.refresh()}})}});return{View:b}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: ToolForm: Add download button, prepare for activation
by commits-noreply@bitbucket.org 07 Oct '14
by commits-noreply@bitbucket.org 07 Oct '14
07 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f94fbe948b7a/
Changeset: f94fbe948b7a
User: guerler
Date: 2014-10-07 17:52:53+00:00
Summary: ToolForm: Add download button, prepare for activation
Affected #: 5 files
diff -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 client/galaxy/scripts/mvc/tools/tools-form.js
--- a/client/galaxy/scripts/mvc/tools/tools-form.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form.js
@@ -42,7 +42,8 @@
// load tool model
this.model = new Model({
- id : options.id
+ id : options.id,
+ job_id : options.job_id
});
// creates a tree/json structure from the input form
@@ -93,7 +94,7 @@
}
// log
- console.debug('tools-form::refresh() - Recreated tree structure. Refresh.');
+ console.debug('tools-form::refresh() - Recreated data structure. Refresh.');
},
// initialize tool form
@@ -131,6 +132,26 @@
}
});
+ // default operations
+ var operations = {
+ button_question: button_question,
+ button_search: button_search,
+ button_share: button_share
+ }
+
+ // add admin operations
+ if (Galaxy.currUser.get('is_admin')) {
+ // create download button
+ operations['button_download'] = new Ui.ButtonIcon({
+ icon : 'fa-download',
+ title : 'Download',
+ tooltip : 'Download this tool',
+ onclick : function() {
+ window.location.href = galaxy_config.root + 'api/tools/' + self.options.id + '/download';
+ }
+ });
+ }
+
// fetch model and render form
this.model.fetch({
error: function(response) {
@@ -155,6 +176,7 @@
self.portlet = new Portlet.View({
icon : 'fa-wrench',
title: '<b>' + self.model.get('name') + '</b> ' + self.model.get('description'),
+ operations: operations,
buttons: {
execute: new Ui.ButtonIcon({
icon : 'fa-check',
@@ -165,11 +187,6 @@
self.job_handler.submit();
}
})
- },
- operations: {
- button_question: button_question,
- button_search: button_search,
- button_share: button_share
}
});
diff -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 lib/galaxy/webapps/galaxy/controllers/tool_runner.py
--- a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
+++ b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
@@ -264,6 +264,7 @@
toolbox=self.get_toolbox(),
tool_version_select_field=tool_version_select_field,
tool=tool,
+ job=job,
util=galaxy.util,
add_frame=add_frame,
tool_id_version_message=tool_id_version_message,
diff -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 static/scripts/mvc/tools/tools-form.js
--- a/static/scripts/mvc/tools/tools-form.js
+++ b/static/scripts/mvc/tools/tools-form.js
@@ -42,7 +42,8 @@
// load tool model
this.model = new Model({
- id : options.id
+ id : options.id,
+ job_id : options.job_id
});
// creates a tree/json structure from the input form
@@ -93,7 +94,7 @@
}
// log
- console.debug('tools-form::refresh() - Recreated tree structure. Refresh.');
+ console.debug('tools-form::refresh() - Recreated data structure. Refresh.');
},
// initialize tool form
@@ -131,6 +132,26 @@
}
});
+ // default operations
+ var operations = {
+ button_question: button_question,
+ button_search: button_search,
+ button_share: button_share
+ }
+
+ // add admin operations
+ if (Galaxy.currUser.get('is_admin')) {
+ // create download button
+ operations['button_download'] = new Ui.ButtonIcon({
+ icon : 'fa-download',
+ title : 'Download',
+ tooltip : 'Download this tool',
+ onclick : function() {
+ window.location.href = galaxy_config.root + 'api/tools/' + self.options.id + '/download';
+ }
+ });
+ }
+
// fetch model and render form
this.model.fetch({
error: function(response) {
@@ -155,6 +176,7 @@
self.portlet = new Portlet.View({
icon : 'fa-wrench',
title: '<b>' + self.model.get('name') + '</b> ' + self.model.get('description'),
+ operations: operations,
buttons: {
execute: new Ui.ButtonIcon({
icon : 'fa-check',
@@ -165,11 +187,6 @@
self.job_handler.submit();
}
})
- },
- operations: {
- button_question: button_question,
- button_search: button_search,
- button_share: button_share
}
});
diff -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 static/scripts/packed/mvc/tools/tools-form.js
--- a/static/scripts/packed/mvc/tools/tools-form.js
+++ b/static/scripts/packed/mvc/tools/tools-form.js
@@ -1,1 +1,1 @@
-define(["mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-datasets","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(h,l,j,a,f,d,i,k,c,g){var e=Backbone.Model.extend({initialize:function(m){this.url=galaxy_config.root+"api/tools/"+m.id+"?io_details=true"}});var b=Backbone.View.extend({container:"body",initialize:function(n){var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.setElement("<div/>");$(this.container).append(this.$el);this.model=new e({id:n.id});this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.datasets=new i({history_id:this.options.history_id,success:function(){m._initializeToolForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated tree structure. Refresh.")},_initializeToolForm:function(){var n=this;var o=new l.ButtonIcon({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});var p=new l.ButtonIcon({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}});var m=new l.ButtonIcon({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",galaxy_config.root+"root?tool_id="+n.options.id)}});this.model.fetch({error:function(q){console.debug("tools-form::_initializeToolForm() : Attempt to fetch tool model failed.")},success:function(){n.section=new k.View(n,{inputs:n.model.get("inputs"),cls:"ui-table-plain"});if(n.incompatible){n.$el.hide();$("#tool-form-classic").show();return}n.portlet=new h.View({icon:"fa-wrench",title:"<b>"+n.model.get("name")+"</b> "+n.model.get("description"),buttons:{execute:new l.ButtonIcon({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",floating:"clear",onclick:function(){n.job_handler.submit()}})},operations:{button_question:o,button_search:p,button_share:m}});if(!n.options.biostar_url){o.$el.hide();p.$el.hide()}n.$el.append(n.portlet.$el);if(n.options.help!=""){n.$el.append(d.help(n.options.help))}if(n.options.citations){n.$el.append(d.citations());var q=new j.ToolCitationCollection();q.tool_id=n.options.id;var r=new a.CitationListView({collection:q});r.render();q.fetch()}n.setElement(n.portlet.content());n.portlet.append(n.section.$el);n.refresh()}})}});return{View:b}});
\ No newline at end of file
+define(["mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-datasets","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(h,l,j,a,f,d,i,k,c,g){var e=Backbone.Model.extend({initialize:function(m){this.url=galaxy_config.root+"api/tools/"+m.id+"?io_details=true"}});var b=Backbone.View.extend({container:"body",initialize:function(n){var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.setElement("<div/>");$(this.container).append(this.$el);this.model=new e({id:n.id,job_id:n.job_id});this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.datasets=new i({history_id:this.options.history_id,success:function(){m._initializeToolForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_initializeToolForm:function(){var n=this;var p=new l.ButtonIcon({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});var q=new l.ButtonIcon({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}});var m=new l.ButtonIcon({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",galaxy_config.root+"root?tool_id="+n.options.id)}});var o={button_question:p,button_search:q,button_share:m};if(Galaxy.currUser.get("is_admin")){o.button_download=new l.ButtonIcon({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.model.fetch({error:function(r){console.debug("tools-form::_initializeToolForm() : Attempt to fetch tool model failed.")},success:function(){n.section=new k.View(n,{inputs:n.model.get("inputs"),cls:"ui-table-plain"});if(n.incompatible){n.$el.hide();$("#tool-form-classic").show();return}n.portlet=new h.View({icon:"fa-wrench",title:"<b>"+n.model.get("name")+"</b> "+n.model.get("description"),operations:o,buttons:{execute:new l.ButtonIcon({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",floating:"clear",onclick:function(){n.job_handler.submit()}})}});if(!n.options.biostar_url){p.$el.hide();q.$el.hide()}n.$el.append(n.portlet.$el);if(n.options.help!=""){n.$el.append(d.help(n.options.help))}if(n.options.citations){n.$el.append(d.citations());var r=new j.ToolCitationCollection();r.tool_id=n.options.id;var s=new a.CitationListView({collection:r});s.render();r.fetch()}n.setElement(n.portlet.content());n.portlet.append(n.section.$el);n.refresh()}})}});return{View:b}});
\ No newline at end of file
diff -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 templates/webapps/galaxy/tool_form.api.mako
--- a/templates/webapps/galaxy/tool_form.api.mako
+++ b/templates/webapps/galaxy/tool_form.api.mako
@@ -27,7 +27,8 @@
'help' : tool_help,
'citations' : tool_citations,
'biostar_url' : trans.app.config.biostar_url,
- 'history_id' : trans.security.encode_id( trans.history.id )
+ 'history_id' : trans.security.encode_id( trans.history.id ),
+ 'job_id' : trans.security.encode_id( job.id ) if job else None
}
%>
${h.js("libs/bibtex", "libs/jquery/jquery-ui")}
@@ -40,14 +41,6 @@
});
</script>
-##%if tool.tool_shed_repository:
-## <% tool_url = tool.tool_shed_repository.get_sharable_url( tool.app ) %>
-## %if tool_url:
-## <br/>
-## ${ render_msg( 'This tool was installed from a ToolShed, you may be able to find additional information by following this link: <a href="%s" target="_blank">%s</a>' % ( tool_url, tool_url ), 'info' ) }
-## %endif
-##%endif
-
## classic tool form
<div id="tool-form-classic" style="display: none;"><%include file="tool_form.mako"/>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jmchilton: Method for using local network (e.g. NFS) to distribute cached docker images across clusters.
by commits-noreply@bitbucket.org 07 Oct '14
by commits-noreply@bitbucket.org 07 Oct '14
07 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a3cff55b129f/
Changeset: a3cff55b129f
User: jmchilton
Date: 2014-10-07 17:28:43+00:00
Summary: Method for using local network (e.g. NFS) to distribute cached docker images across clusters.
General idea and outline for short caching script embedded in containers.py from Kyle Ellrott.
Affected #: 4 files
diff -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -143,6 +143,7 @@
self.cluster_files_directory = os.path.abspath( kwargs.get( "cluster_files_directory", "database/pbs" ) )
self.job_working_directory = resolve_path( kwargs.get( "job_working_directory", "database/job_working_directory" ), self.root )
self.cleanup_job = kwargs.get( "cleanup_job", "always" )
+ self.container_image_cache_path = self.resolve_path( kwargs.get( "container_image_cache_path", "database/container_images" ) )
self.outputs_to_working_directory = string_as_bool( kwargs.get( 'outputs_to_working_directory', False ) )
self.output_size_limit = int( kwargs.get( 'output_size_limit', 0 ) )
self.retry_job_output_collection = int( kwargs.get( 'retry_job_output_collection', 0 ) )
@@ -640,7 +641,8 @@
app_info = containers.AppInfo(
galaxy_root_dir,
default_file_path=file_path,
- outputs_to_working_directory=self.config.outputs_to_working_directory
+ outputs_to_working_directory=self.config.outputs_to_working_directory,
+ container_image_cache_path=self.config.container_image_cache_path,
)
self.container_finder = galaxy.tools.deps.containers.ContainerFinder(app_info)
diff -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 lib/galaxy/tools/deps/containers.py
--- a/lib/galaxy/tools/deps/containers.py
+++ b/lib/galaxy/tools/deps/containers.py
@@ -13,6 +13,29 @@
DEFAULT_CONTAINER_TYPE = "docker"
+LOAD_CACHED_IMAGE_COMMAND_TEMPLATE = '''
+python << EOF
+import re, tarfile, json, subprocess
+t = tarfile.TarFile("${cached_image_file}")
+meta_str = t.extractfile('repositories').read()
+meta = json.loads(meta_str)
+tag, tag_value = meta.items()[0]
+rev, rev_value = tag_value.items()[0]
+cmd = "${images_cmd}"
+proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
+stdo, stde = proc.communicate()
+found = False
+for line in stdo.split("\\n"):
+ tmp = re.split(r'\s+', line)
+ if tmp[0] == tag and tmp[1] == rev and tmp[2] == rev_value:
+ found = True
+if not found:
+ print "Loading image"
+ cmd = "cat ${cached_image_file} | ${load_cmd}"
+ subprocess.check_call(cmd, shell=True)
+EOF
+'''
+
class ContainerFinder(object):
@@ -117,11 +140,18 @@
class AppInfo(object):
- def __init__(self, galaxy_root_dir=None, default_file_path=None, outputs_to_working_directory=False):
+ def __init__(
+ self,
+ galaxy_root_dir=None,
+ default_file_path=None,
+ outputs_to_working_directory=False,
+ container_image_cache_path=None,
+ ):
self.galaxy_root_dir = galaxy_root_dir
self.default_file_path = default_file_path
# TODO: Vary default value for docker_volumes based on this...
self.outputs_to_working_directory = outputs_to_working_directory
+ self.container_image_cache_path = container_image_cache_path
class ToolInfo(object):
@@ -199,7 +229,12 @@
host=prop("host", docker_util.DEFAULT_HOST),
)
- cache_command = docker_util.build_docker_cache_command(self.container_id, **docker_host_props)
+ cached_image_file = self.__get_cached_image_file()
+ if not cached_image_file:
+ # TODO: Add option to cache it once here and create cached_image_file.
+ cache_command = docker_util.build_docker_cache_command(self.container_id, **docker_host_props)
+ else:
+ cache_command = self.__cache_from_file_command(cached_image_file, docker_host_props)
run_command = docker_util.build_docker_run_command(
command,
self.container_id,
@@ -213,6 +248,29 @@
)
return "%s\n%s" % (cache_command, run_command)
+ def __cache_from_file_command(self, cached_image_file, docker_host_props):
+ images_cmd = docker_util.build_docker_images_command(truncate=False, **docker_host_props)
+ load_cmd = docker_util.build_docker_load_command(**docker_host_props)
+
+ return string.Template(LOAD_CACHED_IMAGE_COMMAND_TEMPLATE).safe_substitute(
+ cached_image_file=cached_image_file,
+ images_cmd=images_cmd,
+ load_cmd=load_cmd
+ )
+
+ def __get_cached_image_file(self):
+ container_id = self.container_id
+ cache_directory = os.path.abspath(self.__get_destination_overridable_property("container_image_cache_path"))
+ cache_path = docker_cache_path(cache_directory, container_id)
+ return cache_path if os.path.exists(cache_path) else None
+
+ def __get_destination_overridable_property(self, name):
+ prop_name = "docker_%s" % name
+ if prop_name in self.destination_info:
+ return self.destination_info[prop_name]
+ else:
+ return getattr(self.app_info, name)
+
def __expand_str(self, value):
if not value:
return value
@@ -248,6 +306,12 @@
return template.safe_substitute(variables)
+def docker_cache_path(cache_directory, container_id):
+ file_container_id = container_id.replace("/", "_slash_")
+ cache_file_name = "docker_%s.tar" % file_container_id
+ return os.path.join(cache_directory, cache_file_name)
+
+
CONTAINER_CLASSES = dict(
docker=DockerContainer,
)
diff -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 lib/galaxy/tools/deps/docker_util.py
--- a/lib/galaxy/tools/deps/docker_util.py
+++ b/lib/galaxy/tools/deps/docker_util.py
@@ -55,14 +55,11 @@
def build_command(
image,
docker_build_path,
- docker_cmd=DEFAULT_DOCKER_COMMAND,
- sudo=DEFAULT_SUDO,
- sudo_cmd=DEFAULT_SUDO_COMMAND,
- host=DEFAULT_HOST,
+ **kwds
):
if os.path.isfile(docker_build_path):
docker_build_path = os.path.dirname(os.path.abspath(docker_build_path))
- build_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
+ build_command_parts = __docker_prefix(**kwds)
build_command_parts.extend(["build", "-t", image, docker_build_path])
return build_command_parts
@@ -70,34 +67,42 @@
def build_save_image_command(
image,
destination,
- docker_cmd=DEFAULT_DOCKER_COMMAND,
- sudo=DEFAULT_SUDO,
- sudo_cmd=DEFAULT_SUDO_COMMAND,
- host=DEFAULT_HOST,
+ **kwds
):
- build_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
+ build_command_parts = __docker_prefix(**kwds)
build_command_parts.extend(["save", "-o", destination, image])
return build_command_parts
def build_docker_cache_command(
image,
- docker_cmd=DEFAULT_DOCKER_COMMAND,
- sudo=DEFAULT_SUDO,
- sudo_cmd=DEFAULT_SUDO_COMMAND,
- host=DEFAULT_HOST,
+ **kwds
):
- inspect_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
+ inspect_command_parts = __docker_prefix(**kwds)
inspect_command_parts.extend(["inspect", image])
inspect_image_command = " ".join(inspect_command_parts)
- pull_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
+ pull_command_parts = __docker_prefix(**kwds)
pull_command_parts.extend(["pull", image])
pull_image_command = " ".join(pull_command_parts)
cache_command = "%s > /dev/null 2>&1\n[ $? -ne 0 ] && %s > /dev/null 2>&1\n" % (inspect_image_command, pull_image_command)
return cache_command
+def build_docker_images_command(truncate=True, **kwds):
+ images_command_parts = __docker_prefix(**kwds)
+ images_command_parts.append("images")
+ if not truncate:
+ images_command_parts.append("--no-trunc")
+ return " ".join(images_command_parts)
+
+
+def build_docker_load_command(**kwds):
+ load_command_parts = __docker_prefix(**kwds)
+ load_command_parts.append("load")
+ return " ".join(load_command_parts)
+
+
def build_docker_run_command(
container_command,
image,
@@ -116,7 +121,12 @@
auto_rm=DEFAULT_AUTO_REMOVE,
host=DEFAULT_HOST,
):
- command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
+ command_parts = __docker_prefix(
+ docker_cmd=docker_cmd,
+ sudo=sudo,
+ sudo_cmd=sudo_cmd,
+ host=host
+ )
command_parts.append("run")
if interactive:
command_parts.append("-i")
@@ -144,7 +154,13 @@
return " ".join(command_parts)
-def __docker_prefix(docker_cmd, sudo, sudo_cmd, host):
+def __docker_prefix(
+ docker_cmd=DEFAULT_DOCKER_COMMAND,
+ sudo=DEFAULT_SUDO,
+ sudo_cmd=DEFAULT_SUDO_COMMAND,
+ host=DEFAULT_HOST,
+ **kwds
+):
""" Prefix to issue a docker command.
"""
command_parts = []
diff -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 lib/galaxy/tools/deps/dockerfiles.py
--- a/lib/galaxy/tools/deps/dockerfiles.py
+++ b/lib/galaxy/tools/deps/dockerfiles.py
@@ -2,6 +2,7 @@
from ..deps import commands
from ..deps import docker_util
+from ..deps.containers import docker_cache_path
from ..deps.requirements import parse_requirements_from_xml
from ...tools import loader_directory
@@ -20,11 +21,13 @@
def dockerfile_build(path, dockerfile=None, error=log.error, **kwds):
expected_container_names = set()
+ tool_directories = set()
for (tool_path, tool_xml) in loader_directory.load_tool_elements_from_path(path):
requirements, containers = parse_requirements_from_xml(tool_xml)
for container in containers:
if container.type == "docker":
expected_container_names.add(container.identifier)
+ tool_directories.add(os.path.dirname(tool_path))
break
if len(expected_container_names) == 0:
@@ -34,9 +37,8 @@
error("Multiple different docker identifiers found for selected tools [%s]", expected_container_names)
image_identifier = expected_container_names.pop()
- if dockerfile is None:
- dockerfile = "Dockerfile"
+ dockerfile = __find_dockerfile(dockerfile, tool_directories)
docker_command_parts = docker_util.build_command(
image_identifier,
dockerfile,
@@ -45,10 +47,24 @@
commands.execute(docker_command_parts)
docker_image_cache = kwds['docker_image_cache']
if docker_image_cache:
- destination = os.path.join(docker_image_cache, image_identifier + ".tar")
+ destination = docker_cache_path(docker_image_cache, image_identifier)
save_image_command_parts = docker_util.build_save_image_command(
image_identifier,
destination,
**docker_host_args(**kwds)
)
commands.execute(save_image_command_parts)
+
+
+def __find_dockerfile(dockerfile, tool_directories):
+ if dockerfile is not None:
+ return dockerfile
+ search_directories = ["."]
+ if len(tool_directories) == 1:
+ tool_directory = tool_directories.pop()
+ search_directories.insert(0, tool_directory)
+ for directory in search_directories:
+ potential_dockerfile = os.path.join(directory, "Dockerfile")
+ if os.path.exists(potential_dockerfile):
+ return potential_dockerfile
+ raise Exception("Could not find dockerfile to build.")
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/47171159e9c0/
Changeset: 47171159e9c0
User: jmchilton
Date: 2014-10-07 14:23:41+00:00
Summary: Python 3 fix from planemo.
Affected #: 1 file
diff -r 9cad38925c8da6221a1ce9817d382421c6627ecd -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead lib/galaxy/util/submodules.py
--- a/lib/galaxy/util/submodules.py
+++ b/lib/galaxy/util/submodules.py
@@ -14,7 +14,7 @@
__import__(full_submodule)
submodule = getattr(module, submodule_name)
submodules.append(submodule)
- except BaseException, exception:
+ except BaseException as exception:
exception_str = str(exception)
message = "%s dynamic module could not be loaded: %s" % (full_submodule, exception_str)
log.debug(message)
https://bitbucket.org/galaxy/galaxy-central/commits/6b7782f17e84/
Changeset: 6b7782f17e84
User: jmchilton
Date: 2014-10-07 14:23:41+00:00
Summary: Bring in newer experimental components from downstream work on planemo.
This includes some utilities for working with Dockerfiles requested by Kyle Ellrott, a linting framework for Galaxy tools and a bunch of work on brew integration - most specifically a brew dependency resolver. It is obvious why the brew dependnecy resolver needs to be included in galaxy core - but I am also including the linting stuff here in case we want to reuse it in the tool shed or in the tool form. Sam's new tool form, plus the automatic tool form reloading by me and Kyle, and the tool package downloader by Dave B - is an exciting confluence of features that should really speed up tool development - adding in an GUI tool linting report would pair nicely with these features. (GUI + API work not included here - just the outline of the tool linter).
The homebrew work is tracking progress on building isolated, versioned homebrew environments here - https://github.com/jmchilton/brew-tests.
Allows deployers to add homebrew elements to config/tool_dependency_resolvers_conf.xml. Optional attributes include 'cellar' - this should be the absolute path to the homebrew Cellar to target (defaults to $HOME/.linuxbrew/Cellar under linux and to /usr/local/Cellar under that other operating system Galaxy supports).
'versionless' is another attribute supported by this tag - if set to true - it will ignore the specified package version and just resolve the latest installed homebrew version of that recipe. (If used this should always come after a resolver that respects versions.)
This should work in some superficial way for any brew installed recipe - but it is much more robust and useful for packages installed with the `brew vinstall` external command (found in https://github.com/jmchilton/brew-tests) For `install`ed packages - each dependency must be laided out as a requirement in Galaxy - so samtools 1.1 would require to second requirement tag for hstlib for instance. For `vinstall`ed packages the dependencies are recorded at install time and can be reproducibily recovered at runtime without requiring modifying the state of the Cellar or even needing brew installed at runtime on the worker (only the Cellar directory needs to be avaialable).
Affected #: 15 files
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/deps/brew_exts.py
--- /dev/null
+++ b/lib/galaxy/tools/deps/brew_exts.py
@@ -0,0 +1,470 @@
+#!/usr/bin/env python
+
+# % brew vinstall samtools 1.0
+# % brew vinstall samtools 0.1.19
+# % brew vinstall samtools 1.1
+# % brew env samtools 1.1
+# PATH=/home/john/.linuxbrew/Cellar/htslib/1.1/bin:/home/john/.linuxbrew/Cellar/samtools/1.1/bin:$PATH
+# export PATH
+# LD_LIBRARY_PATH=/home/john/.linuxbrew/Cellar/htslib/1.1/lib:/home/john/.linuxbrew/Cellar/samtools/1.1/lib:$LD_LIBRARY_PATH
+# export LD_LIBRARY_PATH
+# % . <(brew env samtools 1.1)
+# % which samtools
+# /home/john/.linuxbrew/Cellar/samtools/1.1/bin/samtools
+# % . <(brew env samtools 0.1.19)
+# % which samtools
+# /home/john/.linuxbrew/Cellar/samtools/0.1.19/bin/samtools
+# % brew vuninstall samtools 1.0
+# % brew vdeps samtools 1.1
+# htslib(a)1.1
+# % brew vdeps samtools 0.1.19
+
+from __future__ import print_function
+
+import argparse
+import contextlib
+import json
+import glob
+import os
+import re
+import sys
+import subprocess
+
+WHITESPACE_PATTERN = re.compile("[\s]+")
+
+DESCRIPTION = "Script built on top of linuxbrew to operate on isolated, versioned brew installed environments."
+
+if sys.platform == "darwin":
+ DEFAULT_HOMEBREW_ROOT = "/usr/local"
+else:
+ DEFAULT_HOMEBREW_ROOT = os.path.join(os.path.expanduser("~"), ".linuxbrew")
+
+NO_BREW_ERROR_MESSAGE = "Could not find brew on PATH, please place on path or pass to script with --brew argument."
+CANNOT_DETERMINE_TAP_ERROR_MESSAGE = "Cannot determine tap of specified recipe - please use fully qualified recipe (e.g. homebrew/science/samtools)."
+VERBOSE = False
+RELAXED = False
+
+
+class BrewContext(object):
+
+ def __init__(self, args=None):
+ ensure_brew_on_path(args)
+ raw_config = brew_execute(["config"])
+ config_lines = [l.strip().split(":", 1) for l in raw_config.split("\n") if l]
+ config = dict([(p[0].strip(), p[1].strip()) for p in config_lines])
+ # unset if "/usr/local" -> https://github.com/Homebrew/homebrew/blob/master/Library/Homebrew/cmd/confi…
+ homebrew_prefix = config.get("HOMEBREW_PREFIX", "/usr/local")
+ homebrew_cellar = config.get("HOMEBREW_CELLAR", os.path.join(homebrew_prefix, "Cellar"))
+ self.homebrew_prefix = homebrew_prefix
+ self.homebrew_cellar = homebrew_cellar
+
+
+class RecipeContext(object):
+
+ @staticmethod
+ def from_args(args, brew_context=None):
+ return RecipeContext(args.recipe, args.version, brew_context)
+
+ def __init__(self, recipe, version, brew_context=None):
+ self.recipe = recipe
+ self.version = version
+ self.brew_context = brew_context or BrewContext()
+
+ @property
+ def cellar_path(self):
+ return recipe_cellar_path(self.brew_context.homebrew_cellar, self.recipe, self.version)
+
+ @property
+ def tap_path(self):
+ return os.path.join(self.brew_context.homebrew_prefix, "Library", "Taps", self.__tap_path(self.recipe))
+
+ def __tap_path(self, recipe):
+ parts = recipe.split("/")
+ if len(parts) == 1:
+ info = brew_info(self.recipe)
+ from_url = info["from_url"]
+ if not from_url:
+ raise Exception(CANNOT_DETERMINE_TAP_ERROR_MESSAGE)
+ from_url_parts = from_url.split("/")
+ blob_index = from_url_parts.index("blob") # comes right after username and repository
+ if blob_index < 2:
+ raise Exception(CANNOT_DETERMINE_TAP_ERROR_MESSAGE)
+ username = from_url_parts[blob_index - 2]
+ repository = from_url_parts[blob_index - 1]
+ else:
+ assert len(parts) == 3
+ parts = recipe.split("/")
+ username = parts[0]
+ repository = "homebrew-%s" % parts[1]
+
+ path = os.path.join(username, repository)
+ return path
+
+
+def main():
+ global VERBOSE
+ global RELAXED
+ parser = argparse.ArgumentParser(description=DESCRIPTION)
+ parser.add_argument("--brew", help="Path to linuxbrew 'brew' executable to target")
+ actions = ["vinstall", "vuninstall", "vdeps", "vinfo", "env"]
+ action = __action(sys)
+ if not action:
+ parser.add_argument('action', metavar='action', help="Versioned action to perform.", choices=actions)
+ parser.add_argument('recipe', metavar='recipe', help="Recipe for action - should be absolute (e.g. homebrew/science/samtools).")
+ parser.add_argument('version', metavar='version', help="Version for action (e.g. 0.1.19).")
+ parser.add_argument('--relaxed', action='store_true', help="Relaxed processing - for instance allow use of env on non-vinstall-ed recipes.")
+ parser.add_argument('--verbose', action='store_true', help="Verbose output")
+ args = parser.parse_args()
+ if args.verbose:
+ VERBOSE = True
+ if args.relaxed:
+ RELAXED = True
+ if not action:
+ action = args.action
+ brew_context = BrewContext(args)
+ recipe_context = RecipeContext.from_args(args, brew_context)
+ if action == "vinstall":
+ versioned_install(recipe_context, args.recipe, args.version)
+ elif action == "vuninstall":
+ brew_execute(["switch", args.recipe, args.version])
+ brew_execute(["uninstall", args.recipe])
+ elif action == "vdeps":
+ print_versioned_deps(recipe_context, args.recipe, args.version)
+ elif action == "env":
+ env_statements = build_env_statements_from_recipe_context(recipe_context)
+ print(env_statements)
+ elif action == "vinfo":
+ with brew_head_at_version(recipe_context, args.recipe, args.version):
+ print(brew_info(args.recipe))
+ else:
+ raise NotImplementedError()
+
+
+class CommandLineException(Exception):
+
+ def __init__(self, command, stdout, stderr):
+ self.command = command
+ self.stdout = stdout
+ self.stderr = stderr
+ self.message = ("Failed to execute command-line %s, stderr was:\n"
+ "-------->>begin stderr<<--------\n"
+ "%s\n"
+ "-------->>end stderr<<--------\n"
+ "-------->>begin stdout<<--------\n"
+ "%s\n"
+ "-------->>end stdout<<--------\n"
+ ) % (command, stderr, stdout)
+
+ def __str__(self):
+ return self.message
+
+
+def versioned_install(recipe_context, package=None, version=None):
+ if package is None:
+ package = recipe_context.recipe
+ version = recipe_context.version
+
+ attempt_unlink(package)
+ with brew_head_at_version(recipe_context, package, version):
+ deps = brew_deps(package)
+ deps_metadata = []
+ dep_to_version = {}
+ for dep in deps:
+ version_info = brew_versions_info(dep, recipe_context.tap_path)[0]
+ dep_version = version_info[0]
+ dep_to_version[dep] = dep_version
+ versioned = version_info[2]
+ if versioned:
+ dep_to_version[dep] = dep_version
+ versioned_install(recipe_context, dep, dep_version)
+ else:
+ # Install latest.
+ dep_to_version[dep] = None
+ unversioned_install(dep)
+ try:
+ for dep in deps:
+ dep_version = dep_to_version[dep]
+ if dep_version:
+ brew_execute(["switch", dep, dep_version])
+ else:
+ brew_execute(["link", dep])
+ # dep_version obtained from brew versions doesn't
+ # include revision. This linked_keg attribute does.
+ keg_verion = brew_info(dep)["linked_keg"]
+ dep_metadata = {
+ 'name': dep,
+ 'version': keg_verion,
+ 'versioned': versioned
+ }
+ deps_metadata.append(dep_metadata)
+
+ brew_execute(["install", package])
+ deps = brew_execute(["deps", package])
+ deps = [d.strip() for d in deps.split("\n") if d]
+ metadata = {
+ 'deps': deps_metadata
+ }
+ cellar_root = recipe_context.brew_context.homebrew_cellar
+ cellar_path = recipe_cellar_path( cellar_root, package, version )
+ v_metadata_path = os.path.join(cellar_path, "INSTALL_RECEIPT_VERSIONED.json")
+ with open(v_metadata_path, "w") as f:
+ json.dump(metadata, f)
+
+ finally:
+ attempt_unlink_all(package, deps)
+
+
+def commit_for_version(recipe_context, package, version):
+ tap_path = recipe_context.tap_path
+ commit = None
+ with brew_head_at_commit("master", tap_path):
+ version_to_commit = brew_versions_info(package, tap_path)
+ if version is None:
+ version = version_to_commit[0][0]
+ commit = version_to_commit[0][1]
+ else:
+ for mapping in version_to_commit:
+ if mapping[0] == version:
+ commit = mapping[1]
+ if commit is None:
+ raise Exception("Failed to find commit for version %s" % version)
+ return commit
+
+
+def print_versioned_deps(recipe_context, recipe, version):
+ deps = load_versioned_deps(recipe_context.cellar_path)
+ for dep in deps:
+ val = dep['name']
+ if dep['versioned']:
+ val += "@%s" % dep['version']
+ print(val)
+
+
+def load_versioned_deps(cellar_path, relaxed=None):
+ if relaxed is None:
+ relaxed = RELAXED
+ v_metadata_path = os.path.join(cellar_path, "INSTALL_RECEIPT_VERSIONED.json")
+ if not os.path.isfile(v_metadata_path):
+ if RELAXED:
+ return []
+ else:
+ raise IOError("Could not locate versioned receipt file: {}".format(v_metadata_path))
+ with open(v_metadata_path, "r") as f:
+ metadata = json.load(f)
+ return metadata['deps']
+
+
+def unversioned_install(package):
+ try:
+ deps = brew_deps(package)
+ for dep in deps:
+ brew_execute(["link", dep])
+ brew_execute(["install", package])
+ finally:
+ attempt_unlink_all(package, deps)
+
+
+def attempt_unlink_all(package, deps):
+ for dep in deps:
+ attempt_unlink(dep)
+ attempt_unlink(package)
+
+
+def attempt_unlink(package):
+ try:
+ brew_execute(["unlink", package])
+ except Exception:
+ # TODO: warn
+ pass
+
+
+def brew_execute(args):
+ os.environ["HOMEBREW_NO_EMOJI"] = "1" # simplify brew parsing.
+ cmds = ["brew"] + args
+ return execute(cmds)
+
+
+def build_env_statements_from_recipe_context(recipe_context, **kwds):
+ cellar_root = recipe_context.brew_context.homebrew_cellar
+ env_statements = build_env_statements(cellar_root, recipe_context.cellar_path, **kwds)
+ return env_statements
+
+
+def build_env_statements(cellar_root, cellar_path, relaxed=None):
+ deps = load_versioned_deps(cellar_path, relaxed=relaxed)
+
+ path_appends = []
+ ld_path_appends = []
+
+ def handle_keg(cellar_path):
+ bin_path = os.path.join(cellar_path, "bin")
+ if os.path.isdir(bin_path):
+ path_appends.append(bin_path)
+ lib_path = os.path.join(cellar_path, "lib")
+ if os.path.isdir(lib_path):
+ ld_path_appends.append(lib_path)
+
+ for dep in deps:
+ package = dep['name']
+ version = dep['version']
+ dep_cellar_path = recipe_cellar_path( cellar_root, package, version )
+ handle_keg( dep_cellar_path )
+
+ handle_keg( cellar_path )
+ env_statements = []
+ if path_appends:
+ env_statements.append("PATH=" + ":".join(path_appends) + ":$PATH")
+ env_statements.append("export PATH")
+ if ld_path_appends:
+ env_statements.append("LD_LIBRARY_PATH=" + ":".join(ld_path_appends) + ":$LD_LIBRARY_PATH")
+ env_statements.append("export LD_LIBRARY_PATH")
+ return "\n".join(env_statements)
+
+
+(a)contextlib.contextmanager
+def brew_head_at_version(recipe_context, package, version):
+ commit = commit_for_version(recipe_context, package, version)
+ tap_path = recipe_context.tap_path
+ with brew_head_at_commit(commit, tap_path):
+ yield
+
+
+(a)contextlib.contextmanager
+def brew_head_at_commit(commit, tap_path):
+ try:
+ os.chdir(tap_path)
+ current_commit = git_execute(["rev-parse", "HEAD"]).strip()
+ try:
+ git_execute(["checkout", commit])
+ yield
+ finally:
+ git_execute(["checkout", current_commit])
+ finally:
+ # TODO: restore chdir - or better yet just don't chdir
+ # shouldn't be needed.
+ pass
+
+
+def git_execute(args):
+ cmds = ["git"] + args
+ return execute(cmds)
+
+
+def execute(cmds):
+ p = subprocess.Popen(cmds, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ #log = p.stdout.read()
+ global VERBOSE
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ raise CommandLineException(" ".join(cmds), stdout, stderr)
+ if VERBOSE:
+ print(stdout)
+ return stdout
+
+
+def brew_deps(package):
+ stdout = brew_execute(["deps", package])
+ return [p.strip() for p in stdout.split("\n") if p]
+
+
+def brew_info(recipe):
+ info_json = brew_execute(["info", "--json=v1", recipe])
+ info = json.loads(info_json)[0]
+ info.update(extended_brew_info(recipe))
+ return info
+
+
+def extended_brew_info(recipe):
+ # Extract more info from non-json variant. JSON variant should
+ # include this in a backward compatible way (TODO: Open PR).
+ raw_info = brew_execute(["info", recipe])
+ extra_info = dict(
+ from_url=None,
+ build_dependencies=[],
+ required_dependencies=[],
+ recommended_dependencies=[],
+ optional_dependencies=[],
+ )
+
+ for line in raw_info.split("\n"):
+ if line.startswith("From: "):
+ extra_info["from_url"] = line[len("From: "):].strip()
+ for dep_type in ["Build", "Required", "Recommended", "Optional"]:
+ if line.startswith("%s: " % dep_type):
+ key = "%s_dependencies" % dep_type.lower()
+ raw_val = line[len("%s: " % dep_type):]
+ extra_info[key].extend(raw_val.split(", "))
+ return extra_info
+
+
+def brew_versions_info(package, tap_path):
+
+ def versioned(recipe_path):
+ if not os.path.isabs(recipe_path):
+ recipe_path = os.path.join(os.getcwd(), recipe_path)
+ # Dependencies in the same repository should be versioned,
+ # core dependencies (presumably in base homebrew) are not
+ # versioned.
+ return tap_path in recipe_path
+
+ # TODO: Also use tags.
+ stdout = brew_execute(["versions", package])
+ version_parts = [l for l in stdout.split("\n") if l and "git checkout" in l]
+ version_parts = map(lambda l: WHITESPACE_PATTERN.split(l), version_parts)
+ info = [(p[0], p[3], versioned(p[4])) for p in version_parts]
+ return info
+
+
+def __action(sys):
+ script_name = os.path.basename(sys.argv[0])
+ if script_name.startswith("brew-"):
+ return script_name[len("brew-"):]
+ else:
+ return None
+
+
+def recipe_cellar_path(cellar_path, recipe, version):
+ recipe_base = recipe.split("/")[-1]
+ recipe_base_path = os.path.join(cellar_path, recipe_base, version)
+ revision_paths = glob.glob(recipe_base_path + "_*")
+ if revision_paths:
+ revisions = map(lambda x: int(x.rsplit("_", 1)[-1]), revision_paths)
+ max_revision = max(revisions)
+ recipe_path = "%s_%d" % (recipe_base_path, max_revision)
+ else:
+ recipe_path = recipe_base_path
+ return recipe_path
+
+
+def ensure_brew_on_path(args):
+ brew_on_path = which("brew")
+ if brew_on_path:
+ brew_on_path = os.path.abspath(brew_on_path)
+
+ def ensure_on_path(brew):
+ if brew != brew_on_path:
+ os.environ["PATH"] = "%s:%s" % (os.path.dirname(brew), os.environ["PATH"])
+
+ default_brew_path = os.path.join(DEFAULT_HOMEBREW_ROOT, "bin", "brew")
+ if args and args.brew:
+ user_brew_path = os.path.abspath(args.brew)
+ ensure_on_path(user_brew_path)
+ elif brew_on_path:
+ return brew_on_path
+ elif os.path.exists(default_brew_path):
+ ensure_on_path(default_brew_path)
+ else:
+ raise Exception(NO_BREW_ERROR_MESSAGE)
+
+
+def which(file):
+ # http://stackoverflow.com/questions/5226958/which-equivalent-function-in-pyt…
+ for path in os.environ["PATH"].split(":"):
+ if os.path.exists(path + "/" + file):
+ return path + "/" + file
+
+ return None
+
+
+if __name__ == "__main__":
+ main()
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/deps/brew_util.py
--- /dev/null
+++ b/lib/galaxy/tools/deps/brew_util.py
@@ -0,0 +1,40 @@
+""" brew_exts defines generic extensions to Homebrew this file
+builds on those abstraction and provides Galaxy specific functionality
+not useful to the brew external commands.
+"""
+from ..deps import brew_exts
+
+DEFAULT_TAP = "homebrew/science"
+
+
+class HomebrewRecipe(object):
+
+ def __init__(self, recipe, version, tap):
+ self.recipe = recipe
+ self.version = version
+ self.tap = tap
+
+
+def requirements_to_recipes(requirements):
+ return filter(None, map(requirement_to_recipe, requirements))
+
+
+def requirement_to_recipe(requirement):
+ if requirement.type != "package":
+ return None
+ # TOOD: Allow requirements to annotate optionalbrew specific
+ # adaptions.
+ recipe_name = requirement.name
+ recipe_version = requirement.version
+ return HomebrewRecipe(recipe_name, recipe_version, tap=DEFAULT_TAP)
+
+
+def requirements_to_recipe_contexts(requirements, brew_context):
+ def to_recipe_context(homebrew_recipe):
+ return brew_exts.RecipeContext(
+ homebrew_recipe.recipe,
+ homebrew_recipe.version,
+ brew_context
+ )
+ return map(to_recipe_context, requirements_to_recipes(requirements))
+
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/deps/commands.py
--- /dev/null
+++ b/lib/galaxy/tools/deps/commands.py
@@ -0,0 +1,54 @@
+import os
+import subprocess
+
+
+def shell(cmds, env=None):
+ popen_kwds = dict(
+ shell=True,
+ )
+ if env:
+ new_env = os.environ.copy()
+ new_env.update(env)
+ popen_kwds["env"] = new_env
+ p = subprocess.Popen(cmds, **popen_kwds)
+ return p.wait()
+
+
+def execute(cmds):
+ return __wait(cmds, shell=False)
+
+
+def which(file):
+ # http://stackoverflow.com/questions/5226958/which-equivalent-function-in-pyt…
+ for path in os.environ["PATH"].split(":"):
+ if os.path.exists(path + "/" + file):
+ return path + "/" + file
+
+ return None
+
+
+def __wait(cmds, **popen_kwds):
+ p = subprocess.Popen(cmds, **popen_kwds)
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ raise CommandLineException(" ".join(cmds), stdout, stderr)
+ return stdout
+
+
+class CommandLineException(Exception):
+
+ def __init__(self, command, stdout, stderr):
+ self.command = command
+ self.stdout = stdout
+ self.stderr = stderr
+ self.message = ("Failed to execute command-line %s, stderr was:\n"
+ "-------->>begin stderr<<--------\n"
+ "%s\n"
+ "-------->>end stderr<<--------\n"
+ "-------->>begin stdout<<--------\n"
+ "%s\n"
+ "-------->>end stdout<<--------\n"
+ ) % (command, stderr, stdout)
+
+ def __str__(self):
+ return self.message
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/deps/docker_util.py
--- a/lib/galaxy/tools/deps/docker_util.py
+++ b/lib/galaxy/tools/deps/docker_util.py
@@ -1,3 +1,4 @@
+import os
DEFAULT_DOCKER_COMMAND = "docker"
DEFAULT_SUDO = True
@@ -51,6 +52,34 @@
return ":".join([self.from_path, self.to_path, self.how])
+def build_command(
+ image,
+ docker_build_path,
+ docker_cmd=DEFAULT_DOCKER_COMMAND,
+ sudo=DEFAULT_SUDO,
+ sudo_cmd=DEFAULT_SUDO_COMMAND,
+ host=DEFAULT_HOST,
+):
+ if os.path.isfile(docker_build_path):
+ docker_build_path = os.path.dirname(os.path.abspath(docker_build_path))
+ build_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
+ build_command_parts.extend(["build", "-t", image, docker_build_path])
+ return build_command_parts
+
+
+def build_save_image_command(
+ image,
+ destination,
+ docker_cmd=DEFAULT_DOCKER_COMMAND,
+ sudo=DEFAULT_SUDO,
+ sudo_cmd=DEFAULT_SUDO_COMMAND,
+ host=DEFAULT_HOST,
+):
+ build_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
+ build_command_parts.extend(["save", "-o", destination, image])
+ return build_command_parts
+
+
def build_docker_cache_command(
image,
docker_cmd=DEFAULT_DOCKER_COMMAND,
@@ -72,6 +101,7 @@
def build_docker_run_command(
container_command,
image,
+ interactive=False,
tag=None,
volumes=[],
volumes_from=DEFAULT_VOLUMES_FROM,
@@ -88,6 +118,8 @@
):
command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
command_parts.append("run")
+ if interactive:
+ command_parts.append("-i")
for env_directive in env_directives:
command_parts.extend(["-e", env_directive])
for volume in volumes:
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/deps/dockerfiles.py
--- /dev/null
+++ b/lib/galaxy/tools/deps/dockerfiles.py
@@ -0,0 +1,54 @@
+import os
+
+from ..deps import commands
+from ..deps import docker_util
+from ..deps.requirements import parse_requirements_from_xml
+from ...tools import loader_directory
+
+import logging
+log = logging.getLogger(__name__)
+
+
+def docker_host_args(**kwds):
+ return dict(
+ docker_cmd=kwds["docker_cmd"],
+ sudo=kwds["docker_sudo"],
+ sudo_cmd=kwds["docker_sudo_cmd"],
+ host=kwds["docker_host"]
+ )
+
+
+def dockerfile_build(path, dockerfile=None, error=log.error, **kwds):
+ expected_container_names = set()
+ for (tool_path, tool_xml) in loader_directory.load_tool_elements_from_path(path):
+ requirements, containers = parse_requirements_from_xml(tool_xml)
+ for container in containers:
+ if container.type == "docker":
+ expected_container_names.add(container.identifier)
+ break
+
+ if len(expected_container_names) == 0:
+ error("Could not find any docker identifiers to generate.")
+
+ if len(expected_container_names) > 1:
+ error("Multiple different docker identifiers found for selected tools [%s]", expected_container_names)
+
+ image_identifier = expected_container_names.pop()
+ if dockerfile is None:
+ dockerfile = "Dockerfile"
+
+ docker_command_parts = docker_util.build_command(
+ image_identifier,
+ dockerfile,
+ **docker_host_args(**kwds)
+ )
+ commands.execute(docker_command_parts)
+ docker_image_cache = kwds['docker_image_cache']
+ if docker_image_cache:
+ destination = os.path.join(docker_image_cache, image_identifier + ".tar")
+ save_image_command_parts = docker_util.build_save_image_command(
+ image_identifier,
+ destination,
+ **docker_host_args(**kwds)
+ )
+ commands.execute(save_image_command_parts)
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/deps/resolvers/homebrew.py
--- /dev/null
+++ b/lib/galaxy/tools/deps/resolvers/homebrew.py
@@ -0,0 +1,96 @@
+"""
+This file implements a brew resolver for Galaxy requirements. In order for Galaxy
+to pick up on recursively defined and versioned brew dependencies recipes should
+be installed using the experimental `brew-vinstall` external command.
+
+More information here:
+
+https://github.com/jmchilton/brew-tests
+https://github.com/Homebrew/homebrew-science/issues/1191
+
+This is still an experimental module and there will almost certainly be backward
+incompatible changes coming.
+"""
+
+import os
+
+from ..brew_exts import DEFAULT_HOMEBREW_ROOT, recipe_cellar_path, build_env_statements
+from ..resolvers import DependencyResolver, INDETERMINATE_DEPENDENCY, Dependency
+
+# TODO: Implement prefer version linked...
+PREFER_VERSION_LINKED = 'linked'
+PREFER_VERSION_LATEST = 'latest'
+UNKNOWN_PREFER_VERSION_MESSAGE_TEMPLATE = "HomebrewDependencyResolver prefer_version must be latest %s"
+UNKNOWN_PREFER_VERSION_MESSAGE = UNKNOWN_PREFER_VERSION_MESSAGE_TEMPLATE % (PREFER_VERSION_LATEST)
+DEFAULT_PREFER_VERSION = PREFER_VERSION_LATEST
+
+
+class HomebrewDependencyResolver(DependencyResolver):
+ resolver_type = "homebrew"
+
+ def __init__(self, dependency_manager, **kwds):
+ self.versionless = _string_as_bool(kwds.get('versionless', 'false'))
+ self.prefer_version = kwds.get('prefer_version', None)
+
+ if self.prefer_version is None:
+ self.prefer_version = DEFAULT_PREFER_VERSION
+
+ if self.versionless and self.prefer_version not in [PREFER_VERSION_LATEST]:
+ raise Exception(UNKNOWN_PREFER_VERSION_MESSAGE)
+
+ cellar_root = kwds.get('cellar', None)
+ if cellar_root is None:
+ cellar_root = os.path.join(DEFAULT_HOMEBREW_ROOT, "Cellar")
+
+ self.cellar_root = cellar_root
+
+ def resolve(self, name, version, type, **kwds):
+ if type != "package":
+ return INDETERMINATE_DEPENDENCY
+
+ if version is None or self.versionless:
+ return self._find_dep_default(name, version)
+ else:
+ return self._find_dep_versioned(name, version)
+
+ def _find_dep_versioned(self, name, version):
+ recipe_path = recipe_cellar_path(self.cellar_root, name, version)
+ if not os.path.exists(recipe_path) or not os.path.isdir(recipe_path):
+ return INDETERMINATE_DEPENDENCY
+
+ commands = build_env_statements(self.cellar_root, recipe_path, relaxed=True)
+ return HomebrewDependency(commands)
+
+ def _find_dep_default(self, name, version):
+ installed_versions = self._installed_versions(name)
+ if not installed_versions:
+ return INDETERMINATE_DEPENDENCY
+
+ # Just grab newest installed version - may make sense some day to find
+ # the linked version instead.
+ default_version = sorted(installed_versions, reverse=True)[0]
+ return self._find_dep_versioned(name, default_version)
+
+ def _installed_versions(self, recipe):
+ recipe_base_path = os.path.join(self.cellar_root, recipe)
+ if not os.path.exists(recipe_base_path):
+ return []
+
+ names = os.listdir(recipe_base_path)
+ return filter(lambda n: os.path.isdir(os.path.join(recipe_base_path, n)), names)
+
+
+class HomebrewDependency(Dependency):
+
+ def __init__(self, commands):
+ self.commands = commands
+
+ def shell_commands(self, requirement):
+ return self.commands.replace("\n", ";") + "\n"
+
+
+def _string_as_bool( value ):
+ return str( value ).lower() == "true"
+
+
+__all__ = [HomebrewDependencyResolver]
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/lint.py
--- /dev/null
+++ b/lib/galaxy/tools/lint.py
@@ -0,0 +1,89 @@
+from __future__ import print_function
+import inspect
+from galaxy.util import submodules
+
+LEVEL_ALL = "all"
+LEVEL_WARN = "warn"
+LEVEL_ERROR = "error"
+
+
+def lint_xml(tool_xml, level=LEVEL_ALL, fail_level=LEVEL_WARN):
+ import galaxy.tools.linters
+ lint_context = LintContext(level=level)
+ linter_modules = submodules.submodules(galaxy.tools.linters)
+ for module in linter_modules:
+ for (name, value) in inspect.getmembers(module):
+ if callable(value) and name.startswith("lint_"):
+ lint_context.lint(module, name, value, tool_xml)
+ found_warns = lint_context.found_warns
+ found_errors = lint_context.found_errors
+ if level == LEVEL_WARN and (found_warns or found_errors):
+ return False
+ else:
+ return found_errors
+
+
+class LintContext(object):
+
+ def __init__(self, level):
+ self.level = level
+ self.found_errors = False
+ self.found_warns = False
+
+ def lint(self, module, name, lint_func, tool_xml):
+ self.printed_linter_info = False
+ self.valid_messages = []
+ self.info_messages = []
+ self.warn_messages = []
+ self.error_messages = []
+ lint_func(tool_xml, self)
+ # TODO: colorful emoji if in click CLI.
+ if self.error_messages:
+ status = "FAIL"
+ elif self.warn_messages:
+
+ status = "WARNING"
+ else:
+ status = "CHECK"
+
+ def print_linter_info():
+ if self.printed_linter_info:
+ return
+ self.printed_linter_info = True
+ print("Applying linter %s... %s" % (name, status))
+
+ for message in self.error_messages:
+ self.found_errors = True
+ print_linter_info()
+ print(".. ERROR: %s" % message)
+
+ if self.level != LEVEL_ERROR:
+ for message in self.warn_messages:
+ self.found_warns = True
+ print_linter_info()
+ print(".. WARNING: %s" % message)
+
+ if self.level == LEVEL_ALL:
+ for message in self.info_messages:
+ print_linter_info()
+ print(".. INFO: %s" % message)
+ for message in self.valid_messages:
+ print_linter_info()
+ print(".. CHECK: %s" % message)
+
+ def __handle_message(self, message_list, message, *args):
+ if args:
+ message = message % args
+ message_list.append(message)
+
+ def valid(self, message, *args):
+ self.__handle_message(self.valid_messages, message, *args)
+
+ def info(self, message, *args):
+ self.__handle_message(self.info_messages, message, *args)
+
+ def error(self, message, *args):
+ self.__handle_message(self.error_messages, message, *args)
+
+ def warn(self, message, *args):
+ self.__handle_message(self.warn_messages, message, *args)
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/linters/__init__.py
--- /dev/null
+++ b/lib/galaxy/tools/linters/__init__.py
@@ -0,0 +1,2 @@
+""" Framework for linting tools.
+"""
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/linters/citations.py
--- /dev/null
+++ b/lib/galaxy/tools/linters/citations.py
@@ -0,0 +1,27 @@
+
+
+def lint_citations(tool_xml, lint_ctx):
+ root = tool_xml.getroot()
+ citations = root.findall("citations")
+ if len(citations) > 1:
+ lint_ctx.error("More than one citation section found, behavior undefined.")
+ return
+
+ if len(citations) == 0:
+ lint_ctx.warn("No citations found, consider adding citations to your tool.")
+ return
+
+ valid_citations = 0
+ for citation in citations[0]:
+ if citation.tag != "citation":
+ lint_ctx.warn("Unknown tag discovered in citations block [%s], will be ignored." % citation.tag)
+ if "type" in citation.attrib:
+ citation_type = citation.attrib.get("type")
+ if citation_type not in ["doi", "bibtex"]:
+ lint_ctx.warn("Unknown citation type discovered [%s], will be ignored.", citation_type)
+ else:
+ valid_citations += 1
+
+ if valid_citations > 0:
+ lint_ctx.valid("Found %d likely valid citations.", valid_citations)
+
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/linters/help.py
--- /dev/null
+++ b/lib/galaxy/tools/linters/help.py
@@ -0,0 +1,15 @@
+
+
+def lint_help(tool_xml, lint_ctx):
+ root = tool_xml.getroot()
+ helps = root.findall("help")
+ if len(helps) > 1:
+ lint_ctx.error("More than one help section found, behavior undefined.")
+ return
+
+ if len(helps) == 0:
+ lint_ctx.warn("No help section found, consider adding a help section to your tool.")
+ return
+
+ # TODO: validate help section RST.
+ lint_ctx.valid("Tool contains help section.")
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/linters/inputs.py
--- /dev/null
+++ b/lib/galaxy/tools/linters/inputs.py
@@ -0,0 +1,38 @@
+
+
+def lint_inputs(tool_xml, lint_ctx):
+ inputs = tool_xml.findall("./inputs//param")
+ num_inputs = 0
+ for param in inputs:
+ num_inputs += 1
+ param_attrib = param.attrib
+ has_errors = False
+ if "type" not in param_attrib:
+ lint_ctx.error("Found param input with type specified.")
+ has_errors = True
+ if "name" not in param_attrib:
+ lint_ctx.error("Found param input with not name specified.")
+ has_errors = True
+
+ if has_errors:
+ continue
+
+ param_type = param_attrib["type"]
+ param_name = param_attrib["name"]
+ if param_type == "data_input":
+ if "format" not in param_attrib:
+ lint_ctx.warn("Found param input %s contains no format specified - 'data' format will be assumed.", param_name)
+ # TODO: Validate type, much more...
+ if num_inputs:
+ lint_ctx.info("Found %d input parameters.", num_inputs)
+ else:
+ lint_ctx.warn("Found not input parameters.")
+
+
+def lint_repeats(tool_xml, lint_ctx):
+ repeats = tool_xml.findall("./inputs//repeat")
+ for repeat in repeats:
+ if "name" not in repeat.attrib:
+ lint_ctx.error("Repeat does not specify name attribute.")
+ if "title" not in repeat.attrib:
+ lint_ctx.error("Repeat does not specify title attribute.")
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/linters/outputs.py
--- /dev/null
+++ b/lib/galaxy/tools/linters/outputs.py
@@ -0,0 +1,25 @@
+
+
+def lint_output(tool_xml, lint_ctx):
+ outputs = tool_xml.findall("./outputs/data")
+ if not outputs:
+ lint_ctx.warn("Tool contains no outputs, most tools should produce outputs..")
+ return
+
+ num_outputs = 0
+ for output in outputs:
+ num_outputs += 1
+ output_attrib = output.attrib
+ format_set = False
+ if "format" in output_attrib:
+ format_set = True
+ format = output_attrib["format"]
+ if format == "input":
+ lint_ctx.warn("Using format='input' on output data, format_source attribute is less ambigious and should be used instead.")
+ elif "format_source" in output_attrib:
+ format_set = True
+
+ if not format_set:
+ lint_ctx.warn("Tool data output doesn't define an output format.")
+
+ lint_ctx.info("%d output datasets found.", num_outputs)
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/linters/tests.py
--- /dev/null
+++ b/lib/galaxy/tools/linters/tests.py
@@ -0,0 +1,20 @@
+
+
+# Misspelled so as not be picked up by nosetests.
+def lint_tsts(tool_xml, lint_ctx):
+ tests = tool_xml.findall("./tests/test")
+ if not tests:
+ lint_ctx.warn("No tests found, most tools should define test cases.")
+
+ num_valid_tests = 0
+ for test in tests:
+ outputs = test.findall("output")
+ if not outputs:
+ lint_ctx.warn("No outputs defined for tests, this test is likely invalid.")
+ else:
+ num_valid_tests += 1
+
+ if num_valid_tests:
+ lint_ctx.valid("%d test(s) found.", num_valid_tests)
+ else:
+ lint_ctx.warn("No valid test(s) found.")
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/linters/top_level.py
--- /dev/null
+++ b/lib/galaxy/tools/linters/top_level.py
@@ -0,0 +1,17 @@
+
+def lint_top_level(tree, lint_ctx):
+ root = tree.getroot()
+ if "version" not in root.attrib:
+ lint_ctx.error("Tool does not define a version attribute.")
+ else:
+ lint_ctx.valid("Tool defines a version.")
+
+ if "name" not in root.attrib:
+ lint_ctx.error("Tool does not define a name attribute.")
+ else:
+ lint_ctx.valid("Tool defines a name.")
+
+ if "id" not in root.attrib:
+ lint_ctx.error("Tool does not define an id attribute.")
+ else:
+ lint_ctx.valid("Tool defines an id name.")
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/loader_directory.py
--- /dev/null
+++ b/lib/galaxy/tools/loader_directory.py
@@ -0,0 +1,31 @@
+import glob
+import os
+from ..tools import loader
+
+PATH_DOES_NOT_EXIST_ERROR = "Could not load tools from path [%s] - this path does not exist."
+
+
+def load_tool_elements_from_path(path):
+ tool_elements = []
+ for file in __find_tool_files(path):
+ if __looks_like_a_tool(file):
+ tool_elements.append((file, loader.load_tool(file)))
+ return tool_elements
+
+
+def __looks_like_a_tool(path):
+ with open(path) as f:
+ for i in range(10):
+ line = f.next()
+ if "<tool" in line:
+ return True
+ return False
+
+
+def __find_tool_files(path):
+ if not os.path.exists(path):
+ raise Exception(PATH_DOES_NOT_EXIST_ERROR)
+ if not os.path.isdir(path):
+ return [os.path.abspath(path)]
+ else:
+ return map(os.path.abspath, glob.glob(path + "/**.xml"))
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jmchilton: Update master API key handling in tests for d7dd1f9.
by commits-noreply@bitbucket.org 07 Oct '14
by commits-noreply@bitbucket.org 07 Oct '14
07 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9cad38925c8d/
Changeset: 9cad38925c8d
User: jmchilton
Date: 2014-10-07 01:25:30+00:00
Summary: Update master API key handling in tests for d7dd1f9.
Now aware of anyone actually overriding this with GALAXY_TEST_MASTER_API_KEY so not maintaining backward compatibility with respect to that environment variable.
Affected #: 1 file
diff -r d7dd1f92d5b8e35ed9530fc5f0494e160ff8c4da -r 9cad38925c8da6221a1ce9817d382421c6627ecd test/base/api_util.py
--- a/test/base/api_util.py
+++ b/test/base/api_util.py
@@ -9,7 +9,11 @@
configured as a master API key and should be able to create additional
users and keys.
"""
- return os.environ.get( "GALAXY_TEST_MASTER_API_KEY", DEFAULT_GALAXY_MASTER_API_KEY )
+ for key in ["GALAXY_CONFIG_MASTER_API_KEY", "GALAXY_CONFIG_OVERRIDE_MASTER_API_KEY"]:
+ value = os.environ.get(key, None)
+ if value:
+ return value
+ return DEFAULT_GALAXY_MASTER_API_KEY
def get_user_api_key():
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jmchilton: Make functional tests to respect GALAXY_CONFIG_ environment variables.
by commits-noreply@bitbucket.org 07 Oct '14
by commits-noreply@bitbucket.org 07 Oct '14
07 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d7dd1f92d5b8/
Changeset: d7dd1f92d5b8
User: jmchilton
Date: 2014-10-07 00:56:58+00:00
Summary: Make functional tests to respect GALAXY_CONFIG_ environment variables.
Functional tests don't work without the tweak to imports in cloudlaunch - not sure if that has always been a problem and I am just running the tests in a different Galaxy instance or if the earlier import of util caused the problem.
Regardless I guess we shoud update to a version of bioblend that doesn't require simplejson.
Affected #: 2 files
diff -r 594b48fe90b7b17ed22f5c597837022d8204db47 -r d7dd1f92d5b8e35ed9530fc5f0494e160ff8c4da lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
--- a/lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
+++ b/lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
@@ -17,6 +17,7 @@
eggs.require('PyYAML')
eggs.require('boto')
+eggs.require('simplejson')
eggs.require('bioblend')
from boto.exception import EC2ResponseError
diff -r 594b48fe90b7b17ed22f5c597837022d8204db47 -r d7dd1f92d5b8e35ed9530fc5f0494e160ff8c4da scripts/functional_tests.py
--- a/scripts/functional_tests.py
+++ b/scripts/functional_tests.py
@@ -16,6 +16,7 @@
from base.tool_shed_util import parse_tool_panel_config
from galaxy import eggs
+from galaxy.util.properties import load_app_properties
eggs.require( "nose" )
eggs.require( "NoseHTML" )
@@ -401,6 +402,9 @@
kwargs[ 'global_conf' ] = get_webapp_global_conf()
kwargs[ 'global_conf' ][ '__file__' ] = galaxy_config_file
kwargs[ 'config_file' ] = galaxy_config_file
+ kwargs = load_app_properties(
+ kwds=kwargs
+ )
# Build the Universe Application
app = UniverseApplication( **kwargs )
database_contexts.galaxy_context = app.model.context
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0