galaxy-commits
Threads by month
- ----- 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
February 2014
- 1 participants
- 192 discussions
commit/galaxy-central: greg: Enhance the Tool Shed fabric_util.wait_for_process method to timeout after a reasonable period of waiting for stderr or stdout during tool dependency package compilation.
by commits-noreply@bitbucket.org 24 Feb '14
by commits-noreply@bitbucket.org 24 Feb '14
24 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ef5f750810f7/
Changeset: ef5f750810f7
User: greg
Date: 2014-02-24 16:20:14
Summary: Enhance the Tool Shed fabric_util.wait_for_process method to timeout after a reasonable period of waiting for stderr or stdout during tool dependency package compilation.
Affected #: 1 file
diff -r f573461f3667e8f120dc05bbd11a019d5fae1960 -r ef5f750810f791d39d5fe37f256b2526fa9916ae lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -38,6 +38,7 @@
log = logging.getLogger( __name__ )
INSTALLATION_LOG = 'INSTALLATION.log'
+NO_CMD_OUTPUT_TIMEOUT = 600
VIRTUALENV_URL = 'https://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.9.1.tar.gz'
@@ -829,19 +830,46 @@
return env
def wait_for_process( process_handle, stream_output, stdout_queue, stderr_queue ):
+ pid = process_handle.pid
standard_out = []
standard_err = []
process_handle.wait()
+ # Generate stdout.
while True:
- line = stdout_queue.get()
- if line is None:
+ try:
+ line = stdout_queue.get( timeout=NO_CMD_OUTPUT_TIMEOUT )
+ except Queue.Empty:
+ err_msg = "\nShutting down process id %s because it generated no stdout for the defined timout period of %d seconds.\n" % \
+ ( pid, NO_CMD_OUTPUT_TIMEOUT )
+ print err_msg
+ standard_out.append( err_msg )
+ stdout_queue.task_done()
+ process_handle.kill()
break
- standard_out.append(line)
+ else:
+ if line:
+ standard_out.append( line )
+ else:
+ stdout_queue.task_done()
+ break
+ # Generate stderr.
while True:
- line = stderr_queue.get()
- if line is None:
+ try:
+ line = stderr_queue.get( timeout=NO_CMD_OUTPUT_TIMEOUT )
+ except Queue.Empty:
+ err_msg = "\nShutting down process id %s because it generated no stderr for the defined timout period of %d seconds.\n" % \
+ ( pid, NO_CMD_OUTPUT_TIMEOUT )
+ print err_msg
+ standard_err.append( err_msg )
+ stderr_queue.task_done()
+ process_handle.kill()
break
- standard_err.append(line)
+ else:
+ if line:
+ standard_err.append( line )
+ else:
+ stderr_queue.task_done()
+ break
stdout = '\n'.join( standard_out )
stderr = '\n'.join( standard_err )
return stdout, stderr
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: Charts: Remove message box
by commits-noreply@bitbucket.org 24 Feb '14
by commits-noreply@bitbucket.org 24 Feb '14
24 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f573461f3667/
Changeset: f573461f3667
User: guerler
Date: 2014-02-24 08:47:45
Summary: Charts: Remove message box
Affected #: 2 files
diff -r dc448888a8651b5555f54e838532ab09e0248cbd -r f573461f3667e8f120dc05bbd11a019d5fae1960 config/plugins/visualizations/charts/static/app.js
--- a/config/plugins/visualizations/charts/static/app.js
+++ b/config/plugins/visualizations/charts/static/app.js
@@ -79,7 +79,11 @@
// refresh title
_refreshTitle: function() {
- this.portlet.title('Charts - ' + this.config.get('title'));
+ var title = this.config.get('title');
+ if (title) {
+ title = ' - ' + title;
+ }
+ this.portlet.title('Charts' + title);
},
// current view
diff -r dc448888a8651b5555f54e838532ab09e0248cbd -r f573461f3667e8f120dc05bbd11a019d5fae1960 config/plugins/visualizations/charts/static/views/chart.js
--- a/config/plugins/visualizations/charts/static/views/chart.js
+++ b/config/plugins/visualizations/charts/static/views/chart.js
@@ -253,7 +253,7 @@
this.chart.set('id', Utils.uuid());
this.chart.set('dataset_id', this.app.options.dataset.id);
this.chart.set('type', 'bardiagram');
- this.chart.set('title', 'Chart title');
+ this.chart.set('title', 'New Chart');
},
// create chart
@@ -266,22 +266,6 @@
date : Utils.time()
});
- // validate
- if (!this.chart.get('title')) {
- this.message.update({message : 'Please enter a title for your chart.'});
- return;
- }
-
- if (!this.chart.get('type')) {
- this.message.update({message : 'Please select a chart type.'});
- return;
- }
-
- if (this.chart.groups.length == 0) {
- this.message.update({message : 'Please configure at least one data source.'});
- return;
- }
-
// create/get chart
var current = this.app.charts.get(this.chart.id);
if (!current) {
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: Ui: Fix title function in portlets
by commits-noreply@bitbucket.org 24 Feb '14
by commits-noreply@bitbucket.org 24 Feb '14
24 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/dc448888a865/
Changeset: dc448888a865
User: guerler
Date: 2014-02-24 08:17:36
Summary: Ui: Fix title function in portlets
Affected #: 7 files
diff -r 33b8fa988ad0cf58277553f1cc569a581cfd652d -r dc448888a8651b5555f54e838532ab09e0248cbd config/plugins/visualizations/charts/static/app.js
--- a/config/plugins/visualizations/charts/static/app.js
+++ b/config/plugins/visualizations/charts/static/app.js
@@ -40,7 +40,7 @@
// create portlet
if (!this.options.config.widget) {
- this.portlet = new Portlet.View({icon : 'fa-bar-chart-o', title : 'Charts'});
+ this.portlet = new Portlet.View({icon : 'fa-bar-chart-o'});
} else {
this.portlet = $('<div></div>');
}
@@ -64,6 +64,22 @@
this.config.on('change:current_view', function() {
self._showCurrent();
});
+ this.config.on('change:title', function() {
+ self._refreshTitle();
+ });
+
+ // render
+ this.render();
+ },
+
+ // render
+ render: function() {
+ this._refreshTitle();
+ },
+
+ // refresh title
+ _refreshTitle: function() {
+ this.portlet.title('Charts - ' + this.config.get('title'));
},
// current view
diff -r 33b8fa988ad0cf58277553f1cc569a581cfd652d -r dc448888a8651b5555f54e838532ab09e0248cbd config/plugins/visualizations/charts/static/models/config.js
--- a/config/plugins/visualizations/charts/static/models/config.js
+++ b/config/plugins/visualizations/charts/static/models/config.js
@@ -9,7 +9,8 @@
defaults : {
query_limit : 20,
query_pace : 1000,
- query_max : 5
+ query_max : 5,
+ title : 'Create a new chart'
}
});
diff -r 33b8fa988ad0cf58277553f1cc569a581cfd652d -r dc448888a8651b5555f54e838532ab09e0248cbd config/plugins/visualizations/charts/static/views/chart.js
--- a/config/plugins/visualizations/charts/static/views/chart.js
+++ b/config/plugins/visualizations/charts/static/views/chart.js
@@ -23,11 +23,6 @@
// configure options
this.options = Utils.merge(options, this.optionsDefault);
- // main elements
- this.message = new Ui.Message();
- this.title = new Ui.Input({placeholder: 'Chart title'});
- this.dataset = new Ui.Input({value : app.options.dataset.id, disabled: true, visible: false});
-
//
// table with chart types
//
@@ -115,9 +110,21 @@
}
});
- // construct element
+ //
+ // main/default tab
+ //
+
+ // construct elements
+ this.title = new Ui.Input({
+ placeholder: 'Chart title',
+ onchange: function() {
+ self.app.config.set('title', self.title.value());
+ }
+ });
+ this.dataset = new Ui.Input({value : app.options.dataset.id, disabled: true, visible: false});
+
+ // append element
var $settings = $('<div/>');
- $settings.append(Utils.wrap(this.message.$el));
$settings.append(Utils.wrap((new Ui.Label({ title : 'Provide a chart title:'})).$el));
$settings.append(Utils.wrap(this.title.$el));
$settings.append(Utils.wrap((new Ui.Label({ title : 'Select a chart type:'})).$el));
@@ -140,6 +147,7 @@
var self = this;
this.chart.on('change:title', function(chart) {
self.title.value(chart.get('title'));
+ self.app.config.set('title', chart.get('title'));
});
this.chart.on('change:type', function(chart) {
self.table.value(chart.get('type'));
diff -r 33b8fa988ad0cf58277553f1cc569a581cfd652d -r dc448888a8651b5555f54e838532ab09e0248cbd config/plugins/visualizations/charts/static/views/charts.js
--- a/config/plugins/visualizations/charts/static/views/charts.js
+++ b/config/plugins/visualizations/charts/static/views/charts.js
@@ -25,6 +25,13 @@
self.app.chart_view.$el.show();
},
onchange : function(chart_id) {
+ // get chart
+ var chart = self.app.charts.get(chart_id);
+
+ // update main title
+ self.app.config.set('title', chart.get('title'));
+
+ // show viewport
self.app.viewport_view.show(chart_id);
}
});
diff -r 33b8fa988ad0cf58277553f1cc569a581cfd652d -r dc448888a8651b5555f54e838532ab09e0248cbd config/plugins/visualizations/charts/static/views/viewport.js
--- a/config/plugins/visualizations/charts/static/views/viewport.js
+++ b/config/plugins/visualizations/charts/static/views/viewport.js
@@ -25,8 +25,7 @@
// add table to portlet
this.portlet = new Portlet.View({
- title : '',
- icon : 'fa-signal',
+ title : 'title',
height : this.options.height,
overflow : 'hidden',
operations : {
diff -r 33b8fa988ad0cf58277553f1cc569a581cfd652d -r dc448888a8651b5555f54e838532ab09e0248cbd static/scripts/mvc/ui/ui-portlet.js
--- a/static/scripts/mvc/ui/ui-portlet.js
+++ b/static/scripts/mvc/ui/ui-portlet.js
@@ -10,7 +10,7 @@
// defaults options
optionsDefault: {
title : '',
- icon : 'fa-tasks',
+ icon : '',
buttons : null,
body : null,
height : null,
@@ -20,6 +20,7 @@
},
// elements
+ $title : null,
$content : null,
$buttons : null,
$operations : null,
@@ -35,6 +36,9 @@
// link content
this.$content = this.$el.find('#content');
+ // link title
+ this.$title = this.$el.find('#title-text');
+
// set content height
if (this.options.height) {
this.$el.find('#body').css('height', this.options.height);
@@ -128,7 +132,7 @@
// title
title: function(new_title) {
- var $el = this.$el.find('#title');
+ var $el = this.$title;
if (new_title) {
$el.html(new_title);
}
@@ -147,7 +151,7 @@
if (options.icon)
tmpl += '<i style="padding-top: 3px; float: left; font-size: 1.2em" class="icon fa ' + options.icon + '"> </i>';
- tmpl += '<div id="title" style="padding-top: 2px; float: left;">' + options.title + '</div>';
+ tmpl += '<div id="title-text" style="padding-top: 2px; float: left;">' + options.title + '</div>';
tmpl += '</div>' +
'</div>';
diff -r 33b8fa988ad0cf58277553f1cc569a581cfd652d -r dc448888a8651b5555f54e838532ab09e0248cbd static/scripts/packed/mvc/ui/ui-portlet.js
--- a/static/scripts/packed/mvc/ui/ui-portlet.js
+++ b/static/scripts/packed/mvc/ui/ui-portlet.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){var b=Backbone.View.extend({visible:false,optionsDefault:{title:"",icon:"fa-tasks",buttons:null,body:null,height:null,operations:null,placement:"bottom",overflow:"auto"},$content:null,$buttons:null,$operations:null,initialize:function(d){this.options=a.merge(d,this.optionsDefault);this.setElement(this._template(this.options));this.$content=this.$el.find("#content");if(this.options.height){this.$el.find("#body").css("height",this.options.height);this.$el.find("#content").css("overflow",this.options.overflow)}this.$buttons=$(this.el).find("#buttons");if(this.options.buttons){var c=this;$.each(this.options.buttons,function(e,f){f.$el.prop("id",e);c.$buttons.append(f.$el)})}else{this.$buttons.remove()}this.$operations=$(this.el).find("#operations");if(this.options.operations){var c=this;$.each(this.options.operations,function(e,f){f.$el.prop("id",e);c.$operations.append(f.$el)})}if(this.options.body){this.append(this.options.body)}},append:function(c){this.$content.append(a.wrap(c))},content:function(){return this.$content},show:function(){this.$el.fadeIn("fast");this.visible=true},hide:function(){this.$el.fadeOut("fast");this.visible=false},enableButton:function(c){this.$buttons.find("#"+c).prop("disabled",false)},disableButton:function(c){this.$buttons.find("#"+c).prop("disabled",true)},hideOperation:function(c){this.$operations.find("#"+c).hide()},showOperation:function(c){this.$operations.find("#"+c).show()},setOperation:function(e,d){var c=this.$operations.find("#"+e);c.off("click");c.on("click",d)},title:function(d){var c=this.$el.find("#title");if(d){c.html(d)}return c.html()},_template:function(d){var c='<div class="toolForm">';if(d.title||d.icon){c+='<div id="title" class="toolFormTitle" style="overflow:hidden;"><div id="operations" style="float: right;"></div><div style="overflow: hidden">';if(d.icon){c+='<i style="padding-top: 3px; float: left; font-size: 1.2em" class="icon fa '+d.icon+'"> </i>'}c+='<div id="title" style="padding-top: 2px; float: left;">'+d.title+"</div>";c+="</div></div>"}c+='<div id="body" class="toolFormBody">';if(d.placement=="top"){c+='<div id="buttons" class="buttons" style="height: 50px; padding: 10px;"></div>'}c+='<div id="content" class="content" style="height: inherit; padding: 10px;"></div>';if(d.placement=="bottom"){c+='<div id="buttons" class="buttons" style="height: 50px; padding: 10px;"></div>'}c+="</div></div>";return c}});return{View:b}});
\ No newline at end of file
+define(["utils/utils"],function(a){var b=Backbone.View.extend({visible:false,optionsDefault:{title:"",icon:"",buttons:null,body:null,height:null,operations:null,placement:"bottom",overflow:"auto"},$title:null,$content:null,$buttons:null,$operations:null,initialize:function(d){this.options=a.merge(d,this.optionsDefault);this.setElement(this._template(this.options));this.$content=this.$el.find("#content");this.$title=this.$el.find("#title-text");if(this.options.height){this.$el.find("#body").css("height",this.options.height);this.$el.find("#content").css("overflow",this.options.overflow)}this.$buttons=$(this.el).find("#buttons");if(this.options.buttons){var c=this;$.each(this.options.buttons,function(e,f){f.$el.prop("id",e);c.$buttons.append(f.$el)})}else{this.$buttons.remove()}this.$operations=$(this.el).find("#operations");if(this.options.operations){var c=this;$.each(this.options.operations,function(e,f){f.$el.prop("id",e);c.$operations.append(f.$el)})}if(this.options.body){this.append(this.options.body)}},append:function(c){this.$content.append(a.wrap(c))},content:function(){return this.$content},show:function(){this.$el.fadeIn("fast");this.visible=true},hide:function(){this.$el.fadeOut("fast");this.visible=false},enableButton:function(c){this.$buttons.find("#"+c).prop("disabled",false)},disableButton:function(c){this.$buttons.find("#"+c).prop("disabled",true)},hideOperation:function(c){this.$operations.find("#"+c).hide()},showOperation:function(c){this.$operations.find("#"+c).show()},setOperation:function(e,d){var c=this.$operations.find("#"+e);c.off("click");c.on("click",d)},title:function(d){var c=this.$title;if(d){c.html(d)}return c.html()},_template:function(d){var c='<div class="toolForm">';if(d.title||d.icon){c+='<div id="title" class="toolFormTitle" style="overflow:hidden;"><div id="operations" style="float: right;"></div><div style="overflow: hidden">';if(d.icon){c+='<i style="padding-top: 3px; float: left; font-size: 1.2em" class="icon fa '+d.icon+'"> </i>'}c+='<div id="title-text" style="padding-top: 2px; float: left;">'+d.title+"</div>";c+="</div></div>"}c+='<div id="body" class="toolFormBody">';if(d.placement=="top"){c+='<div id="buttons" class="buttons" style="height: 50px; padding: 10px;"></div>'}c+='<div id="content" class="content" style="height: inherit; padding: 10px;"></div>';if(d.placement=="bottom"){c+='<div id="buttons" class="buttons" style="height: 50px; padding: 10px;"></div>'}c+="</div></div>";return c}});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: Charts: Load tab titles from model
by commits-noreply@bitbucket.org 24 Feb '14
by commits-noreply@bitbucket.org 24 Feb '14
24 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/33b8fa988ad0/
Changeset: 33b8fa988ad0
User: guerler
Date: 2014-02-24 07:14:42
Summary: Charts: Load tab titles from model
Affected #: 1 file
diff -r 462a28f96c2172113d1cad657e271e792493b49e -r 33b8fa988ad0cf58277553f1cc569a581cfd652d config/plugins/visualizations/charts/static/views/chart.js
--- a/config/plugins/visualizations/charts/static/views/chart.js
+++ b/config/plugins/visualizations/charts/static/views/chart.js
@@ -10,7 +10,7 @@
header : true,
content : 'No content available.'
},
-
+
// initialize
initialize: function(app, options)
{
@@ -85,7 +85,8 @@
this.tabs = new Tabs.View({
title_new : 'Add Data',
onnew : function() {
- self._addGroupModel();
+ var group = self._addGroupModel();
+ self.tabs.show(group.id);
},
operations : {
'save' : new Ui.ButtonIcon({
@@ -95,8 +96,7 @@
onclick : function() {
// ensure that data group is available
if (self.chart.groups.length == 0) {
- var group = self._addGroupModel();
- self.tabs.show(group.id);
+ self._addGroupModel();
}
// save chart
@@ -171,11 +171,27 @@
this.app.chart.groups.on('reset', function(group) {
self._removeAllGroups();
});
-
+ this.app.chart.groups.on('change:label', function(group) {
+ self._refreshLabels();
+ });
+
// reset
this._resetChart();
},
+ // update
+ _refreshLabels: function() {
+ var self = this;
+ var counter = 0;
+ this.chart.groups.each(function(group) {
+ var title = group.get('label', '');
+ if (title == '') {
+ title = 'Chart data';
+ }
+ self.tabs.title(group.id, ++counter + ': ' + title);
+ });
+ },
+
// new group
_addGroupModel: function() {
var group = new Group({
@@ -199,18 +215,23 @@
// add new tab
this.tabs.add({
- title : count + ': Chart Data',
id : group.id,
$el : group_view.$el,
ondel : function() {
self.chart.groups.remove(group.id);
}
});
+
+ // update titles
+ this._refreshLabels()
},
// remove group
_removeGroup: function(group) {
this.tabs.del(group.id);
+
+ // update titles
+ this._refreshLabels()
},
// remove group
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: Ui/Charts: Enable user to add/remove tabs and include that in Charts
by commits-noreply@bitbucket.org 23 Feb '14
by commits-noreply@bitbucket.org 23 Feb '14
23 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/462a28f96c21/
Changeset: 462a28f96c21
User: guerler
Date: 2014-02-24 06:44:07
Summary: Ui/Charts: Enable user to add/remove tabs and include that in Charts
Affected #: 12 files
diff -r fac578cca75887d811e67993a655fed20c0d8713 -r 462a28f96c2172113d1cad657e271e792493b49e config/plugins/visualizations/charts/static/app.js
--- a/config/plugins/visualizations/charts/static/app.js
+++ b/config/plugins/visualizations/charts/static/app.js
@@ -1,10 +1,10 @@
// dependencies
define(['mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils',
- 'plugin/views/charts', 'plugin/views/viewport', 'plugin/views/chart', 'plugin/views/group',
- 'plugin/models/config', 'plugin/models/datasets', 'plugin/models/chart', 'plugin/models/charts', 'plugin/models/group', 'plugin/models/types'],
+ 'plugin/views/charts', 'plugin/views/viewport', 'plugin/views/chart',
+ 'plugin/models/config', 'plugin/models/datasets', 'plugin/models/chart', 'plugin/models/charts', 'plugin/models/types'],
function( Portlet, Ui, Utils,
- ChartsView, ViewportView, ChartView, GroupView,
- Config, Datasets, Chart, Charts, Group, Types
+ ChartsView, ViewportView, ChartView,
+ Config, Datasets, Chart, Charts, Types
) {
// widget
@@ -26,14 +26,12 @@
this.types = new Types();
this.chart = new Chart();
this.charts = new Charts();
- this.group = new Group();
// create dataset handler
this.datasets = new Datasets(this);
// create views
this.charts_view = new ChartsView(this);
- this.group_view = new GroupView(this);
this.chart_view = new ChartView(this);
this.viewport_view = new ViewportView(this);
@@ -49,9 +47,8 @@
// append views
this.portlet.append(this.charts_view.$el);
- this.portlet.append(this.group_view.$el);
this.portlet.append(this.chart_view.$el);
-
+
// set element
if (!this.options.config.widget) {
this.setElement(this.portlet.$el);
@@ -60,7 +57,6 @@
}
// hide views
- this.group_view.$el.hide();
this.charts_view.$el.hide();
// events
diff -r fac578cca75887d811e67993a655fed20c0d8713 -r 462a28f96c2172113d1cad657e271e792493b49e config/plugins/visualizations/charts/static/library/table.js
--- a/config/plugins/visualizations/charts/static/library/table.js
+++ b/config/plugins/visualizations/charts/static/library/table.js
@@ -20,8 +20,8 @@
// events
events : {
- 'click' : 'onclick',
- 'dblclick' : 'ondblclick'
+ 'click' : '_onclick',
+ 'dblclick' : '_ondblclick'
},
// first
@@ -33,7 +33,7 @@
this.options = Utils.merge(options, this.optionsDefault);
// create new element
- this.setElement(this.template(options));
+ this.setElement(this._template(options));
// initialize row
this.row = $('<tr></tr>');
@@ -64,46 +64,26 @@
// append
append: function(id) {
- this.commit(id);
+ this._commit(id);
},
// prepend
prepend: function(id) {
- this.commit(id, true);
- },
-
- // commit
- commit: function(id, prepend) {
- // add
- this.row.attr('id', id);
-
- // add row
- if (prepend) {
- $(this.el).find('tbody').prepend(this.row);
- } else {
- $(this.el).find('tbody').append(this.row);
- }
-
- // row
- this.row = $('<tr></tr>');
-
- // row count
- this.row_count++;
- this.refresh();
+ this._commit(id, true);
},
// remove
remove: function(id) {
$(this.el).find('#' + id).remove();
this.row_count--;
- this.refresh();
+ this._refresh();
},
// remove
removeAll: function() {
$(this.el).find('tbody').html('');
this.row_count = 0;
- this.refresh();
+ this._refresh();
},
// value
@@ -134,13 +114,28 @@
}
},
- // confirm new value
- confirm: function(new_value) {
- this.value(new_value);
+ // commit
+ _commit: function(id, prepend) {
+ // add
+ this.row.attr('id', id);
+
+ // add row
+ if (prepend) {
+ $(this.el).find('tbody').prepend(this.row);
+ } else {
+ $(this.el).find('tbody').append(this.row);
+ }
+
+ // row
+ this.row = $('<tr></tr>');
+
+ // row count
+ this.row_count++;
+ this._refresh();
},
// onclick
- onclick: function(e) {
+ _onclick: function(e) {
// get values
var old_value = this.value();
var new_value = $(e.target).closest('tr').attr('id');
@@ -150,13 +145,13 @@
if (this.options.onconfirm) {
this.options.onconfirm(new_value);
} else {
- this.confirm(new_value);
+ this.value(new_value);
}
}
},
- // onclick
- ondblclick: function(e) {
+ // ondblclick
+ _ondblclick: function(e) {
var value = this.value();
if (value && this.options.ondblclick) {
this.options.ondblclick(value);
@@ -164,7 +159,7 @@
},
// refresh
- refresh: function() {
+ _refresh: function() {
if (this.row_count == 0) {
this.$el.find('tmessage').show();
} else {
@@ -173,7 +168,7 @@
},
// load html template
- template: function(options)
+ _template: function(options)
{
return '<div>' +
'<table class="grid">' +
diff -r fac578cca75887d811e67993a655fed20c0d8713 -r 462a28f96c2172113d1cad657e271e792493b49e config/plugins/visualizations/charts/static/library/ui.js
--- a/config/plugins/visualizations/charts/static/library/ui.js
+++ b/config/plugins/visualizations/charts/static/library/ui.js
@@ -6,7 +6,7 @@
{
// options
optionsDefault: {
- label : ''
+ title : ''
},
// initialize
@@ -15,17 +15,17 @@
this.options = Utils.merge(options, this.optionsDefault);
// create new element
- this.setElement(this.template(this.options));
+ this.setElement(this._template(this.options));
},
// template
- template: function(options) {
- return '<label><b>' + options.label + '</b></label>';
+ _template: function(options) {
+ return '<label><b>' + options.title + '</b></label>';
},
// value
value: function() {
- return options.label;
+ return options.title;
}
});
@@ -35,10 +35,9 @@
// options
optionsDefault: {
id : null,
- label : '',
+ title : '',
float : 'right',
cls : 'btn-default',
- type : 'submit',
icon : ''
},
@@ -52,43 +51,99 @@
// add event
$(this.el).on('click', options.onclick);
+
+ // add tooltip
+ $(this.el).tooltip({title: options.tooltip, placement: 'bottom'});
+ },
+
+ // element
+ _template: function(options) {
+ var str = '<button id="' + options.id + '" type="submit" style="margin-right: 5px; float: ' + options.float + ';" type="button" class="btn ' + options.cls + '">';
+ if (options.icon) {
+ str += '<i class="icon fa ' + options.icon + '"></i> ' ;
+ }
+ str += options.title +
+ '</button>';
+ return str;
+ }
+});
+
+// plugin
+var ButtonIcon = Backbone.View.extend(
+{
+ // options
+ optionsDefault: {
+ title : '',
+ id : null,
+ float : 'right',
+ cls : 'icon-btn',
+ icon : '',
+ tooltip : ''
+ },
+
+ // initialize
+ initialize : function(options) {
+ // get options
+ this.options = Utils.merge(options, this.optionsDefault);
+
+ // create new element
+ this.setElement(this._template(this.options));
+
+ // add event
+ $(this.el).on('click', options.onclick);
+
+ // add tooltip
+ $(this.el).tooltip({title: options.tooltip, placement: 'bottom'});
+ },
+
+ // element
+ _template: function(options) {
+ // width
+ var width = '';
+ if (options.title) {
+ width = 'width: auto;';
+ }
+
+ // string
+ var str = '<div id="' + options.id + '" style="margin-right: 5px; float: ' + options.float + '; ' + width + '" class="' + options.cls + '">';
+
+ // title
+ if (options.title) {
+ str += '<div style="margin-right: 5px; margin-left: 5px;">' +
+ '<i class="icon fa ' + options.icon + '"/> ' +
+ '<span style="position: relative; font-size: 0.8em; top: -1px;">' + options.title + '</span>' +
+ '</div>';
+ } else {
+ str += '<i class="icon fa ' + options.icon + '"/>';
+ }
+ str += '</div>';
+ return str;
+ }
+});
+
+// plugin
+var Anchor = Backbone.View.extend(
+{
+ // options
+ optionsDefault: {
+ title : ''
+ },
+
+ // initialize
+ initialize : function(options) {
+ // get options
+ this.options = Utils.merge(options, this.optionsDefault);
+
+ // create new element
+ this.setElement(this._template(this.options));
+
+ // add event
+ $(this.el).on('click', options.onclick);
},
// element
_template: function(options) {
- var str = '<button id="' + options.id + '" type="' + options.type + '" style="margin-right: 5px; float: ' + options.float + ';" type="button" class="btn ' + options.cls + '">';
- if (options.icon) {
- str += '<i class="icon fa ' + options.icon + '"></i> ' ;
- }
- str += options.label +
- '</button>';
- return str;
- }
-});
-
-// plugin
-var Anchor = Backbone.View.extend(
-{
- // options
- optionsDefault: {
- label : ''
- },
-
- // initialize
- initialize : function(options) {
- // get options
- this.options = Utils.merge(options, this.optionsDefault);
-
- // create new element
- this.setElement(this._template(this.options));
-
- // add event
- $(this.el).on('click', options.onclick);
- },
-
- // element
- _template: function(options) {
- return '<div><a href="javascript:void(0)">' + options.label + '</a></div>';
+ return '<div><a href="javascript:void(0)">' + options.title + '</a></div>';
}
});
@@ -118,7 +173,7 @@
// show message
if (options.message != '') {
- this.$el.html(this.template(this.options));
+ this.$el.html(this._template(this.options));
this.$el.fadeIn();
// check if message is persistent
@@ -139,7 +194,7 @@
},
// element
- template: function(options) {
+ _template: function(options) {
return '<div class="alert alert-' + options.status + '" style="padding: 2px 2px 2px 10px;">' + options.message + '</div>';
}
});
@@ -159,7 +214,7 @@
this.options = Utils.merge(options, this.optionsDefault);
// create new element
- this.setElement(this.template(this.options));
+ this.setElement(this._template(this.options));
// add click event
var self = this;
@@ -172,7 +227,7 @@
},
// element
- template: function(options) {
+ _template: function(options) {
return '<div class="search">' +
'<form onsubmit="return false;">' +
'<input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="' + options.searchword + '">' +
@@ -189,7 +244,7 @@
{
// options
optionsDefault: {
- label : 'Unlabeled',
+ title : 'Unlabeled',
body : null
},
@@ -199,7 +254,7 @@
this.options = Utils.merge(options, this.optionsDefault);
// create new element
- this.setElement(this.template(this.options));
+ this.setElement(this._template(this.options));
if (this.options.body) {
this.$el.find('.body').append(this.options.body);
@@ -207,9 +262,9 @@
},
// element
- template: function(options) {
+ _template: function(options) {
return '<div id="title" class="title">' +
- options.label + ':' +
+ options.title + ':' +
'</div>';
}
});
@@ -370,48 +425,6 @@
});
// plugin
-var ButtonIcon = Backbone.View.extend(
-{
- // options
- optionsDefault: {
- id : null,
- label : '',
- float : 'right',
- cls : 'icon-btn',
- type : 'submit',
- icon : '',
- tooltip : ''
- },
-
- // initialize
- initialize : function(options) {
- // get options
- this.options = Utils.merge(options, this.optionsDefault);
-
- // create new element
- this.setElement(this.template(this.options));
-
- // add event
- $(this.el).on('click', options.onclick);
-
- // add tooltip
- $(this.el).tooltip({title: options.tooltip, placement: 'bottom'});
- },
-
- // element
- template: function(options) {
- var str = '<a id="' + options.id + '" style="margin-right: 5px; float: ' + options.float + ';" class="' + options.cls + '">';
- if (options.icon) {
- str += '<i class="icon fa ' + options.icon + '"></i>';
- }
- str += options.label +
- '</a>';
- return str;
- }
-});
-
-
-// plugin
var Input = Backbone.View.extend(
{
// options
@@ -429,7 +442,7 @@
this.options = Utils.merge(options, this.optionsDefault);
// create new element
- this.setElement(this.template(this.options));
+ this.setElement(this._template(this.options));
// disable input field
if (this.options.disabled) {
@@ -440,6 +453,14 @@
if (!this.options.visible) {
this.$el.hide();
}
+
+ // onchange event handler
+ var self = this;
+ if (this.options.onchange) {
+ this.$el.on('input', function() {
+ self.options.onchange();
+ });
+ }
},
// value
@@ -451,7 +472,7 @@
},
// element
- template: function(options) {
+ _template: function(options) {
return '<input id="' + options.id + '" type="' + options.type + '" value="' + options.value + '" placeholder="' + options.placeholder + '" class="form-control">';
}
});
diff -r fac578cca75887d811e67993a655fed20c0d8713 -r 462a28f96c2172113d1cad657e271e792493b49e config/plugins/visualizations/charts/static/library/ui.select.js
--- a/config/plugins/visualizations/charts/static/library/ui.select.js
+++ b/config/plugins/visualizations/charts/static/library/ui.select.js
@@ -19,6 +19,11 @@
// create new element
this.setElement(this._template(this.options));
+ // initial value
+ if (this.options.value) {
+ this.$el.val(this.options.value);
+ }
+
// add change event
var self = this;
if (this.options.onchange) {
diff -r fac578cca75887d811e67993a655fed20c0d8713 -r 462a28f96c2172113d1cad657e271e792493b49e config/plugins/visualizations/charts/static/models/group.js
--- a/config/plugins/visualizations/charts/static/models/group.js
+++ b/config/plugins/visualizations/charts/static/models/group.js
@@ -4,6 +4,12 @@
// model
return Backbone.Model.extend(
{
+ // options
+ defaults : {
+ label : 'Data label',
+ date : ''
+ },
+
// reset
reset: function()
{
diff -r fac578cca75887d811e67993a655fed20c0d8713 -r 462a28f96c2172113d1cad657e271e792493b49e config/plugins/visualizations/charts/static/views/chart.js
--- a/config/plugins/visualizations/charts/static/views/chart.js
+++ b/config/plugins/visualizations/charts/static/views/chart.js
@@ -1,6 +1,6 @@
// dependencies
-define(['mvc/ui/ui-tabs', 'plugin/library/table', 'plugin/library/ui', 'utils/utils', 'plugin/models/chart', 'plugin/views/groups'],
- function(Tabs, Table, Ui, Utils, Chart, GroupsView) {
+define(['mvc/ui/ui-tabs', 'plugin/library/table', 'plugin/library/ui', 'utils/utils', 'plugin/models/chart', 'plugin/models/group', 'plugin/views/group'],
+ function(Tabs, Table, Ui, Utils, Chart, Group, GroupView) {
// widget
return Backbone.View.extend(
@@ -28,10 +28,9 @@
this.title = new Ui.Input({placeholder: 'Chart title'});
this.dataset = new Ui.Input({value : app.options.dataset.id, disabled: true, visible: false});
- // configure dataset
- this.groups_view = new GroupsView(this.app);
-
- // table
+ //
+ // table with chart types
+ //
var self = this;
this.table = new Table({
header : false,
@@ -40,7 +39,7 @@
// show modal
self.app.modal.show({
title : 'Switching the chart type?',
- body : 'You configured data sources. If you switch chart types your configurations will be removed.',
+ body : 'If you continue your data selections will cleared.',
buttons : {
'Cancel' : function() {
// hide modal
@@ -51,13 +50,13 @@
self.app.modal.hide();
// confirm
- self.table.confirm(type);
+ self.table.value(type);
}
}
});
} else {
// confirm
- self.table.confirm(type);
+ self.table.value(type);
}
},
onchange : function(type) {
@@ -70,7 +69,7 @@
content: 'No chart types available'
});
- // add types
+ // load chart types into table
var types_n = 0;
var types = app.types.attributes;
for (var id in types){
@@ -80,47 +79,55 @@
this.table.append(id);
}
+ //
+ // tabs
+ //
+ this.tabs = new Tabs.View({
+ title_new : 'Add Data',
+ onnew : function() {
+ self._addGroupModel();
+ },
+ operations : {
+ 'save' : new Ui.ButtonIcon({
+ icon : 'fa-save',
+ tooltip : 'Draw Chart',
+ title : 'Draw',
+ onclick : function() {
+ // ensure that data group is available
+ if (self.chart.groups.length == 0) {
+ var group = self._addGroupModel();
+ self.tabs.show(group.id);
+ }
+
+ // save chart
+ self._saveChart();
+ }
+ }),
+ 'back' : new Ui.ButtonIcon({
+ icon : 'fa-caret-left',
+ tooltip : 'Return to Viewer',
+ title : 'Return',
+ onclick : function() {
+ self.$el.hide();
+ self.app.charts_view.$el.show();
+ }
+ })
+ }
+ });
+
// construct element
var $settings = $('<div/>');
$settings.append(Utils.wrap(this.message.$el));
- $settings.append(Utils.wrap((new Ui.Label({ label : 'Provide a chart title:'})).$el));
+ $settings.append(Utils.wrap((new Ui.Label({ title : 'Provide a chart title:'})).$el));
$settings.append(Utils.wrap(this.title.$el));
- $settings.append(Utils.wrap((new Ui.Label({ label : 'Select a chart type:'})).$el));
+ $settings.append(Utils.wrap((new Ui.Label({ title : 'Select a chart type:'})).$el));
$settings.append(Utils.wrap(this.table.$el));
-
- // tabs
- this.tabs = new Tabs.View({
- operations : {
- 'save' : new Ui.ButtonIcon({
- icon : 'fa-save',
- tooltip : 'Save Chart',
- onclick : function() {
- self._saveChart();
- }
- }),
- 'back' : new Ui.ButtonIcon({
- icon : 'fa-caret-left',
- tooltip : 'Return',
- onclick : function() {
- self.$el.hide();
- self.app.charts_view.$el.show();
- }
- })
- }
- });
// add tab
this.tabs.add({
- $el: $settings,
- title: 'Start',
- id: 'settings'
- });
-
- // add tab
- this.tabs.add({
- $el: this.groups_view.$el,
- title: 'Chart Groups',
- id: 'groups'
+ id : 'settings',
+ title : 'Start',
+ $el : $settings
});
// elements
@@ -129,7 +136,7 @@
// hide back button on startup
this.tabs.hideOperation('back');
- // model events
+ // chart events
var self = this;
this.chart.on('change:title', function(chart) {
self.title.value(chart.get('title'));
@@ -141,7 +148,7 @@
self._resetChart();
});
- // collection events
+ // charts events
this.app.charts.on('add', function(chart) {
self.tabs.showOperation('back');
});
@@ -154,12 +161,66 @@
self.tabs.hideOperation('back');
});
+ // groups events
+ this.app.chart.groups.on('add', function(group) {
+ self._addGroup(group);
+ });
+ this.app.chart.groups.on('remove', function(group) {
+ self._removeGroup(group);
+ });
+ this.app.chart.groups.on('reset', function(group) {
+ self._removeAllGroups();
+ });
+
// reset
this._resetChart();
},
+ // new group
+ _addGroupModel: function() {
+ var group = new Group({
+ id : Utils.uuid(),
+ dataset_id : this.chart.get('dataset_id')
+ });
+ this.chart.groups.add(group);
+ return group;
+ },
+
+ // add group
+ _addGroup: function(group) {
+ // link this
+ var self = this;
+
+ // create view
+ var group_view = new GroupView(this.app, {group: group});
+
+ // number of groups
+ var count = self.chart.groups.length;
+
+ // add new tab
+ this.tabs.add({
+ title : count + ': Chart Data',
+ id : group.id,
+ $el : group_view.$el,
+ ondel : function() {
+ self.chart.groups.remove(group.id);
+ }
+ });
+ },
+
+ // remove group
+ _removeGroup: function(group) {
+ this.tabs.del(group.id);
+ },
+
+ // remove group
+ _removeAllGroups: function(group) {
+ this.tabs.delRemovable();
+ },
+
// reset
_resetChart: function() {
+ // reset chart details
this.chart.set('id', Utils.uuid());
this.chart.set('dataset_id', this.app.options.dataset.id);
this.chart.set('type', 'bardiagram');
diff -r fac578cca75887d811e67993a655fed20c0d8713 -r 462a28f96c2172113d1cad657e271e792493b49e config/plugins/visualizations/charts/static/views/charts.js
--- a/config/plugins/visualizations/charts/static/views/charts.js
+++ b/config/plugins/visualizations/charts/static/views/charts.js
@@ -1,5 +1,5 @@
// dependencies
-define(['mvc/ui/ui-portlet', 'plugin/library/table', 'plugin/library/ui', 'utils/utils'], function(Portlet, Table, Ui, Utils) {
+define(['mvc/ui/ui-portlet', 'plugin/library/table', 'plugin/library/ui', 'utils/utils', 'plugin/models/group'], function(Portlet, Table, Ui, Utils, Group) {
// widget
return Backbone.View.extend(
@@ -17,11 +17,11 @@
// get chart
var chart = self.app.charts.get(chart_id);
self.app.chart.copy(chart);
-
- // show edit
+
+ // hide this element
self.$el.hide();
- // update model and show create
+ // show chart view
self.app.chart_view.$el.show();
},
onchange : function(chart_id) {
diff -r fac578cca75887d811e67993a655fed20c0d8713 -r 462a28f96c2172113d1cad657e271e792493b49e config/plugins/visualizations/charts/static/views/group.js
--- a/config/plugins/visualizations/charts/static/views/group.js
+++ b/config/plugins/visualizations/charts/static/views/group.js
@@ -12,46 +12,34 @@
initialize: function(app, options) {
// link app
this.app = app;
-
+
+ // link this
+ var self = this;
+
// get current chart object
this.chart = this.app.chart;
- this.group = this.app.group;
+
+ // access group
+ this.group = options.group;
// ui elements
- this.message = new Ui.Message();
- this.label = new Ui.Input({placeholder: 'Group label'});
+ this.label = new Ui.Input({
+ placeholder: 'Data label',
+ onchange: function() {
+ self.group.set('label', self.label.value());
+ }
+ });
this.table = new Table({content: 'No data column.'});
// add table to portlet
- var self = this;
- this.portlet = new Portlet.View({
- icon : 'fa-edit',
- title : 'Define group properties:',
- operations : {
- 'save' : new Ui.ButtonIcon({
- icon : 'fa-save',
- tooltip : 'Save',
- onclick : function() {
- // save/add group
- self._saveGroup();
- }
- }),
- 'back' : new Ui.ButtonIcon({
- icon : 'fa-caret-left',
- tooltip : 'Return',
- onclick : function() {
- self.$el.hide();
- self.app.chart_view.$el.show();
- }
- })
- }
- });
- this.portlet.append(this.message.$el);
- this.portlet.append(this.label.$el);
- this.portlet.append(this.table.$el);
+ var $view = $('<div/>');
+ $view.append(Utils.wrap((new Ui.Label({title: 'Provide a label:'})).$el));
+ $view.append(Utils.wrap(this.label.$el));
+ $view.append(Utils.wrap((new Ui.Label({title: 'Select columns:'})).$el));
+ $view.append(Utils.wrap(this.table.$el));
// add element
- this.setElement(this.portlet.$el);
+ this.setElement($view);
// change
var self = this;
@@ -67,20 +55,17 @@
this.group.on('change', function() {
self._refreshGroup();
});
- this.group.on('reset', function() {
- self._resetGroup();
- });
+
+ // refresh
+ this._refresh();
},
- // show
- show: function() {
- this.$el.show();
- },
-
- // reset
- _resetGroup: function() {
- this.group.set('id', Utils.uuid());
- this.group.set('label', 'Group label');
+ // render
+ _refresh: function() {
+ this._refreshDataset();
+ this._refreshType();
+ this._refreshLabel();
+ this._refreshGroup();
},
// update dataset
@@ -98,7 +83,7 @@
// check
if (!dataset) {
- this.app.log('Config::render()', 'Failed to retrieve dataset.');
+ this.app.log('Group::_refreshDataset()', 'Failed to retrieve dataset.');
return;
}
@@ -138,9 +123,13 @@
data : this.columns,
onchange : function(value) {
self.group.set(this.gid, value);
- }
+ },
+ value : this.group.get(id)
});
+ // set model value
+ this.group.set(id, select.value());
+
// add row to table
this.table.add(data_def.title);
this.table.add(select.$el);
@@ -154,14 +143,7 @@
// update
_refreshGroup: function() {
- // update select fields
- for (var id in this.list) {
- var col = this.group.get(id);
- if (col === undefined) {
- col = 0;
- }
- this.list[id].value(col);
- }
+ this.group.set('date', Utils.time());
},
// update label
@@ -171,48 +153,6 @@
label_text = '';
}
this.label.value(label_text);
- },
-
- // create group
- _saveGroup: function() {
- // get current chart
- var chart = this.chart;
-
- // update group object
- var group = this.group;
- for (var key in this.list) {
- group.set(key, this.list[key].value());
- }
-
- // add label
- group.set({
- dataset_id : this.chart.get('dataset_id'),
- label : this.label.value(),
- date : Utils.time()
- });
-
- // validate
- if (!group.get('label')) {
- this.message.update({message : 'Please enter a label for your group.'});
- return;
- }
-
- // get groups of current chart
- var groups = this.chart.groups;
-
- // create/update group
- var group_update = groups.get(group.id);
- if (group_update) {
- group_update.set(group.attributes);
- } else {
- groups.add(group.clone());
- }
-
- // hide
- this.$el.hide();
-
- // update main
- this.app.chart_view.$el.show();
}
});
diff -r fac578cca75887d811e67993a655fed20c0d8713 -r 462a28f96c2172113d1cad657e271e792493b49e config/plugins/visualizations/charts/static/views/groups.js
--- a/config/plugins/visualizations/charts/static/views/groups.js
+++ /dev/null
@@ -1,154 +0,0 @@
-// dependencies
-define(['mvc/ui/ui-portlet', 'plugin/library/table', 'plugin/library/ui', 'utils/utils'], function(Portlet, Table, Ui, Utils) {
-
-// chart config
-return Backbone.View.extend(
-{
- // initialize
- initialize: function(app, options) {
- // link app
- this.app = app;
-
- // get current chart object
- this.chart = this.app.chart;
-
- // table
- this.table = new Table({
- content : 'Add data columns to this table.',
- ondblclick : function(group_id) {
- // get group
- var group = self.app.chart.groups.get(group_id);
-
- // show edit
- self.app.chart_view.$el.hide();
- self.app.group_view.show();
- self.app.group_view.group.set(group.attributes);
- }
- });
-
- // add table to portlet
- var self = this;
- this.portlet = new Portlet.View({
- icon : '',
- title : 'Select data columns:',
- height : 100,
- operations : {
- 'new' : new Ui.ButtonIcon({
- icon : 'fa-plus',
- tooltip: 'Create',
- onclick: function() {
- self.app.group.reset();
- self.app.chart_view.$el.hide();
- self.app.group_view.show();
- }
- }),
- 'edit' : new Ui.ButtonIcon({
- icon : 'fa-pencil',
- tooltip: 'Edit',
- onclick: function() {
- // check if element has been selected
- var group_id = self.table.value();
- if (!group_id) {
- return;
- }
-
- // get group
- var group = self.app.chart.groups.get(group_id);
-
- // show edit
- self.app.chart_view.$el.hide();
- self.app.group_view.show();
- self.app.group_view.group.set(group.attributes);
- }
- }),
- 'delete' : new Ui.ButtonIcon({
- icon : 'fa-minus',
- tooltip: 'Delete',
- onclick: function() {
- // check if element has been selected
- var id = self.table.value();
- if (!id) {
- return;
- }
- // remove group from chart
- self.chart.groups.remove(id);
- }
- })
- }
- });
- this.portlet.append(this.table.$el);
-
- // add element
- this.setElement(this.portlet.$el);
-
- // change
- var self = this;
- this.chart.on('change', function() {
- self._refresh();
- });
- this.chart.on('reset', function() {
- self._removeGroupAll();
- });
- this.chart.on('change:type', function() {
- self.app.group_view.trigger('change');
- });
- this.chart.groups.on('add', function(group) {
- self._addGroup(group);
- });
- this.chart.groups.on('remove', function(group) {
- self._removeGroup(group);
- });
- this.chart.groups.on('reset', function(group) {
- self._removeGroupAll();
- });
- this.chart.groups.on('change', function(group) {
- self._removeGroup(group);
- self._addGroup(group);
- });
- },
-
- // refresh
- _refresh: function() {
- this._removeGroupAll();
- var self = this;
- var groups = this.chart.groups;
- if (groups) {
- groups.each(function(group) { self._addGroup(group); });
- }
- },
-
- // add
- _addGroup: function(group) {
- // make custom info string
- var info = '[';
- var chart_type = this.chart.get('type');
- if (chart_type) {
- var chart_settings = this.app.types.get(chart_type);
- for (var key in chart_settings.data) {
- info += key + '=' + group.get(key) + ', '
- }
- }
- info = info.substring(0, info.length - 2) + ']';
-
- // add to table
- this.table.add(group.get('label'));
- this.table.add(info);
- this.table.add('Last changed: ' + group.get('date'));
- this.table.prepend(group.id);
- this.table.value(group.id);
- },
-
- // remove
- _removeGroup: function(group) {
- // remove from to table
- this.table.remove(group.id);
- },
-
- // data config reset
- _removeGroupAll: function() {
- // reset options table
- this.table.removeAll();
- }
-});
-
-});
\ No newline at end of file
diff -r fac578cca75887d811e67993a655fed20c0d8713 -r 462a28f96c2172113d1cad657e271e792493b49e static/scripts/mvc/ui/ui-portlet.js
--- a/static/scripts/mvc/ui/ui-portlet.js
+++ b/static/scripts/mvc/ui/ui-portlet.js
@@ -109,12 +109,12 @@
this.$buttons.find('#' + id).prop('disabled', true);
},
- // enable operation
+ // hide operation
hideOperation: function(id) {
this.$operations.find('#' + id).hide();
},
- // disable operation
+ // show operation
showOperation: function(id) {
this.$operations.find('#' + id).show();
},
diff -r fac578cca75887d811e67993a655fed20c0d8713 -r 462a28f96c2172113d1cad657e271e792493b49e static/scripts/mvc/ui/ui-tabs.js
--- a/static/scripts/mvc/ui/ui-tabs.js
+++ b/static/scripts/mvc/ui/ui-tabs.js
@@ -12,9 +12,14 @@
$nav: null,
$content: null,
+ // first
+ first_tab: null,
+
// defaults options
optionsDefault: {
- operations: null,
+ title_new : '',
+ operations : null,
+ onnew : null
},
// initialize
@@ -22,10 +27,12 @@
// configure options
this.options = Utils.merge(options, this.optionsDefault);
- // create element
+ // create tabs
var $tabs = $(this._template(this.options));
- this.$nav = $tabs.find('.tab-navigation');
- this.$content = $tabs.find('.tab-content');
+
+ // link elements
+ this.$nav = $tabs.find('.tab-navigation');
+ this.$content = $tabs.find('.tab-content');
// create new element
this.setElement($tabs);
@@ -38,42 +45,111 @@
self.$nav.append(item.$el);
});
}
+
+ // add built-in add-new-tab tab
+ if (this.options.onnew) {
+ // create tab object
+ var $tab_new = $(this._template_tab_new(this.options));
+
+ // append to navbar
+ this.$nav.append($tab_new);
+
+ // add tooltip
+ $tab_new.tooltip({title: 'Add a new tab', placement: 'bottom'});
+
+ // link click event
+ $tab_new.on('click', function(e) {
+ $tab_new.tooltip('hide');
+ self.options.onnew();
+ });
+ }
},
// append
add: function(options) {
- // collect parameters
- var $el = options.$el;
- var title = options.title;
+ // get tab id
var id = options.id;
// create tab object
var tab = {
- $title : $(this._template_tab(options)),
- $content : $(this._template_tab_content(options))
+ $title : $(this._template_tab(options)),
+ $content : $(this._template_tab_content(options)),
+ removable : options.ondel ? true : false
}
- // add nav element
- this.$nav.append(tab.$title);
-
- // add content
- tab.$content.append($el);
- this.$content.append(tab.$content);
-
// add to list
this.list[id] = tab;
- // check list size
+ // add a new tab either before the add-new-tab tab or behind the last tab
+ if (this.options.onnew) {
+ this.$nav.find('#new-tab').before(tab.$title);
+ } else {
+ this.$nav.append(tab.$title);
+ }
+
+ // add content
+ tab.$content.append(options.$el);
+ this.$content.append(tab.$content);
+
+ // activate this tab if this is the first tab
if (_.size(this.list) == 1) {
tab.$title.addClass('active');
tab.$content.addClass('active');
+ this.first_tab = id;
+ }
+
+ // add click event to remove tab
+ if (options.ondel) {
+ var $del_icon = tab.$title.find('#delete');
+ $del_icon.tooltip({title: 'Delete this tab', placement: 'bottom'});
+ $del_icon.on('click', function(e) {
+ $del_icon.tooltip('destroy');
+ options.ondel();
+ return false;
+ });
+ }
+ },
+
+ // delete tab
+ del: function(id) {
+ // delete tab from list/dom
+ var tab = this.list[id];
+ tab.$title.remove();
+ tab.$content.remove();
+ delete tab;
+
+ // check if first tab has been deleted
+ if (this.first_tab == id) {
+ this.first_tab = null;
+ }
+
+ // show first tab
+ if (this.first_tab != null) {
+ this.show(this.first_tab);
+ }
+ },
+
+ // delete tab
+ delRemovable: function() {
+ // delete tab from list/dom
+ for (var id in this.list) {
+ var tab = this.list[id];
+ if (tab.removable) {
+ this.del(id);
+ }
}
},
// show
- show: function(){
+ show: function(id){
+ // show tab view
this.$el.fadeIn('fast');
this.visible = true;
+
+ // show selected tab
+ if (id) {
+ this.list[id].$title.find('a').tab('show');
+ }
},
// hide
@@ -82,12 +158,12 @@
this.visible = false;
},
- // enable operation
+ // hide operation
hideOperation: function(id) {
this.$nav.find('#' + id).hide();
},
- // disable operation
+ // show operation
showOperation: function(id) {
this.$nav.find('#' + id).show();
},
@@ -100,8 +176,8 @@
},
// title
- title: function(id, new_label) {
- var $el = this.$el.find('#title-' + id + ' a');
+ title: function(id, new_title) {
+ var $el = this.list[id].$title.find('#text');
if (new_title) {
$el.html(new_title);
}
@@ -117,10 +193,29 @@
},
// fill template tab
+ _template_tab_new: function(options) {
+ return '<li id="new-tab">' +
+ '<a href="javascript:void(0);">' +
+ '<i style="font-size: 0.8em; margin-right: 5px;" class="fa fa-plus-circle"/>' +
+ options.title_new +
+ '</a>' +
+ '</li>';
+ },
+
+ // fill template tab
_template_tab: function(options) {
- return '<li id="title-' + options.id + '">' +
- '<a title="" href="#tab-' + options.id + '" data-toggle="tab" data-original-title="">' + options.title + '</a>' +
- '</li>';
+ var tmpl = '<li id="title-' + options.id + '">' +
+ '<a title="" href="#tab-' + options.id + '" data-toggle="tab" data-original-title="">' +
+ '<span id="text">' + options.title + '</span>';
+
+ if (options.ondel) {
+ tmpl += '<i id="delete" style="font-size: 0.8em; margin-left: 5px; cursor: pointer;" class="fa fa-minus-circle"/>';
+ }
+
+ tmpl += '</a>' +
+ '</li>';
+
+ return tmpl;
},
// fill template tab content
diff -r fac578cca75887d811e67993a655fed20c0d8713 -r 462a28f96c2172113d1cad657e271e792493b49e static/scripts/packed/mvc/ui/ui-tabs.js
--- a/static/scripts/packed/mvc/ui/ui-tabs.js
+++ b/static/scripts/packed/mvc/ui/ui-tabs.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){var b=Backbone.View.extend({visible:false,list:{},$nav:null,$content:null,optionsDefault:{operations:null,},initialize:function(e){this.options=a.merge(e,this.optionsDefault);var c=$(this._template(this.options));this.$nav=c.find(".tab-navigation");this.$content=c.find(".tab-content");this.setElement(c);if(this.options.operations){var d=this;$.each(this.options.operations,function(f,g){g.$el.prop("id",f);d.$nav.append(g.$el)})}},add:function(c){var d=c.$el;var f=c.title;var g=c.id;var e={$title:$(this._template_tab(c)),$content:$(this._template_tab_content(c))};this.$nav.append(e.$title);e.$content.append(d);this.$content.append(e.$content);this.list[g]=e;if(_.size(this.list)==1){e.$title.addClass("active");e.$content.addClass("active")}},show:function(){this.$el.fadeIn("fast");this.visible=true},hide:function(){this.$el.fadeOut("fast");this.visible=false},hideOperation:function(c){this.$nav.find("#"+c).hide()},showOperation:function(c){this.$nav.find("#"+c).show()},setOperation:function(e,d){var c=this.$nav.find("#"+e);c.off("click");c.on("click",d)},title:function(e,c){var d=this.$el.find("#title-"+e+" a");if(new_title){d.html(new_title)}return d.html()},_template:function(c){return'<div class="tabbable tabs-left"><ul class="tab-navigation nav nav-tabs"/><div class="tab-content"/></div>'},_template_tab:function(c){return'<li id="title-'+c.id+'"><a title="" href="#tab-'+c.id+'" data-toggle="tab" data-original-title="">'+c.title+"</a></li>"},_template_tab_content:function(c){return'<div id="tab-'+c.id+'" class="tab-pane"/>'}});return{View:b}});
\ No newline at end of file
+define(["utils/utils"],function(a){var b=Backbone.View.extend({visible:false,list:{},$nav:null,$content:null,first_tab:null,optionsDefault:{title_new:"",operations:null,onnew:null},initialize:function(e){this.options=a.merge(e,this.optionsDefault);var c=$(this._template(this.options));this.$nav=c.find(".tab-navigation");this.$content=c.find(".tab-content");this.setElement(c);if(this.options.operations){var d=this;$.each(this.options.operations,function(g,h){h.$el.prop("id",g);d.$nav.append(h.$el)})}if(this.options.onnew){var f=$(this._template_tab_new(this.options));this.$nav.append(f);f.tooltip({title:"Add a new tab",placement:"bottom"});f.on("click",function(g){f.tooltip("hide");d.options.onnew()})}},add:function(d){var f=d.id;var e={$title:$(this._template_tab(d)),$content:$(this._template_tab_content(d)),removable:d.ondel?true:false};this.list[f]=e;if(this.options.onnew){this.$nav.find("#new-tab").before(e.$title)}else{this.$nav.append(e.$title)}e.$content.append(d.$el);this.$content.append(e.$content);if(_.size(this.list)==1){e.$title.addClass("active");e.$content.addClass("active");this.first_tab=f}if(d.ondel){var c=e.$title.find("#delete");c.tooltip({title:"Delete this tab",placement:"bottom"});c.on("click",function(g){c.tooltip("destroy");d.ondel();return false})}},del:function(d){var c=this.list[d];c.$title.remove();c.$content.remove();delete c;if(this.first_tab==d){this.first_tab=null}if(this.first_tab!=null){this.show(this.first_tab)}},delRemovable:function(){for(var d in this.list){var c=this.list[d];if(c.removable){this.del(d)}}},show:function(c){this.$el.fadeIn("fast");this.visible=true;if(c){this.list[c].$title.find("a").tab("show")}},hide:function(){this.$el.fadeOut("fast");this.visible=false},hideOperation:function(c){this.$nav.find("#"+c).hide()},showOperation:function(c){this.$nav.find("#"+c).show()},setOperation:function(e,d){var c=this.$nav.find("#"+e);c.off("click");c.on("click",d)},title:function(e,d){var c=this.list[e].$title.find("#text");if(d){c.html(d)}return c.html()},_template:function(c){return'<div class="tabbable tabs-left"><ul class="tab-navigation nav nav-tabs"/><div class="tab-content"/></div>'},_template_tab_new:function(c){return'<li id="new-tab"><a href="javascript:void(0);"><i style="font-size: 0.8em; margin-right: 5px;" class="fa fa-plus-circle"/>'+c.title_new+"</a></li>"},_template_tab:function(d){var c='<li id="title-'+d.id+'"><a title="" href="#tab-'+d.id+'" data-toggle="tab" data-original-title=""><span id="text">'+d.title+"</span>";if(d.ondel){c+='<i id="delete" style="font-size: 0.8em; margin-left: 5px; cursor: pointer;" class="fa fa-minus-circle"/>'}c+="</a></li>";return c},_template_tab_content:function(c){return'<div id="tab-'+c.id+'" class="tab-pane"/>'}});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
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/767d9f567b6f/
Changeset: 767d9f567b6f
User: jmchilton
Date: 2014-02-22 05:09:57
Summary: Unit tests for various data tool parameter handling.
Test optional datasets can be used in tool evaluation (in test_evaluation.py).
Add test_data_parameters.py which test many random DataToolParameter behaviors. Test various paths to DataToolParameter.to_python - including recently enhanced ability to use optional dataset with 'multiple=True' data parameters. Test filtering on datatypes, implicit conversion options (both existing conversions and new ones) both when building HTML forms and picking intial values for workflows. Test special handling of hidden datasets. Tests picking intial datasets when optional and without repeats when used in subsequent calls.
Affected #: 2 files
diff -r 2403d6f67500ec35b16ce604142d98766286b65a -r 767d9f567b6fa5f6554ec2180b4f1249587f1473 test/unit/tools/test_data_parameters.py
--- /dev/null
+++ b/test/unit/tools/test_data_parameters.py
@@ -0,0 +1,223 @@
+from unittest import TestCase
+
+from galaxy import model
+from galaxy.util import bunch
+from galaxy.tools.parameters import basic
+
+from elementtree.ElementTree import XML
+
+import tools_support
+
+
+class DataToolParameterTestCase( TestCase, tools_support.UsesApp ):
+
+ def test_to_python_none_values( self ):
+ assert None is self.param.to_python( None, self.app )
+ assert 'None' == self.param.to_python( 'None', self.app )
+ assert '' == self.param.to_python( '', self.app )
+
+ def test_to_python_hda( self ):
+ hda = self._new_hda()
+ as_python = self.param.to_python( hda.id, self.app )
+ assert hda == as_python
+
+ def test_to_python_multi_hdas( self ):
+ hda1 = self._new_hda()
+ hda2 = self._new_hda()
+ as_python = self.param.to_python( "%s,%s" % ( hda1.id, hda2.id ), self.app )
+ assert as_python == [ hda1, hda2 ]
+
+ def test_to_python_multi_none( self ):
+ self.multiple = True
+ hda = self._new_hda()
+ # Selection is Optional. may be selected with other stuff,
+ # not sure the UI should really allow this but easy enough
+ # to just filter it out.
+ assert [hda] == self.param.to_python( '%s,None' % hda.id, self.app )
+
+ def test_field_filter_on_types( self ):
+ hda1 = MockHistoryDatasetAssociation( name="hda1", id=1 )
+ hda2 = MockHistoryDatasetAssociation( name="hda2", id=2 )
+ self.stub_active_datasets( hda1, hda2 )
+ field = self.param.get_html_field( trans=self.trans )
+ assert len( field.options ) == 2
+ assert field.options[ 0 ][ 0 ] == "1: hda1"
+ assert field.options[ 1 ][ 0 ] == "2: hda2"
+
+ assert field.options[ 1 ][ 2 ] # Last one selected
+ assert not field.options[ 0 ][ 2 ] # Others not selected
+
+ hda2.datatype_matches = False
+ field = self.param.get_html_field( trans=self.trans )
+ assert len( field.options ) == 1
+ assert field.options[ 0 ][ 2 ] is True # Last one selected
+
+ def test_field_display_hidden_hdas_only_if_selected( self ):
+ hda1 = MockHistoryDatasetAssociation( name="hda1", id=1 )
+ hda2 = MockHistoryDatasetAssociation( name="hda2", id=2 )
+ self.stub_active_datasets( hda1, hda2 )
+ hda1.visible = False
+ hda2.visible = False
+ field = self.param.get_html_field( trans=self.trans, value=hda2 )
+ assert len( field.options ) == 1 # hda1 not an option, not visible or selected
+ assert field.options[ 0 ][ 0 ] == "2: (hidden) hda2"
+
+ def test_field_implicit_conversion_new( self ):
+ hda1 = MockHistoryDatasetAssociation( name="hda1", id=1 )
+ hda1.datatype_matches = False
+ hda1.conversion_destination = ( "tabular", None )
+ self.stub_active_datasets( hda1 )
+ field = self.param.get_html_field( trans=self.trans )
+ assert len( field.options ) == 1
+ assert field.options[ 0 ][ 0 ] == "1: (as tabular) hda1"
+ assert field.options[ 0 ][ 1 ] == 1
+
+ def test_field_implicit_conversion_existing( self ):
+ hda1 = MockHistoryDatasetAssociation( name="hda1", id=1 )
+ hda1.datatype_matches = False
+ hda1.conversion_destination = ( "tabular", MockHistoryDatasetAssociation( name="hda1converted", id=2 ) )
+ self.stub_active_datasets( hda1 )
+ field = self.param.get_html_field( trans=self.trans )
+ assert len( field.options ) == 1
+ assert field.options[ 0 ][ 0 ] == "1: (as tabular) hda1"
+ # This is difference with previous test, value is existing
+ # hda id not new one.
+ assert field.options[ 0 ][ 1 ] == 2
+
+ def test_field_multiple( self ):
+ self.multiple = True
+ field = self.param.get_html_field( trans=self.trans )
+ assert field.multiple
+
+ def test_field_empty_selection( self ):
+ field = self.param.get_html_field( trans=self.trans )
+ assert len( field.options ) == 0
+
+ def test_field_empty_selection_optional( self ):
+ self.optional = True
+ field = self.param.get_html_field( trans=self.trans )
+ assert len( field.options ) == 1
+ option = field.options[ 0 ]
+ assert option[ 0 ] == "Selection is Optional"
+ assert option[ 1 ] == "None"
+ assert option[ 2 ] is True
+
+ def test_get_initial_value_prevents_repeats( self ):
+ hda1 = MockHistoryDatasetAssociation( name="hda1", id=1 )
+ hda2 = MockHistoryDatasetAssociation( name="hda2", id=2 )
+ self.stub_active_datasets( hda1, hda2 )
+ already_used = []
+ assert hda2 == self.param.get_initial_value_from_history_prevent_repeats( self.trans, {}, already_used )
+ assert hda1 == self.param.get_initial_value_from_history_prevent_repeats( self.trans, {}, already_used )
+
+ def test_get_initial_value_is_empty_string_if_no_match( self ):
+ hda1 = MockHistoryDatasetAssociation( name="hda1", id=1 )
+ hda1.visible = False
+ hda2 = MockHistoryDatasetAssociation( name="hda2", id=2 )
+ hda2.visible = False
+ self.stub_active_datasets( hda1, hda2 )
+ assert '' == self.param.get_initial_value( self.trans, {} )
+
+ def test_get_initial_none_when_optional( self ):
+ self.optional = True
+ hda1 = MockHistoryDatasetAssociation( name="hda1", id=1 )
+ hda2 = MockHistoryDatasetAssociation( name="hda2", id=2 )
+ self.stub_active_datasets( hda1, hda2 )
+ assert self.param.get_initial_value( self.trans, {} ) is None
+
+ def test_get_initial_with_previously_converted_data( self ):
+ hda1 = MockHistoryDatasetAssociation( name="hda1", id=1 )
+ hda1.datatype_matches = False
+ converted = MockHistoryDatasetAssociation( name="hda1converted", id=2 )
+ hda1.conversion_destination = ( "tabular", converted )
+ self.stub_active_datasets( hda1 )
+ assert converted == self.param.get_initial_value( self.trans, {} )
+
+ def test_get_initial_with_to_be_converted_data( self ):
+ hda1 = MockHistoryDatasetAssociation( name="hda1", id=1 )
+ hda1.datatype_matches = False
+ hda1.conversion_destination = ( "tabular", None )
+ self.stub_active_datasets( hda1 )
+ assert hda1 == self.param.get_initial_value( self.trans, {} )
+
+ def _new_hda( self ):
+ hda = model.HistoryDatasetAssociation()
+ hda.visible = True
+ hda.dataset = model.Dataset()
+ self.app.model.context.add( hda )
+ self.app.model.context.flush( )
+ return hda
+
+ def setUp( self ):
+ self.setup_app( mock_model=False )
+ self.mock_tool = bunch.Bunch(
+ app=self.app,
+ tool_type="default",
+ )
+ self.test_history = model.History()
+ self.app.model.context.add( self.test_history )
+ self.app.model.context.flush()
+ self.trans = bunch.Bunch(
+ app=self.app,
+ get_history=lambda: self.test_history,
+ get_current_user_roles=lambda: [],
+ workflow_building_mode=False,
+ webapp=bunch.Bunch( name="galaxy" ),
+ )
+ self.multiple = False
+ self.optional = False
+ self._param = None
+
+ def stub_active_datasets( self, *hdas ):
+ self.test_history._active_datasets_children_and_roles = hdas
+
+ @property
+ def param( self ):
+ if not self._param:
+ multi_text = ""
+ if self.multiple:
+ multi_text = 'multiple="True"'
+ optional_text = ""
+ if self.optional:
+ optional_text = 'optional="True"'
+ template_xml = '''<param name="data2" type="data" ext="txt" %s %s></param>'''
+ self.param_xml = XML( template_xml % ( multi_text, optional_text ) )
+ self._param = basic.DataToolParameter( self.mock_tool, self.param_xml )
+
+ return self._param
+
+
+class MockHistoryDatasetAssociation( object ):
+ """ Fake HistoryDatasetAssociation stubbed out for testing matching and
+ stuff like that.
+ """
+
+ def __init__( self, test_dataset=None, name="Test Dataset", id=1 ):
+ if not test_dataset:
+ test_dataset = model.Dataset()
+ self.states = model.HistoryDatasetAssociation.states
+ self.deleted = False
+ self.dataset = test_dataset
+ self.visible = True
+ self.datatype_matches = True
+ self.conversion_destination = ( None, None )
+ self.datatype = bunch.Bunch(
+ matches_any=lambda formats: self.datatype_matches,
+ )
+ self.dbkey = "hg19"
+ self.implicitly_converted_parent_datasets = False
+
+ self.name = name
+ self.hid = id
+ self.id = id
+ self.children = []
+
+ @property
+ def state( self ):
+ return self.dataset.state
+
+ def get_dbkey( self ):
+ return self.dbkey
+
+ def find_conversion_destination( self, formats ):
+ return self.conversion_destination
diff -r 2403d6f67500ec35b16ce604142d98766286b65a -r 767d9f567b6fa5f6554ec2180b4f1249587f1473 test/unit/tools/test_evaluation.py
--- a/test/unit/tools/test_evaluation.py
+++ b/test/unit/tools/test_evaluation.py
@@ -20,6 +20,7 @@
from galaxy.tools.parameters.grouping import ConditionalWhen
from galaxy.tools.parameters.basic import IntegerToolParameter
from galaxy.tools.parameters.basic import SelectToolParameter
+from galaxy.tools.parameters.basic import DataToolParameter
from elementtree.ElementTree import XML # Import after model, to ensure elementtree
@@ -78,6 +79,18 @@
command_line, extra_filenames = self.evaluator.build( )
self.assertEquals( command_line, "prog1 --thresh=4 --test_param=true" )
+ def test_evaluation_of_optional_datasets( self ):
+ # Make sure optional dataset don't cause evaluation to break and
+ # evaluate in cheetah templates as 'None'.
+ select_xml = XML('''<param name="input1" type="data" optional="true"></param>''')
+ parameter = DataToolParameter( self.tool, select_xml )
+ self.job.parameters = [ JobParameter( name="input1", value=u'null' ) ]
+ self.tool.set_params( { "input1": parameter } )
+ self.tool._command_line = "prog1 --opt_input='${input1}'"
+ self._set_compute_environment()
+ command_line, extra_filenames = self.evaluator.build( )
+ self.assertEquals( command_line, "prog1 --opt_input='None'" )
+
def test_evaluation_with_path_rewrites_wrapped( self ):
self.tool.check_values = True
self.__test_evaluation_with_path_rewrites()
https://bitbucket.org/galaxy/galaxy-central/commits/9051ceb43593/
Changeset: 9051ceb43593
User: jmchilton
Date: 2014-02-22 05:09:57
Summary: Rearrange unit tests.
Move tests that were in tests/unit but could logically be placed into tests/unit/tools or tests/unit/jobs into these directory.
Affected #: 8 files
diff -r 767d9f567b6fa5f6554ec2180b4f1249587f1473 -r 9051ceb435937348e6417fb96eb9611474496828 test/unit/jobs/test_command_factory.py
--- /dev/null
+++ b/test/unit/jobs/test_command_factory.py
@@ -0,0 +1,156 @@
+from os import getcwd
+from unittest import TestCase
+
+from galaxy.jobs.command_factory import build_command
+from galaxy.util.bunch import Bunch
+
+MOCK_COMMAND_LINE = "/opt/galaxy/tools/bowtie /mnt/galaxyData/files/000/input000.dat"
+TEST_METADATA_LINE = "set_metadata_and_stuff.sh"
+TEST_FILES_PATH = "file_path"
+
+
+class TestCommandFactory(TestCase):
+
+ def setUp(self):
+ self.job_wrapper = MockJobWrapper()
+ self.workdir_outputs = []
+
+ def workdir_outputs(job_wrapper, **kwds):
+ assert job_wrapper == self.job_wrapper
+ return self.workdir_outputs
+
+ self.runner = Bunch(app=Bunch(model=Bunch(Dataset=Bunch(file_path=TEST_FILES_PATH))), get_work_dir_outputs=workdir_outputs)
+ self.include_metadata = False
+ self.include_work_dir_outputs = True
+
+ def test_simplest_command(self):
+ self.include_work_dir_outputs = False
+ self.__assert_command_is( MOCK_COMMAND_LINE )
+
+ def test_shell_commands(self):
+ self.include_work_dir_outputs = False
+ dep_commands = [". /opt/galaxy/tools/bowtie/default/env.sh"]
+ self.job_wrapper.dependency_shell_commands = dep_commands
+ self.__assert_command_is( "%s; %s" % (dep_commands[0], MOCK_COMMAND_LINE) )
+
+ def test_remote_dependency_resolution(self):
+ self.include_work_dir_outputs = False
+ dep_commands = [". /opt/galaxy/tools/bowtie/default/env.sh"]
+ self.job_wrapper.dependency_shell_commands = dep_commands
+ self.__assert_command_is(MOCK_COMMAND_LINE, remote_command_params=dict(dependency_resolution="remote"))
+
+ def test_explicit_local_dependency_resolution(self):
+ self.include_work_dir_outputs = False
+ dep_commands = [". /opt/galaxy/tools/bowtie/default/env.sh"]
+ self.job_wrapper.dependency_shell_commands = dep_commands
+ self.__assert_command_is("%s; %s" % (dep_commands[0], MOCK_COMMAND_LINE),
+ remote_command_params=dict(dependency_resolution="local"))
+
+ def test_task_prepare_inputs(self):
+ self.include_work_dir_outputs = False
+ self.job_wrapper.prepare_input_files_cmds = ["/opt/split1", "/opt/split2"]
+ self.__assert_command_is( "/opt/split1; /opt/split2; %s" % MOCK_COMMAND_LINE )
+
+ def test_workdir_outputs(self):
+ self.include_work_dir_outputs = True
+ self.workdir_outputs = [("foo", "bar")]
+ self.__assert_command_is( '%s; return_code=$?; if [ -f foo ] ; then cp foo bar ; fi; sh -c "exit $return_code"' % MOCK_COMMAND_LINE )
+
+ def test_set_metadata_skipped_if_unneeded(self):
+ self.include_metadata = True
+ self.include_work_dir_outputs = False
+ self.__assert_command_is( MOCK_COMMAND_LINE )
+
+ def test_set_metadata(self):
+ self._test_set_metadata()
+
+ def test_strips_trailing_semicolons(self):
+ self.job_wrapper.command_line = "%s;" % MOCK_COMMAND_LINE
+ self._test_set_metadata()
+
+ def _test_set_metadata(self):
+ self.include_metadata = True
+ self.include_work_dir_outputs = False
+ self.job_wrapper.metadata_line = TEST_METADATA_LINE
+ expected_command = '%s; return_code=$?; cd %s; %s; sh -c "exit $return_code"' % (MOCK_COMMAND_LINE, getcwd(), TEST_METADATA_LINE)
+ self.__assert_command_is( expected_command )
+
+ def test_empty_metadata(self):
+ """
+ As produced by TaskWrapper.
+ """
+ self.include_metadata = True
+ self.include_work_dir_outputs = False
+ self.job_wrapper.metadata_line = ' '
+ # Empty metadata command do not touch command line.
+ expected_command = '%s' % (MOCK_COMMAND_LINE)
+ self.__assert_command_is( expected_command )
+
+ def test_metadata_kwd_defaults(self):
+ configured_kwds = self.__set_metadata_with_kwds()
+ assert configured_kwds['exec_dir'] == getcwd()
+ assert configured_kwds['tmp_dir'] == self.job_wrapper.working_directory
+ assert configured_kwds['dataset_files_path'] == TEST_FILES_PATH
+ assert configured_kwds['output_fnames'] == ['output1']
+
+ def test_metadata_kwds_overrride(self):
+ configured_kwds = self.__set_metadata_with_kwds(
+ exec_dir="/path/to/remote/galaxy",
+ tmp_dir="/path/to/remote/staging/directory/job1",
+ dataset_files_path="/path/to/remote/datasets/",
+ output_fnames=['/path/to/remote_output1'],
+ )
+ assert configured_kwds['exec_dir'] == "/path/to/remote/galaxy"
+ assert configured_kwds['tmp_dir'] == "/path/to/remote/staging/directory/job1"
+ assert configured_kwds['dataset_files_path'] == "/path/to/remote/datasets/"
+ assert configured_kwds['output_fnames'] == ['/path/to/remote_output1']
+
+ def __set_metadata_with_kwds(self, **kwds):
+ self.include_metadata = True
+ self.include_work_dir_outputs = False
+ self.job_wrapper.metadata_line = TEST_METADATA_LINE
+ if kwds:
+ self.__command(remote_command_params=dict(metadata_kwds=kwds))
+ else:
+ self.__command()
+ return self.job_wrapper.configured_external_metadata_kwds
+
+ def __assert_command_is(self, expected_command, **command_kwds):
+ command = self.__command(**command_kwds)
+ self.assertEqual(command, expected_command)
+
+ def __command(self, **extra_kwds):
+ kwds = dict(
+ runner=self.runner,
+ job_wrapper=self.job_wrapper,
+ include_metadata=self.include_metadata,
+ include_work_dir_outputs=self.include_work_dir_outputs,
+ **extra_kwds
+ )
+ return build_command(**kwds)
+
+
+class MockJobWrapper(object):
+
+ def __init__(self):
+ self.write_version_cmd = None
+ self.command_line = MOCK_COMMAND_LINE
+ self.dependency_shell_commands = []
+ self.metadata_line = None
+ self.configured_external_metadata_kwds = None
+ self.working_directory = "job1"
+ self.prepare_input_files_cmds = None
+
+ def get_command_line(self):
+ return self.command_line
+
+ @property
+ def requires_setting_metadata(self):
+ return self.metadata_line is not None
+
+ def setup_external_metadata(self, *args, **kwds):
+ self.configured_external_metadata_kwds = kwds
+ return self.metadata_line
+
+ def get_output_fnames(self):
+ return ["output1"]
diff -r 767d9f567b6fa5f6554ec2180b4f1249587f1473 -r 9051ceb435937348e6417fb96eb9611474496828 test/unit/jobs/test_job_output_checker.py
--- /dev/null
+++ b/test/unit/jobs/test_job_output_checker.py
@@ -0,0 +1,62 @@
+from unittest import TestCase
+from galaxy.util.bunch import Bunch
+from galaxy.jobs.output_checker import check_output
+from galaxy.jobs.error_level import StdioErrorLevel
+
+
+class OutputCheckerTestCase( TestCase ):
+
+ def setUp( self ):
+ self.tool = Bunch(
+ stdio_regexes=[],
+ stdio_exit_codes=[],
+ )
+ self.job = Bunch(
+ stdout=None,
+ stderr=None,
+ get_id_tag=lambda: "test_id",
+ )
+ self.stdout = ''
+ self.stderr = ''
+ self.tool_exit_code = None
+
+ def test_default_no_stderr_success( self ):
+ self.__assertSuccessful()
+
+ def test_default_stderr_failure( self ):
+ self.stderr = 'foo'
+ self.__assertNotSuccessful()
+
+ def test_exit_code_error( self ):
+ mock_exit_code = Bunch( range_start=1, range_end=1, error_level=StdioErrorLevel.FATAL, desc=None )
+ self.tool.stdio_exit_codes.append( mock_exit_code )
+ self.tool_exit_code = 1
+ self.__assertNotSuccessful()
+
+ def test_exit_code_success( self ):
+ mock_exit_code = Bunch( range_start=1, range_end=1, error_level=StdioErrorLevel.FATAL, desc=None )
+ self.tool.stdio_exit_codes.append( mock_exit_code )
+ self.tool_exit_code = 0
+ self.__assertSuccessful()
+
+ def test_problematic_strings( self ):
+ problematic_str = '\x80abc'
+ regex_rule = Bunch( match=r'.abc', stdout_match=False, stderr_match=True, error_level=StdioErrorLevel.FATAL, desc=None )
+ self.tool.stdio_regexes = [ regex_rule ]
+ self.stderr = problematic_str
+ self.__assertNotSuccessful()
+
+ problematic_str = '\x80abc'
+ regex_rule = Bunch( match=r'.abcd', stdout_match=False, stderr_match=True, error_level=StdioErrorLevel.FATAL, desc=None )
+ self.tool.stdio_regexes = [ regex_rule ]
+ self.stderr = problematic_str
+ self.__assertSuccessful()
+
+ def __assertSuccessful( self ):
+ self.assertTrue( self.__check_output() )
+
+ def __assertNotSuccessful( self ):
+ self.assertFalse( self.__check_output() )
+
+ def __check_output( self ):
+ return check_output( self.tool, self.stdout, self.stderr, self.tool_exit_code, self.job )
diff -r 767d9f567b6fa5f6554ec2180b4f1249587f1473 -r 9051ceb435937348e6417fb96eb9611474496828 test/unit/test_command_factory.py
--- a/test/unit/test_command_factory.py
+++ /dev/null
@@ -1,156 +0,0 @@
-from os import getcwd
-from unittest import TestCase
-
-from galaxy.jobs.command_factory import build_command
-from galaxy.util.bunch import Bunch
-
-MOCK_COMMAND_LINE = "/opt/galaxy/tools/bowtie /mnt/galaxyData/files/000/input000.dat"
-TEST_METADATA_LINE = "set_metadata_and_stuff.sh"
-TEST_FILES_PATH = "file_path"
-
-
-class TestCommandFactory(TestCase):
-
- def setUp(self):
- self.job_wrapper = MockJobWrapper()
- self.workdir_outputs = []
-
- def workdir_outputs(job_wrapper, **kwds):
- assert job_wrapper == self.job_wrapper
- return self.workdir_outputs
-
- self.runner = Bunch(app=Bunch(model=Bunch(Dataset=Bunch(file_path=TEST_FILES_PATH))), get_work_dir_outputs=workdir_outputs)
- self.include_metadata = False
- self.include_work_dir_outputs = True
-
- def test_simplest_command(self):
- self.include_work_dir_outputs = False
- self.__assert_command_is( MOCK_COMMAND_LINE )
-
- def test_shell_commands(self):
- self.include_work_dir_outputs = False
- dep_commands = [". /opt/galaxy/tools/bowtie/default/env.sh"]
- self.job_wrapper.dependency_shell_commands = dep_commands
- self.__assert_command_is( "%s; %s" % (dep_commands[0], MOCK_COMMAND_LINE) )
-
- def test_remote_dependency_resolution(self):
- self.include_work_dir_outputs = False
- dep_commands = [". /opt/galaxy/tools/bowtie/default/env.sh"]
- self.job_wrapper.dependency_shell_commands = dep_commands
- self.__assert_command_is(MOCK_COMMAND_LINE, remote_command_params=dict(dependency_resolution="remote"))
-
- def test_explicit_local_dependency_resolution(self):
- self.include_work_dir_outputs = False
- dep_commands = [". /opt/galaxy/tools/bowtie/default/env.sh"]
- self.job_wrapper.dependency_shell_commands = dep_commands
- self.__assert_command_is("%s; %s" % (dep_commands[0], MOCK_COMMAND_LINE),
- remote_command_params=dict(dependency_resolution="local"))
-
- def test_task_prepare_inputs(self):
- self.include_work_dir_outputs = False
- self.job_wrapper.prepare_input_files_cmds = ["/opt/split1", "/opt/split2"]
- self.__assert_command_is( "/opt/split1; /opt/split2; %s" % MOCK_COMMAND_LINE )
-
- def test_workdir_outputs(self):
- self.include_work_dir_outputs = True
- self.workdir_outputs = [("foo", "bar")]
- self.__assert_command_is( '%s; return_code=$?; if [ -f foo ] ; then cp foo bar ; fi; sh -c "exit $return_code"' % MOCK_COMMAND_LINE )
-
- def test_set_metadata_skipped_if_unneeded(self):
- self.include_metadata = True
- self.include_work_dir_outputs = False
- self.__assert_command_is( MOCK_COMMAND_LINE )
-
- def test_set_metadata(self):
- self._test_set_metadata()
-
- def test_strips_trailing_semicolons(self):
- self.job_wrapper.command_line = "%s;" % MOCK_COMMAND_LINE
- self._test_set_metadata()
-
- def _test_set_metadata(self):
- self.include_metadata = True
- self.include_work_dir_outputs = False
- self.job_wrapper.metadata_line = TEST_METADATA_LINE
- expected_command = '%s; return_code=$?; cd %s; %s; sh -c "exit $return_code"' % (MOCK_COMMAND_LINE, getcwd(), TEST_METADATA_LINE)
- self.__assert_command_is( expected_command )
-
- def test_empty_metadata(self):
- """
- As produced by TaskWrapper.
- """
- self.include_metadata = True
- self.include_work_dir_outputs = False
- self.job_wrapper.metadata_line = ' '
- # Empty metadata command do not touch command line.
- expected_command = '%s' % (MOCK_COMMAND_LINE)
- self.__assert_command_is( expected_command )
-
- def test_metadata_kwd_defaults(self):
- configured_kwds = self.__set_metadata_with_kwds()
- assert configured_kwds['exec_dir'] == getcwd()
- assert configured_kwds['tmp_dir'] == self.job_wrapper.working_directory
- assert configured_kwds['dataset_files_path'] == TEST_FILES_PATH
- assert configured_kwds['output_fnames'] == ['output1']
-
- def test_metadata_kwds_overrride(self):
- configured_kwds = self.__set_metadata_with_kwds(
- exec_dir="/path/to/remote/galaxy",
- tmp_dir="/path/to/remote/staging/directory/job1",
- dataset_files_path="/path/to/remote/datasets/",
- output_fnames=['/path/to/remote_output1'],
- )
- assert configured_kwds['exec_dir'] == "/path/to/remote/galaxy"
- assert configured_kwds['tmp_dir'] == "/path/to/remote/staging/directory/job1"
- assert configured_kwds['dataset_files_path'] == "/path/to/remote/datasets/"
- assert configured_kwds['output_fnames'] == ['/path/to/remote_output1']
-
- def __set_metadata_with_kwds(self, **kwds):
- self.include_metadata = True
- self.include_work_dir_outputs = False
- self.job_wrapper.metadata_line = TEST_METADATA_LINE
- if kwds:
- self.__command(remote_command_params=dict(metadata_kwds=kwds))
- else:
- self.__command()
- return self.job_wrapper.configured_external_metadata_kwds
-
- def __assert_command_is(self, expected_command, **command_kwds):
- command = self.__command(**command_kwds)
- self.assertEqual(command, expected_command)
-
- def __command(self, **extra_kwds):
- kwds = dict(
- runner=self.runner,
- job_wrapper=self.job_wrapper,
- include_metadata=self.include_metadata,
- include_work_dir_outputs=self.include_work_dir_outputs,
- **extra_kwds
- )
- return build_command(**kwds)
-
-
-class MockJobWrapper(object):
-
- def __init__(self):
- self.write_version_cmd = None
- self.command_line = MOCK_COMMAND_LINE
- self.dependency_shell_commands = []
- self.metadata_line = None
- self.configured_external_metadata_kwds = None
- self.working_directory = "job1"
- self.prepare_input_files_cmds = None
-
- def get_command_line(self):
- return self.command_line
-
- @property
- def requires_setting_metadata(self):
- return self.metadata_line is not None
-
- def setup_external_metadata(self, *args, **kwds):
- self.configured_external_metadata_kwds = kwds
- return self.metadata_line
-
- def get_output_fnames(self):
- return ["output1"]
diff -r 767d9f567b6fa5f6554ec2180b4f1249587f1473 -r 9051ceb435937348e6417fb96eb9611474496828 test/unit/test_job_output_checker.py
--- a/test/unit/test_job_output_checker.py
+++ /dev/null
@@ -1,62 +0,0 @@
-from unittest import TestCase
-from galaxy.util.bunch import Bunch
-from galaxy.jobs.output_checker import check_output
-from galaxy.jobs.error_level import StdioErrorLevel
-
-
-class OutputCheckerTestCase( TestCase ):
-
- def setUp( self ):
- self.tool = Bunch(
- stdio_regexes=[],
- stdio_exit_codes=[],
- )
- self.job = Bunch(
- stdout=None,
- stderr=None,
- get_id_tag=lambda: "test_id",
- )
- self.stdout = ''
- self.stderr = ''
- self.tool_exit_code = None
-
- def test_default_no_stderr_success( self ):
- self.__assertSuccessful()
-
- def test_default_stderr_failure( self ):
- self.stderr = 'foo'
- self.__assertNotSuccessful()
-
- def test_exit_code_error( self ):
- mock_exit_code = Bunch( range_start=1, range_end=1, error_level=StdioErrorLevel.FATAL, desc=None )
- self.tool.stdio_exit_codes.append( mock_exit_code )
- self.tool_exit_code = 1
- self.__assertNotSuccessful()
-
- def test_exit_code_success( self ):
- mock_exit_code = Bunch( range_start=1, range_end=1, error_level=StdioErrorLevel.FATAL, desc=None )
- self.tool.stdio_exit_codes.append( mock_exit_code )
- self.tool_exit_code = 0
- self.__assertSuccessful()
-
- def test_problematic_strings( self ):
- problematic_str = '\x80abc'
- regex_rule = Bunch( match=r'.abc', stdout_match=False, stderr_match=True, error_level=StdioErrorLevel.FATAL, desc=None )
- self.tool.stdio_regexes = [ regex_rule ]
- self.stderr = problematic_str
- self.__assertNotSuccessful()
-
- problematic_str = '\x80abc'
- regex_rule = Bunch( match=r'.abcd', stdout_match=False, stderr_match=True, error_level=StdioErrorLevel.FATAL, desc=None )
- self.tool.stdio_regexes = [ regex_rule ]
- self.stderr = problematic_str
- self.__assertSuccessful()
-
- def __assertSuccessful( self ):
- self.assertTrue( self.__check_output() )
-
- def __assertNotSuccessful( self ):
- self.assertFalse( self.__check_output() )
-
- def __check_output( self ):
- return check_output( self.tool, self.stdout, self.stderr, self.tool_exit_code, self.job )
diff -r 767d9f567b6fa5f6554ec2180b4f1249587f1473 -r 9051ceb435937348e6417fb96eb9611474496828 test/unit/test_tool_deps.py
--- a/test/unit/test_tool_deps.py
+++ /dev/null
@@ -1,378 +0,0 @@
-import tempfile
-import os.path
-from stat import S_IXUSR
-from os import makedirs, stat, symlink, chmod, environ
-from shutil import rmtree
-from galaxy.tools.deps import DependencyManager, INDETERMINATE_DEPENDENCY
-from galaxy.tools.deps.resolvers.galaxy_packages import GalaxyPackageDependency
-from galaxy.tools.deps.resolvers.modules import ModuleDependencyResolver, ModuleDependency
-from galaxy.util.bunch import Bunch
-from contextlib import contextmanager
-from subprocess import Popen, PIPE
-
-
-def test_tool_dependencies():
- # Setup directories
-
- with __test_base_path() as base_path:
- for name, version, sub in [ ( "dep1", "1.0", "env.sh" ), ( "dep1", "2.0", "bin" ), ( "dep2", "1.0", None ) ]:
- if sub == "bin":
- p = os.path.join( base_path, name, version, "bin" )
- else:
- p = os.path.join( base_path, name, version )
- try:
- makedirs( p )
- except:
- pass
- if sub == "env.sh":
- __touch( os.path.join( p, "env.sh" ) )
-
- dm = DependencyManager( default_base_path=base_path )
- dependency = dm.find_dep( "dep1", "1.0" )
- assert dependency.script == os.path.join( base_path, 'dep1', '1.0', 'env.sh' )
- assert dependency.path == os.path.join( base_path, 'dep1', '1.0' )
- assert dependency.version == "1.0"
- dependency = dm.find_dep( "dep1", "2.0" )
- assert dependency.script == None
- assert dependency.path == os.path.join( base_path, 'dep1', '2.0' )
- assert dependency.version == "2.0"
-
- ## Test default versions
- symlink( os.path.join( base_path, 'dep1', '2.0'), os.path.join( base_path, 'dep1', 'default' ) )
- dependency = dm.find_dep( "dep1", None )
- assert dependency.version == "2.0"
-
- ## Test default resolve will be fall back on default package dependency
- ## when using the default resolver.
- dependency = dm.find_dep( "dep1", "2.1" )
- assert dependency.version == "2.0" # 2.0 is defined as default_version
-
-
-TEST_REPO_USER = "devteam"
-TEST_REPO_NAME = "bwa"
-TEST_REPO_CHANGESET = "12abcd41223da"
-TEST_VERSION = "0.5.9"
-
-
-def test_toolshed_set_enviornment_requiremetns():
- with __test_base_path() as base_path:
- test_repo = __build_test_repo('set_environment')
- dm = DependencyManager( default_base_path=base_path )
- env_settings_dir = os.path.join(base_path, "environment_settings", TEST_REPO_NAME, TEST_REPO_USER, TEST_REPO_NAME, TEST_REPO_CHANGESET)
- os.makedirs(env_settings_dir)
- dependency = dm.find_dep( TEST_REPO_NAME, version=None, type='set_environment', installed_tool_dependencies=[test_repo] )
- assert dependency.version == None
- assert dependency.script == os.path.join(env_settings_dir, "env.sh")
-
-
-def test_toolshed_package_requirements():
- with __test_base_path() as base_path:
- test_repo = __build_test_repo('package', version=TEST_VERSION)
- dm = DependencyManager( default_base_path=base_path )
- package_dir = __build_ts_test_package(base_path)
- dependency = dm.find_dep( TEST_REPO_NAME, version=TEST_VERSION, type='package', installed_tool_dependencies=[test_repo] )
- assert dependency.version == TEST_VERSION
- assert dependency.script == os.path.join(package_dir, "env.sh")
-
-
-def test_toolshed_tools_fallback_on_manual_dependencies():
- with __test_base_path() as base_path:
- dm = DependencyManager( default_base_path=base_path )
- test_repo = __build_test_repo('package', version=TEST_VERSION)
- env_path = __setup_galaxy_package_dep(base_path, "dep1", "1.0")
- dependency = dm.find_dep( "dep1", version="1.0", type='package', installed_tool_dependencies=[test_repo] )
- assert dependency.version == "1.0"
- assert dependency.script == env_path
-
-
-def test_toolshed_greater_precendence():
- with __test_base_path() as base_path:
- dm = DependencyManager( default_base_path=base_path )
- test_repo = __build_test_repo('package', version=TEST_VERSION)
- ts_package_dir = __build_ts_test_package(base_path)
- gx_env_path = __setup_galaxy_package_dep(base_path, TEST_REPO_NAME, TEST_VERSION)
- ts_env_path = os.path.join(ts_package_dir, "env.sh")
- dependency = dm.find_dep( TEST_REPO_NAME, version=TEST_VERSION, type='package', installed_tool_dependencies=[test_repo] )
- assert dependency.script != gx_env_path # Not the galaxy path, it should be the tool shed path used.
- assert dependency.script == ts_env_path
-
-
-def __build_ts_test_package(base_path, script_contents=''):
- package_dir = os.path.join(base_path, TEST_REPO_NAME, TEST_VERSION, TEST_REPO_USER, TEST_REPO_NAME, TEST_REPO_CHANGESET)
- __touch(os.path.join(package_dir, 'env.sh'), script_contents)
- return package_dir
-
-
-def test_module_dependency_resolver():
- with __test_base_path() as temp_directory:
- module_script = os.path.join(temp_directory, "modulecmd")
- __write_script(module_script, '''#!/bin/sh
-cat %s/example_output 1>&2;
-''' % temp_directory)
- with open(os.path.join(temp_directory, "example_output"), "w") as f:
- # Subset of module avail from MSI cluster.
- f.write('''
--------------------------- /soft/modules/modulefiles ---------------------------
-JAGS/3.2.0-gcc45
-JAGS/3.3.0-gcc4.7.2
-ProbABEL/0.1-3
-ProbABEL/0.1-9e
-R/2.12.2
-R/2.13.1
-R/2.14.1
-R/2.15.0
-R/2.15.1
-R/3.0.1(default)
-abokia-blast/2.0.2-130524/ompi_intel
-abokia-blast/2.0.2-130630/ompi_intel
-
---------------------------- /soft/intel/modulefiles ----------------------------
-advisor/2013/update1 intel/11.1.075 mkl/10.2.1.017
-advisor/2013/update2 intel/11.1.080 mkl/10.2.5.035
-advisor/2013/update3 intel/12.0 mkl/10.2.7.041
-''')
- resolver = ModuleDependencyResolver(None, modulecmd=module_script)
- module = resolver.resolve( name="R", version=None, type="package" )
- assert module.module_name == "R"
- assert module.module_version == None
-
- module = resolver.resolve( name="R", version="3.0.1", type="package" )
- assert module.module_name == "R"
- assert module.module_version == "3.0.1"
-
- module = resolver.resolve( name="R", version="3.0.4", type="package" )
- assert module == INDETERMINATE_DEPENDENCY
-
-
-def test_module_dependency():
- with __test_base_path() as temp_directory:
- ## Create mock modulecmd script that just exports a variable
- ## the way modulecmd sh load would, but also validate correct
- ## module name and version are coming through.
- mock_modulecmd = os.path.join(temp_directory, 'modulecmd')
- __write_script(mock_modulecmd, '''#!/bin/sh
-if [ $3 != "foomodule/1.0" ];
-then
- exit 1
-fi
-echo 'FOO="bar"'
-''')
- resolver = Bunch(modulecmd=mock_modulecmd)
- dependency = ModuleDependency(resolver, "foomodule", "1.0")
- __assert_foo_exported( dependency.shell_commands( Bunch( type="package" ) ) )
-
-
-def __write_script(path, contents):
- with open(path, 'w') as f:
- f.write(contents)
- st = stat(path)
- chmod(path, st.st_mode | S_IXUSR)
-
-
-def test_galaxy_dependency_object_script():
- with __test_base_path() as base_path:
- ## Create env.sh file that just exports variable FOO and verify it
- ## shell_commands export it correctly.
- env_path = __setup_galaxy_package_dep(base_path, TEST_REPO_NAME, TEST_VERSION, "export FOO=\"bar\"")
- dependency = GalaxyPackageDependency(env_path, os.path.dirname(env_path), TEST_VERSION)
- __assert_foo_exported( dependency.shell_commands( Bunch( type="package" ) ) )
-
-
-def test_shell_commands_built():
- ## Test that dependency manager builds valid shell commands for a list of
- ## requirements.
- with __test_base_path() as base_path:
- dm = DependencyManager( default_base_path=base_path )
- __setup_galaxy_package_dep( base_path, TEST_REPO_NAME, TEST_VERSION, contents="export FOO=\"bar\"" )
- mock_requirements = [ Bunch(type="package", version=TEST_VERSION, name=TEST_REPO_NAME ) ]
- commands = dm.dependency_shell_commands( mock_requirements )
- __assert_foo_exported( commands )
-
-
-def __assert_foo_exported( commands ):
- command = ["bash", "-c", "%s; echo \"$FOO\"" % "".join(commands)]
- process = Popen(command, stdout=PIPE)
- output = process.communicate()[0].strip()
- assert output == 'bar', "Command %s exports FOO as %s, not bar" % (command, output)
-
-
-def __setup_galaxy_package_dep(base_path, name, version, contents=""):
- dep_directory = os.path.join( base_path, name, version )
- env_path = os.path.join( dep_directory, "env.sh" )
- __touch( env_path, contents )
- return env_path
-
-
-def __touch( fname, data=None ):
- dirname = os.path.dirname( fname )
- if not os.path.exists( dirname ):
- makedirs( dirname )
- f = open( fname, 'w' )
- try:
- if data:
- f.write( data )
- finally:
- f.close()
-
-
-def __build_test_repo(type, version=None):
- return Bunch(
- owner=TEST_REPO_USER,
- name=TEST_REPO_NAME,
- type=type,
- version=version,
- tool_shed_repository=Bunch(
- owner=TEST_REPO_USER,
- name=TEST_REPO_NAME,
- installed_changeset_revision=TEST_REPO_CHANGESET
- )
- )
-
-
-@contextmanager
-def __test_base_path():
- base_path = tempfile.mkdtemp()
- try:
- yield base_path
- finally:
- rmtree(base_path)
-
-
-def test_parse():
- with __parse_resolvers('''<dependency_resolvers>
- <tool_shed_packages />
- <galaxy_packages />
-</dependency_resolvers>
-''') as dependency_resolvers:
- assert 'ToolShed' in dependency_resolvers[0].__class__.__name__
- assert 'Galaxy' in dependency_resolvers[1].__class__.__name__
-
- with __parse_resolvers('''<dependency_resolvers>
- <galaxy_packages />
- <tool_shed_packages />
-</dependency_resolvers>
-''') as dependency_resolvers:
- assert 'Galaxy' in dependency_resolvers[0].__class__.__name__
- assert 'ToolShed' in dependency_resolvers[1].__class__.__name__
-
- with __parse_resolvers('''<dependency_resolvers>
- <galaxy_packages />
- <tool_shed_packages />
- <galaxy_packages versionless="true" />
-</dependency_resolvers>
-''') as dependency_resolvers:
- assert not dependency_resolvers[0].versionless
- assert dependency_resolvers[2].versionless
-
- with __parse_resolvers('''<dependency_resolvers>
- <galaxy_packages />
- <tool_shed_packages />
- <galaxy_packages base_path="/opt/galaxy/legacy/"/>
-</dependency_resolvers>
-''') as dependency_resolvers:
- # Unspecified base_paths are both default_base_paths
- assert dependency_resolvers[0].base_path == dependency_resolvers[1].base_path
- # Can specify custom base path...
- assert dependency_resolvers[2].base_path == "/opt/galaxy/legacy"
- # ... that is different from the default.
- assert dependency_resolvers[0].base_path != dependency_resolvers[2].base_path
-
-
-def test_uses_tool_shed_dependencies():
- with __dependency_manager('''<dependency_resolvers>
- <galaxy_packages />
-</dependency_resolvers>
-''') as dm:
- assert not dm.uses_tool_shed_dependencies()
-
- with __dependency_manager('''<dependency_resolvers>
- <tool_shed_packages />
-</dependency_resolvers>
-''') as dm:
- assert dm.uses_tool_shed_dependencies()
-
-
-def test_config_module_defaults():
- with __parse_resolvers('''<dependency_resolvers>
- <modules prefetch="false" />
-</dependency_resolvers>
-''') as dependency_resolvers:
- module_resolver = dependency_resolvers[0]
- assert module_resolver.module_checker.__class__.__name__ == "AvailModuleChecker"
-
-
-def test_config_modulepath():
- # Test reads and splits MODULEPATH if modulepath is not specified.
- with __parse_resolvers('''<dependency_resolvers>
- <modules find_by="directory" modulepath="/opt/modules/modulefiles:/usr/local/modules/modulefiles" />
-</dependency_resolvers>
-''') as dependency_resolvers:
- assert dependency_resolvers[0].module_checker.directories == ["/opt/modules/modulefiles", "/usr/local/modules/modulefiles"]
-
-
-def test_config_MODULEPATH():
- # Test reads and splits MODULEPATH if modulepath is not specified.
- with __environ({"MODULEPATH": "/opt/modules/modulefiles:/usr/local/modules/modulefiles"}):
- with __parse_resolvers('''<dependency_resolvers>
- <modules find_by="directory" />
-</dependency_resolvers>
-''') as dependency_resolvers:
- assert dependency_resolvers[0].module_checker.directories == ["/opt/modules/modulefiles", "/usr/local/modules/modulefiles"]
-
-
-def test_config_MODULESHOME():
- # Test fallbacks to read MODULESHOME if modulepath is not specified and
- # neither is MODULEPATH.
- with __environ({"MODULESHOME": "/opt/modules"}, remove="MODULEPATH"):
- with __parse_resolvers('''<dependency_resolvers>
- <modules find_by="directory" />
-</dependency_resolvers>
-''') as dependency_resolvers:
- assert dependency_resolvers[0].module_checker.directories == ["/opt/modules/modulefiles"]
-
-
-def test_config_module_directory_searcher():
- with __parse_resolvers('''<dependency_resolvers>
- <modules find_by="directory" modulepath="/opt/Modules/modulefiles" />
-</dependency_resolvers>
-''') as dependency_resolvers:
- module_resolver = dependency_resolvers[0]
- assert module_resolver.module_checker.directories == ["/opt/Modules/modulefiles"]
-
-
-@contextmanager
-def __environ(values, remove=[]):
- """
- Modify the environment for a test, adding/updating values in dict `values` and
- removing any environment variables mentioned in list `remove`.
- """
- new_keys = set(environ.keys()) - set(values.keys())
- old_environ = environ.copy()
- try:
- environ.update(values)
- for to_remove in remove:
- try:
- del environ[remove]
- except KeyError:
- pass
- yield
- finally:
- environ.update(old_environ)
- for key in new_keys:
- del environ[key]
-
-
-@contextmanager
-def __parse_resolvers(xml_content):
- with __dependency_manager(xml_content) as dm:
- yield dm.dependency_resolvers
-
-
-@contextmanager
-def __dependency_manager(xml_content):
- with __test_base_path() as base_path:
- f = tempfile.NamedTemporaryFile()
- f.write(xml_content)
- f.flush()
- dm = DependencyManager( default_base_path=base_path, conf_file=f.name )
- yield dm
diff -r 767d9f567b6fa5f6554ec2180b4f1249587f1473 -r 9051ceb435937348e6417fb96eb9611474496828 test/unit/test_tool_loader.py
--- a/test/unit/test_tool_loader.py
+++ /dev/null
@@ -1,191 +0,0 @@
-from tempfile import mkdtemp
-from shutil import rmtree
-import os
-
-from galaxy.util import parse_xml
-from galaxy.tools.loader import template_macro_params, load_tool
-
-def test_loader():
-
- class TestToolDirectory(object):
- def __init__(self):
- self.temp_directory = mkdtemp()
-
- def __enter__(self):
- return self
-
- def __exit__(self, type, value, tb):
- rmtree(self.temp_directory)
-
- def write(self, contents, name="tool.xml"):
- open(os.path.join(self.temp_directory, name), "w").write(contents)
-
- def load(self, name="tool.xml", preprocess=True):
- if preprocess:
- loader = load_tool
- else:
- loader = parse_xml
- return loader(os.path.join(self.temp_directory, name))
-
- ## Test simple macro replacement.
- with TestToolDirectory() as tool_dir:
- tool_dir.write('''
-<tool>
- <expand macro="inputs" />
- <macros>
- <macro name="inputs">
- <inputs />
- </macro>
- </macros>
-</tool>''')
- xml = tool_dir.load(preprocess=False)
- assert xml.find("inputs") is None
- xml = tool_dir.load(preprocess=True)
- assert xml.find("inputs") is not None
-
- # Test importing macros from external files
- with TestToolDirectory() as tool_dir:
- tool_dir.write('''
-<tool>
- <expand macro="inputs" />
- <macros>
- <import>external.xml</import>
- </macros>
-</tool>''')
-
- tool_dir.write('''
-<macros>
- <macro name="inputs">
- <inputs />
- </macro>
-</macros>''', name="external.xml")
- xml = tool_dir.load(preprocess=False)
- assert xml.find("inputs") is None
- xml = tool_dir.load(preprocess=True)
- assert xml.find("inputs") is not None
-
- # Test macros with unnamed yield statements.
- with TestToolDirectory() as tool_dir:
- tool_dir.write('''
-<tool>
- <expand macro="inputs">
- <input name="first_input" />
- </expand>
- <macros>
- <macro name="inputs">
- <inputs>
- <yield />
- </inputs>
- </macro>
- </macros>
-</tool>''')
- xml = tool_dir.load()
- assert xml.find("inputs").find("input").get("name") == "first_input"
-
- # Test recursive macro applications.
- with TestToolDirectory() as tool_dir:
- tool_dir.write('''
-<tool>
- <expand macro="inputs">
- <input name="first_input" />
- <expand macro="second" />
- </expand>
- <macros>
- <macro name="inputs">
- <inputs>
- <yield />
- </inputs>
- </macro>
- <macro name="second">
- <input name="second_input" />
- </macro>
- </macros>
-</tool>''')
- xml = tool_dir.load()
- assert xml.find("inputs").findall("input")[1].get("name") == "second_input"
-
- # Test recursive macro applications.
- with TestToolDirectory() as tool_dir:
- tool_dir.write('''
-<tool>
- <expand macro="inputs">
- <input name="first_input" />
- <expand macro="second" />
- </expand>
- <macros>
- <macro name="inputs">
- <inputs>
- <yield />
- </inputs>
- </macro>
- <macro name="second">
- <expand macro="second_delegate" />
- </macro>
- <macro name="second_delegate">
- <input name="second_input" />
- </macro>
- </macros>
-</tool>''')
- xml = tool_dir.load()
- assert xml.find("inputs").findall("input")[1].get("name") == "second_input"
-
- # Test <xml> is shortcut for macro type="xml"
- with TestToolDirectory() as tool_dir:
- tool_dir.write('''
-<tool>
- <expand macro="inputs" />
- <macros>
- <xml name="inputs">
- <inputs />
- </xml>
- </macros>
-</tool>''')
- xml = tool_dir.load()
- assert xml.find("inputs") is not None
-
- with TestToolDirectory() as tool_dir:
- tool_dir.write('''
-<tool>
- <command interpreter="python">tool_wrapper.py
- #include source=$tool_params
- </command>
- <macros>
- <template name="tool_params">-a 1 -b 2</template>
- </macros>
-</tool>
-''')
- xml = tool_dir.load()
- params_dict = template_macro_params(xml.getroot())
- assert params_dict['tool_params'] == "-a 1 -b 2"
-
- with TestToolDirectory() as tool_dir:
- tool_dir.write('''
-<tool>
- <macros>
- <token name="@CITATION@">The citation.</token>
- </macros>
- <help>@CITATION@</help>
- <another>
- <tag />
- </another>
-</tool>
-''')
- xml = tool_dir.load()
- help_el = xml.find("help")
- assert help_el.text == "The citation.", help_el.text
-
- with TestToolDirectory() as tool_dir:
- tool_dir.write('''
-<tool>
- <macros>
- <token name="@TAG_VAL@">The value.</token>
- </macros>
- <another>
- <tag value="@TAG_VAL@" />
- </another>
-</tool>
-''')
- xml = tool_dir.load()
- tag_el = xml.find("another").find("tag")
- value = tag_el.get('value')
- assert value == "The value.", value
diff -r 767d9f567b6fa5f6554ec2180b4f1249587f1473 -r 9051ceb435937348e6417fb96eb9611474496828 test/unit/tools/test_tool_deps.py
--- /dev/null
+++ b/test/unit/tools/test_tool_deps.py
@@ -0,0 +1,378 @@
+import tempfile
+import os.path
+from stat import S_IXUSR
+from os import makedirs, stat, symlink, chmod, environ
+from shutil import rmtree
+from galaxy.tools.deps import DependencyManager, INDETERMINATE_DEPENDENCY
+from galaxy.tools.deps.resolvers.galaxy_packages import GalaxyPackageDependency
+from galaxy.tools.deps.resolvers.modules import ModuleDependencyResolver, ModuleDependency
+from galaxy.util.bunch import Bunch
+from contextlib import contextmanager
+from subprocess import Popen, PIPE
+
+
+def test_tool_dependencies():
+ # Setup directories
+
+ with __test_base_path() as base_path:
+ for name, version, sub in [ ( "dep1", "1.0", "env.sh" ), ( "dep1", "2.0", "bin" ), ( "dep2", "1.0", None ) ]:
+ if sub == "bin":
+ p = os.path.join( base_path, name, version, "bin" )
+ else:
+ p = os.path.join( base_path, name, version )
+ try:
+ makedirs( p )
+ except:
+ pass
+ if sub == "env.sh":
+ __touch( os.path.join( p, "env.sh" ) )
+
+ dm = DependencyManager( default_base_path=base_path )
+ dependency = dm.find_dep( "dep1", "1.0" )
+ assert dependency.script == os.path.join( base_path, 'dep1', '1.0', 'env.sh' )
+ assert dependency.path == os.path.join( base_path, 'dep1', '1.0' )
+ assert dependency.version == "1.0"
+ dependency = dm.find_dep( "dep1", "2.0" )
+ assert dependency.script == None
+ assert dependency.path == os.path.join( base_path, 'dep1', '2.0' )
+ assert dependency.version == "2.0"
+
+ ## Test default versions
+ symlink( os.path.join( base_path, 'dep1', '2.0'), os.path.join( base_path, 'dep1', 'default' ) )
+ dependency = dm.find_dep( "dep1", None )
+ assert dependency.version == "2.0"
+
+ ## Test default resolve will be fall back on default package dependency
+ ## when using the default resolver.
+ dependency = dm.find_dep( "dep1", "2.1" )
+ assert dependency.version == "2.0" # 2.0 is defined as default_version
+
+
+TEST_REPO_USER = "devteam"
+TEST_REPO_NAME = "bwa"
+TEST_REPO_CHANGESET = "12abcd41223da"
+TEST_VERSION = "0.5.9"
+
+
+def test_toolshed_set_enviornment_requiremetns():
+ with __test_base_path() as base_path:
+ test_repo = __build_test_repo('set_environment')
+ dm = DependencyManager( default_base_path=base_path )
+ env_settings_dir = os.path.join(base_path, "environment_settings", TEST_REPO_NAME, TEST_REPO_USER, TEST_REPO_NAME, TEST_REPO_CHANGESET)
+ os.makedirs(env_settings_dir)
+ dependency = dm.find_dep( TEST_REPO_NAME, version=None, type='set_environment', installed_tool_dependencies=[test_repo] )
+ assert dependency.version == None
+ assert dependency.script == os.path.join(env_settings_dir, "env.sh")
+
+
+def test_toolshed_package_requirements():
+ with __test_base_path() as base_path:
+ test_repo = __build_test_repo('package', version=TEST_VERSION)
+ dm = DependencyManager( default_base_path=base_path )
+ package_dir = __build_ts_test_package(base_path)
+ dependency = dm.find_dep( TEST_REPO_NAME, version=TEST_VERSION, type='package', installed_tool_dependencies=[test_repo] )
+ assert dependency.version == TEST_VERSION
+ assert dependency.script == os.path.join(package_dir, "env.sh")
+
+
+def test_toolshed_tools_fallback_on_manual_dependencies():
+ with __test_base_path() as base_path:
+ dm = DependencyManager( default_base_path=base_path )
+ test_repo = __build_test_repo('package', version=TEST_VERSION)
+ env_path = __setup_galaxy_package_dep(base_path, "dep1", "1.0")
+ dependency = dm.find_dep( "dep1", version="1.0", type='package', installed_tool_dependencies=[test_repo] )
+ assert dependency.version == "1.0"
+ assert dependency.script == env_path
+
+
+def test_toolshed_greater_precendence():
+ with __test_base_path() as base_path:
+ dm = DependencyManager( default_base_path=base_path )
+ test_repo = __build_test_repo('package', version=TEST_VERSION)
+ ts_package_dir = __build_ts_test_package(base_path)
+ gx_env_path = __setup_galaxy_package_dep(base_path, TEST_REPO_NAME, TEST_VERSION)
+ ts_env_path = os.path.join(ts_package_dir, "env.sh")
+ dependency = dm.find_dep( TEST_REPO_NAME, version=TEST_VERSION, type='package', installed_tool_dependencies=[test_repo] )
+ assert dependency.script != gx_env_path # Not the galaxy path, it should be the tool shed path used.
+ assert dependency.script == ts_env_path
+
+
+def __build_ts_test_package(base_path, script_contents=''):
+ package_dir = os.path.join(base_path, TEST_REPO_NAME, TEST_VERSION, TEST_REPO_USER, TEST_REPO_NAME, TEST_REPO_CHANGESET)
+ __touch(os.path.join(package_dir, 'env.sh'), script_contents)
+ return package_dir
+
+
+def test_module_dependency_resolver():
+ with __test_base_path() as temp_directory:
+ module_script = os.path.join(temp_directory, "modulecmd")
+ __write_script(module_script, '''#!/bin/sh
+cat %s/example_output 1>&2;
+''' % temp_directory)
+ with open(os.path.join(temp_directory, "example_output"), "w") as f:
+ # Subset of module avail from MSI cluster.
+ f.write('''
+-------------------------- /soft/modules/modulefiles ---------------------------
+JAGS/3.2.0-gcc45
+JAGS/3.3.0-gcc4.7.2
+ProbABEL/0.1-3
+ProbABEL/0.1-9e
+R/2.12.2
+R/2.13.1
+R/2.14.1
+R/2.15.0
+R/2.15.1
+R/3.0.1(default)
+abokia-blast/2.0.2-130524/ompi_intel
+abokia-blast/2.0.2-130630/ompi_intel
+
+--------------------------- /soft/intel/modulefiles ----------------------------
+advisor/2013/update1 intel/11.1.075 mkl/10.2.1.017
+advisor/2013/update2 intel/11.1.080 mkl/10.2.5.035
+advisor/2013/update3 intel/12.0 mkl/10.2.7.041
+''')
+ resolver = ModuleDependencyResolver(None, modulecmd=module_script)
+ module = resolver.resolve( name="R", version=None, type="package" )
+ assert module.module_name == "R"
+ assert module.module_version == None
+
+ module = resolver.resolve( name="R", version="3.0.1", type="package" )
+ assert module.module_name == "R"
+ assert module.module_version == "3.0.1"
+
+ module = resolver.resolve( name="R", version="3.0.4", type="package" )
+ assert module == INDETERMINATE_DEPENDENCY
+
+
+def test_module_dependency():
+ with __test_base_path() as temp_directory:
+ ## Create mock modulecmd script that just exports a variable
+ ## the way modulecmd sh load would, but also validate correct
+ ## module name and version are coming through.
+ mock_modulecmd = os.path.join(temp_directory, 'modulecmd')
+ __write_script(mock_modulecmd, '''#!/bin/sh
+if [ $3 != "foomodule/1.0" ];
+then
+ exit 1
+fi
+echo 'FOO="bar"'
+''')
+ resolver = Bunch(modulecmd=mock_modulecmd)
+ dependency = ModuleDependency(resolver, "foomodule", "1.0")
+ __assert_foo_exported( dependency.shell_commands( Bunch( type="package" ) ) )
+
+
+def __write_script(path, contents):
+ with open(path, 'w') as f:
+ f.write(contents)
+ st = stat(path)
+ chmod(path, st.st_mode | S_IXUSR)
+
+
+def test_galaxy_dependency_object_script():
+ with __test_base_path() as base_path:
+ ## Create env.sh file that just exports variable FOO and verify it
+ ## shell_commands export it correctly.
+ env_path = __setup_galaxy_package_dep(base_path, TEST_REPO_NAME, TEST_VERSION, "export FOO=\"bar\"")
+ dependency = GalaxyPackageDependency(env_path, os.path.dirname(env_path), TEST_VERSION)
+ __assert_foo_exported( dependency.shell_commands( Bunch( type="package" ) ) )
+
+
+def test_shell_commands_built():
+ ## Test that dependency manager builds valid shell commands for a list of
+ ## requirements.
+ with __test_base_path() as base_path:
+ dm = DependencyManager( default_base_path=base_path )
+ __setup_galaxy_package_dep( base_path, TEST_REPO_NAME, TEST_VERSION, contents="export FOO=\"bar\"" )
+ mock_requirements = [ Bunch(type="package", version=TEST_VERSION, name=TEST_REPO_NAME ) ]
+ commands = dm.dependency_shell_commands( mock_requirements )
+ __assert_foo_exported( commands )
+
+
+def __assert_foo_exported( commands ):
+ command = ["bash", "-c", "%s; echo \"$FOO\"" % "".join(commands)]
+ process = Popen(command, stdout=PIPE)
+ output = process.communicate()[0].strip()
+ assert output == 'bar', "Command %s exports FOO as %s, not bar" % (command, output)
+
+
+def __setup_galaxy_package_dep(base_path, name, version, contents=""):
+ dep_directory = os.path.join( base_path, name, version )
+ env_path = os.path.join( dep_directory, "env.sh" )
+ __touch( env_path, contents )
+ return env_path
+
+
+def __touch( fname, data=None ):
+ dirname = os.path.dirname( fname )
+ if not os.path.exists( dirname ):
+ makedirs( dirname )
+ f = open( fname, 'w' )
+ try:
+ if data:
+ f.write( data )
+ finally:
+ f.close()
+
+
+def __build_test_repo(type, version=None):
+ return Bunch(
+ owner=TEST_REPO_USER,
+ name=TEST_REPO_NAME,
+ type=type,
+ version=version,
+ tool_shed_repository=Bunch(
+ owner=TEST_REPO_USER,
+ name=TEST_REPO_NAME,
+ installed_changeset_revision=TEST_REPO_CHANGESET
+ )
+ )
+
+
+@contextmanager
+def __test_base_path():
+ base_path = tempfile.mkdtemp()
+ try:
+ yield base_path
+ finally:
+ rmtree(base_path)
+
+
+def test_parse():
+ with __parse_resolvers('''<dependency_resolvers>
+ <tool_shed_packages />
+ <galaxy_packages />
+</dependency_resolvers>
+''') as dependency_resolvers:
+ assert 'ToolShed' in dependency_resolvers[0].__class__.__name__
+ assert 'Galaxy' in dependency_resolvers[1].__class__.__name__
+
+ with __parse_resolvers('''<dependency_resolvers>
+ <galaxy_packages />
+ <tool_shed_packages />
+</dependency_resolvers>
+''') as dependency_resolvers:
+ assert 'Galaxy' in dependency_resolvers[0].__class__.__name__
+ assert 'ToolShed' in dependency_resolvers[1].__class__.__name__
+
+ with __parse_resolvers('''<dependency_resolvers>
+ <galaxy_packages />
+ <tool_shed_packages />
+ <galaxy_packages versionless="true" />
+</dependency_resolvers>
+''') as dependency_resolvers:
+ assert not dependency_resolvers[0].versionless
+ assert dependency_resolvers[2].versionless
+
+ with __parse_resolvers('''<dependency_resolvers>
+ <galaxy_packages />
+ <tool_shed_packages />
+ <galaxy_packages base_path="/opt/galaxy/legacy/"/>
+</dependency_resolvers>
+''') as dependency_resolvers:
+ # Unspecified base_paths are both default_base_paths
+ assert dependency_resolvers[0].base_path == dependency_resolvers[1].base_path
+ # Can specify custom base path...
+ assert dependency_resolvers[2].base_path == "/opt/galaxy/legacy"
+ # ... that is different from the default.
+ assert dependency_resolvers[0].base_path != dependency_resolvers[2].base_path
+
+
+def test_uses_tool_shed_dependencies():
+ with __dependency_manager('''<dependency_resolvers>
+ <galaxy_packages />
+</dependency_resolvers>
+''') as dm:
+ assert not dm.uses_tool_shed_dependencies()
+
+ with __dependency_manager('''<dependency_resolvers>
+ <tool_shed_packages />
+</dependency_resolvers>
+''') as dm:
+ assert dm.uses_tool_shed_dependencies()
+
+
+def test_config_module_defaults():
+ with __parse_resolvers('''<dependency_resolvers>
+ <modules prefetch="false" />
+</dependency_resolvers>
+''') as dependency_resolvers:
+ module_resolver = dependency_resolvers[0]
+ assert module_resolver.module_checker.__class__.__name__ == "AvailModuleChecker"
+
+
+def test_config_modulepath():
+ # Test reads and splits MODULEPATH if modulepath is not specified.
+ with __parse_resolvers('''<dependency_resolvers>
+ <modules find_by="directory" modulepath="/opt/modules/modulefiles:/usr/local/modules/modulefiles" />
+</dependency_resolvers>
+''') as dependency_resolvers:
+ assert dependency_resolvers[0].module_checker.directories == ["/opt/modules/modulefiles", "/usr/local/modules/modulefiles"]
+
+
+def test_config_MODULEPATH():
+ # Test reads and splits MODULEPATH if modulepath is not specified.
+ with __environ({"MODULEPATH": "/opt/modules/modulefiles:/usr/local/modules/modulefiles"}):
+ with __parse_resolvers('''<dependency_resolvers>
+ <modules find_by="directory" />
+</dependency_resolvers>
+''') as dependency_resolvers:
+ assert dependency_resolvers[0].module_checker.directories == ["/opt/modules/modulefiles", "/usr/local/modules/modulefiles"]
+
+
+def test_config_MODULESHOME():
+ # Test fallbacks to read MODULESHOME if modulepath is not specified and
+ # neither is MODULEPATH.
+ with __environ({"MODULESHOME": "/opt/modules"}, remove="MODULEPATH"):
+ with __parse_resolvers('''<dependency_resolvers>
+ <modules find_by="directory" />
+</dependency_resolvers>
+''') as dependency_resolvers:
+ assert dependency_resolvers[0].module_checker.directories == ["/opt/modules/modulefiles"]
+
+
+def test_config_module_directory_searcher():
+ with __parse_resolvers('''<dependency_resolvers>
+ <modules find_by="directory" modulepath="/opt/Modules/modulefiles" />
+</dependency_resolvers>
+''') as dependency_resolvers:
+ module_resolver = dependency_resolvers[0]
+ assert module_resolver.module_checker.directories == ["/opt/Modules/modulefiles"]
+
+
+@contextmanager
+def __environ(values, remove=[]):
+ """
+ Modify the environment for a test, adding/updating values in dict `values` and
+ removing any environment variables mentioned in list `remove`.
+ """
+ new_keys = set(environ.keys()) - set(values.keys())
+ old_environ = environ.copy()
+ try:
+ environ.update(values)
+ for to_remove in remove:
+ try:
+ del environ[remove]
+ except KeyError:
+ pass
+ yield
+ finally:
+ environ.update(old_environ)
+ for key in new_keys:
+ del environ[key]
+
+
+@contextmanager
+def __parse_resolvers(xml_content):
+ with __dependency_manager(xml_content) as dm:
+ yield dm.dependency_resolvers
+
+
+@contextmanager
+def __dependency_manager(xml_content):
+ with __test_base_path() as base_path:
+ f = tempfile.NamedTemporaryFile()
+ f.write(xml_content)
+ f.flush()
+ dm = DependencyManager( default_base_path=base_path, conf_file=f.name )
+ yield dm
diff -r 767d9f567b6fa5f6554ec2180b4f1249587f1473 -r 9051ceb435937348e6417fb96eb9611474496828 test/unit/tools/test_tool_loader.py
--- /dev/null
+++ b/test/unit/tools/test_tool_loader.py
@@ -0,0 +1,191 @@
+from tempfile import mkdtemp
+from shutil import rmtree
+import os
+
+from galaxy.util import parse_xml
+from galaxy.tools.loader import template_macro_params, load_tool
+
+def test_loader():
+
+ class TestToolDirectory(object):
+ def __init__(self):
+ self.temp_directory = mkdtemp()
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, type, value, tb):
+ rmtree(self.temp_directory)
+
+ def write(self, contents, name="tool.xml"):
+ open(os.path.join(self.temp_directory, name), "w").write(contents)
+
+ def load(self, name="tool.xml", preprocess=True):
+ if preprocess:
+ loader = load_tool
+ else:
+ loader = parse_xml
+ return loader(os.path.join(self.temp_directory, name))
+
+ ## Test simple macro replacement.
+ with TestToolDirectory() as tool_dir:
+ tool_dir.write('''
+<tool>
+ <expand macro="inputs" />
+ <macros>
+ <macro name="inputs">
+ <inputs />
+ </macro>
+ </macros>
+</tool>''')
+ xml = tool_dir.load(preprocess=False)
+ assert xml.find("inputs") is None
+ xml = tool_dir.load(preprocess=True)
+ assert xml.find("inputs") is not None
+
+ # Test importing macros from external files
+ with TestToolDirectory() as tool_dir:
+ tool_dir.write('''
+<tool>
+ <expand macro="inputs" />
+ <macros>
+ <import>external.xml</import>
+ </macros>
+</tool>''')
+
+ tool_dir.write('''
+<macros>
+ <macro name="inputs">
+ <inputs />
+ </macro>
+</macros>''', name="external.xml")
+ xml = tool_dir.load(preprocess=False)
+ assert xml.find("inputs") is None
+ xml = tool_dir.load(preprocess=True)
+ assert xml.find("inputs") is not None
+
+ # Test macros with unnamed yield statements.
+ with TestToolDirectory() as tool_dir:
+ tool_dir.write('''
+<tool>
+ <expand macro="inputs">
+ <input name="first_input" />
+ </expand>
+ <macros>
+ <macro name="inputs">
+ <inputs>
+ <yield />
+ </inputs>
+ </macro>
+ </macros>
+</tool>''')
+ xml = tool_dir.load()
+ assert xml.find("inputs").find("input").get("name") == "first_input"
+
+ # Test recursive macro applications.
+ with TestToolDirectory() as tool_dir:
+ tool_dir.write('''
+<tool>
+ <expand macro="inputs">
+ <input name="first_input" />
+ <expand macro="second" />
+ </expand>
+ <macros>
+ <macro name="inputs">
+ <inputs>
+ <yield />
+ </inputs>
+ </macro>
+ <macro name="second">
+ <input name="second_input" />
+ </macro>
+ </macros>
+</tool>''')
+ xml = tool_dir.load()
+ assert xml.find("inputs").findall("input")[1].get("name") == "second_input"
+
+ # Test recursive macro applications.
+ with TestToolDirectory() as tool_dir:
+ tool_dir.write('''
+<tool>
+ <expand macro="inputs">
+ <input name="first_input" />
+ <expand macro="second" />
+ </expand>
+ <macros>
+ <macro name="inputs">
+ <inputs>
+ <yield />
+ </inputs>
+ </macro>
+ <macro name="second">
+ <expand macro="second_delegate" />
+ </macro>
+ <macro name="second_delegate">
+ <input name="second_input" />
+ </macro>
+ </macros>
+</tool>''')
+ xml = tool_dir.load()
+ assert xml.find("inputs").findall("input")[1].get("name") == "second_input"
+
+ # Test <xml> is shortcut for macro type="xml"
+ with TestToolDirectory() as tool_dir:
+ tool_dir.write('''
+<tool>
+ <expand macro="inputs" />
+ <macros>
+ <xml name="inputs">
+ <inputs />
+ </xml>
+ </macros>
+</tool>''')
+ xml = tool_dir.load()
+ assert xml.find("inputs") is not None
+
+ with TestToolDirectory() as tool_dir:
+ tool_dir.write('''
+<tool>
+ <command interpreter="python">tool_wrapper.py
+ #include source=$tool_params
+ </command>
+ <macros>
+ <template name="tool_params">-a 1 -b 2</template>
+ </macros>
+</tool>
+''')
+ xml = tool_dir.load()
+ params_dict = template_macro_params(xml.getroot())
+ assert params_dict['tool_params'] == "-a 1 -b 2"
+
+ with TestToolDirectory() as tool_dir:
+ tool_dir.write('''
+<tool>
+ <macros>
+ <token name="@CITATION@">The citation.</token>
+ </macros>
+ <help>@CITATION@</help>
+ <another>
+ <tag />
+ </another>
+</tool>
+''')
+ xml = tool_dir.load()
+ help_el = xml.find("help")
+ assert help_el.text == "The citation.", help_el.text
+
+ with TestToolDirectory() as tool_dir:
+ tool_dir.write('''
+<tool>
+ <macros>
+ <token name="@TAG_VAL@">The value.</token>
+ </macros>
+ <another>
+ <tag value="@TAG_VAL@" />
+ </another>
+</tool>
+''')
+ xml = tool_dir.load()
+ tag_el = xml.find("another").find("tag")
+ value = tag_el.get('value')
+ assert value == "The value.", value
https://bitbucket.org/galaxy/galaxy-central/commits/fac578cca758/
Changeset: fac578cca758
User: jmchilton
Date: 2014-02-22 05:09:57
Summary: Introduce DatasetMatcher to simplify DatasetToolParameter...
This reduces code duplication related dataset_collectors now and abstracts out important functionality I reuse further to collect dataset collections downstream.
Was originally added in 28d43f4 as DatasetParamContext and backed out of right away. I have reworked it so that it no longer breaks implicit conversion, the relevant classes and methods have less generic names, and it has a healthy set of test cases.
In addition to basic tests on matching datasets to parameters, selections, and implicit conversions - these tests include testing of dataset security inconjuction with data_destination tools as well as filtering data parameters on other data parameters.
Affected #: 3 files
diff -r 9051ceb435937348e6417fb96eb9611474496828 -r fac578cca75887d811e67993a655fed20c0d8713 lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -16,6 +16,7 @@
from sanitize import ToolParameterSanitizer
import validation
import dynamic_options
+from .dataset_matcher import DatasetMatcher
# For BaseURLToolParameter
from galaxy.web import url_for
from galaxy.model.item_attrs import Dictifiable
@@ -1610,52 +1611,36 @@
self.conversions.append( ( name, conv_extensions, conv_types ) )
def get_html_field( self, trans=None, value=None, other_values={} ):
- filter_value = None
- if self.options:
- try:
- filter_value = self.options.get_options( trans, other_values )[0][0]
- except IndexError:
- pass # no valid options
history = self._get_history( trans )
if value is not None:
if type( value ) != list:
value = [ value ]
+ dataset_matcher = DatasetMatcher( trans, self, value, other_values )
field = form_builder.SelectField( self.name, self.multiple, None, self.refresh_on_change, refresh_on_change_values=self.refresh_on_change_values )
# CRUCIAL: the dataset_collector function needs to be local to DataToolParameter.get_html_field()
def dataset_collector( hdas, parent_hid ):
- current_user_roles = trans.get_current_user_roles()
for i, hda in enumerate( hdas ):
hda_name = hda.name
if parent_hid is not None:
hid = "%s.%d" % ( parent_hid, i + 1 )
else:
hid = str( hda.hid )
- if not hda.dataset.state in [galaxy.model.Dataset.states.ERROR, galaxy.model.Dataset.states.DISCARDED] and \
- ( hda.visible or ( value and hda in value and not hda.implicitly_converted_parent_datasets ) ) and \
- trans.app.security_agent.can_access_dataset( current_user_roles, hda.dataset ):
- # If we are sending data to an external application, then we need to make sure there are no roles
- # associated with the dataset that restrict it's access from "public".
- if self.tool and self.tool.tool_type == 'data_destination' and not trans.app.security_agent.dataset_is_public( hda.dataset ):
- continue
- if self.options and self._options_filter_attribute( hda ) != filter_value:
- continue
- if hda.datatype.matches_any( self.formats ):
- selected = ( value and ( hda in value ) )
- if hda.visible:
- hidden_text = ""
- else:
- hidden_text = " (hidden)"
- field.add_option( "%s:%s %s" % ( hid, hidden_text, hda_name ), hda.id, selected )
+ hda_match = dataset_matcher.hda_match( hda )
+ if not hda_match:
+ continue
+ if not hda_match.implicit_conversion:
+ selected = dataset_matcher.selected( hda )
+ if hda.visible:
+ hidden_text = ""
else:
- target_ext, converted_dataset = hda.find_conversion_destination( self.formats )
- if target_ext:
- if converted_dataset:
- hda = converted_dataset
- if not trans.app.security_agent.can_access_dataset( current_user_roles, hda.dataset ):
- continue
- selected = ( value and ( hda in value ) )
- field.add_option( "%s: (as %s) %s" % ( hid, target_ext, hda_name ), hda.id, selected )
+ hidden_text = " (hidden)"
+ field.add_option( "%s:%s %s" % ( hid, hidden_text, hda_name ), hda.id, selected )
+ else:
+ hda = hda_match.hda # Get converted dataset
+ target_ext = hda_match.target_ext
+ selected = dataset_matcher.selected( hda )
+ field.add_option( "%s: (as %s) %s" % ( hid, target_ext, hda_name ), hda.id, selected )
# Also collect children via association object
dataset_collector( hda.children, hid )
dataset_collector( history.active_datasets_children_and_roles, None )
@@ -1685,30 +1670,18 @@
if trans is None or trans.workflow_building_mode or trans.webapp.name == 'tool_shed':
return DummyDataset()
history = self._get_history( trans, history )
+ dataset_matcher = DatasetMatcher( trans, self, None, context )
if self.optional:
return None
most_recent_dataset = []
- filter_value = None
- if self.options:
- try:
- filter_value = self.options.get_options( trans, context )[0][0]
- except IndexError:
- pass # no valid options
def dataset_collector( datasets ):
for i, data in enumerate( datasets ):
- if data.visible and not data.deleted and data.state not in [data.states.ERROR, data.states.DISCARDED]:
- is_valid = False
- if data.datatype.matches_any( self.formats ):
- is_valid = True
- else:
- target_ext, converted_dataset = data.find_conversion_destination( self.formats )
- if target_ext:
- is_valid = True
- if converted_dataset:
- data = converted_dataset
- if not is_valid or ( self.options and self._options_filter_attribute( data ) != filter_value ):
+ if data.visible and dataset_matcher.hda_accessible( data, check_security=False ):
+ match = dataset_matcher.valid_hda_match( data, check_security=False )
+ if not match or dataset_matcher.filter( match.hda ):
continue
+ data = match.hda
most_recent_dataset.append(data)
# Also collect children via association object
dataset_collector( data.children )
diff -r 9051ceb435937348e6417fb96eb9611474496828 -r fac578cca75887d811e67993a655fed20c0d8713 lib/galaxy/tools/parameters/dataset_matcher.py
--- /dev/null
+++ b/lib/galaxy/tools/parameters/dataset_matcher.py
@@ -0,0 +1,126 @@
+import galaxy.model
+
+from logging import getLogger
+log = getLogger( __name__ )
+
+ROLES_UNSET = object()
+INVALID_STATES = [ galaxy.model.Dataset.states.ERROR, galaxy.model.Dataset.states.DISCARDED ]
+
+
+class DatasetMatcher( object ):
+ """ Utility class to aid DataToolParameter and similar classes in reasoning
+ about what HDAs could match or are selected for a parameter and value.
+
+ Goal here is to both encapsulate and reuse logic related to filtering,
+ datatype matching, hiding errored dataset, finding implicit conversions,
+ and permission handling.
+ """
+
+ def __init__( self, trans, param, value, other_values ):
+ self.trans = trans
+ self.param = param
+ self.tool = param.tool
+ self.value = value
+ self.current_user_roles = ROLES_UNSET
+ filter_value = None
+ if param.options:
+ try:
+ filter_value = param.options.get_options( trans, other_values )[0][0]
+ except IndexError:
+ pass # no valid options
+ self.filter_value = filter_value
+
+ def hda_accessible( self, hda, check_security=True ):
+ """ Does HDA correspond to dataset that is an a valid state and is
+ accessible to user.
+ """
+ dataset = hda.dataset
+ state_valid = not dataset.state in INVALID_STATES
+ return state_valid and ( not check_security or self.__can_access_dataset( dataset ) )
+
+ def valid_hda_match( self, hda, check_implicit_conversions=True, check_security=False ):
+ """ Return False of this parameter can not be matched to a the supplied
+ HDA, otherwise return a description of the match (either a
+ HdaDirectMatch describing a direct match or a HdaImplicitMatch
+ describing an implicit conversion.)
+ """
+ if self.filter( hda ):
+ return False
+ formats = self.param.formats
+ if hda.datatype.matches_any( formats ):
+ return HdaDirectMatch( hda )
+ if not check_implicit_conversions:
+ return False
+ target_ext, converted_dataset = hda.find_conversion_destination( formats )
+ if target_ext:
+ if converted_dataset:
+ hda = converted_dataset
+ if check_security and not self.__can_access_dataset( hda.dataset ):
+ return False
+ return HdaImplicitMatch( hda, target_ext )
+ return False
+
+ def hda_match( self, hda, check_implicit_conversions=True ):
+ """ If HDA is accessible, return information about whether it could
+ match this parameter and if so how. See valid_hda_match for more
+ information.
+ """
+ accessible = self.hda_accessible( hda )
+ if accessible and ( hda.visible or ( self.selected( hda ) and not hda.implicitly_converted_parent_datasets ) ):
+ # If we are sending data to an external application, then we need to make sure there are no roles
+ # associated with the dataset that restrict it's access from "public".
+ require_public = self.tool and self.tool.tool_type == 'data_destination'
+ if require_public and not self.trans.app.security_agent.dataset_is_public( hda.dataset ):
+ return False
+ if self.filter( hda ):
+ return False
+ return self.valid_hda_match( hda, check_implicit_conversions=check_implicit_conversions )
+
+ def selected( self, hda ):
+ """ Given value for DataToolParameter, is this HDA "selected".
+ """
+ value = self.value
+ return value and hda in value
+
+ def filter( self, hda ):
+ """ Filter out this value based on other values for job (if
+ applicable).
+ """
+ param = self.param
+ return param.options and param._options_filter_attribute( hda ) != self.filter_value
+
+ def __can_access_dataset( self, dataset ):
+ # Lazily cache current_user_roles.
+ if self.current_user_roles is ROLES_UNSET:
+ self.current_user_roles = self.trans.get_current_user_roles()
+ return self.trans.app.security_agent.can_access_dataset( self.current_user_roles, dataset )
+
+
+class HdaDirectMatch( object ):
+ """ Supplied HDA was a valid option directly (did not need to find implicit
+ conversion).
+ """
+
+ def __init__( self, hda ):
+ self.hda = hda
+
+ @property
+ def implicit_conversion( self ):
+ return False
+
+
+class HdaImplicitMatch( object ):
+ """ Supplied HDA was a valid option directly (did not need to find implicit
+ conversion).
+ """
+
+ def __init__( self, hda, target_ext ):
+ self.hda = hda
+ self.target_ext = target_ext
+
+ @property
+ def implicit_conversion( self ):
+ return True
+
+
+__all__ = [ DatasetMatcher ]
diff -r 9051ceb435937348e6417fb96eb9611474496828 -r fac578cca75887d811e67993a655fed20c0d8713 test/unit/tools/test_dataset_matcher.py
--- /dev/null
+++ b/test/unit/tools/test_dataset_matcher.py
@@ -0,0 +1,167 @@
+from unittest import TestCase
+
+from galaxy import model
+from galaxy.util import bunch
+from galaxy.tools.parameters import basic
+from galaxy.tools.parameters import dataset_matcher
+
+from elementtree.ElementTree import XML
+
+import tools_support
+from .test_data_parameters import MockHistoryDatasetAssociation
+
+
+class DatasetMatcherTestCase( TestCase, tools_support.UsesApp ):
+
+ def test_hda_accessible( self ):
+ # Cannot access errored or discard datasets.
+ self.mock_hda.dataset.state = model.Dataset.states.ERROR
+ assert not self.test_context.hda_accessible( self.mock_hda )
+
+ self.mock_hda.dataset.state = model.Dataset.states.DISCARDED
+ assert not self.test_context.hda_accessible( self.mock_hda )
+
+ # Can access datasets in other states.
+ self.mock_hda.dataset.state = model.Dataset.states.OK
+ assert self.test_context.hda_accessible( self.mock_hda )
+
+ self.mock_hda.dataset.state = model.Dataset.states.QUEUED
+ assert self.test_context.hda_accessible( self.mock_hda )
+
+ # Cannot access dataset if security agent says no.
+ self.app.security_agent.can_access_dataset = lambda roles, dataset: False
+ assert not self.test_context.hda_accessible( self.mock_hda )
+
+ def test_selected( self ):
+ self.test_context.value = []
+ assert not self.test_context.selected( self.mock_hda )
+
+ self.test_context.value = [ self.mock_hda ]
+ assert self.test_context.selected( self.mock_hda )
+
+ def test_hda_mismatches( self ):
+ # Datasets not visible are not "valid" for param.
+ self.mock_hda.visible = False
+ assert not self.test_context.hda_match( self.mock_hda )
+
+ # Datasets that don't match datatype are not valid.
+ self.mock_hda.visible = True
+ self.mock_hda.datatype_matches = False
+ assert not self.test_context.hda_match( self.mock_hda )
+
+ def test_valid_hda_direct_match( self ):
+ # Datasets that visible and matching are valid
+ self.mock_hda.visible = True
+ self.mock_hda.datatype_matches = True
+ hda_match = self.test_context.hda_match( self.mock_hda, check_implicit_conversions=False )
+ assert hda_match
+
+ # Match is not a conversion and so matching hda is the same hda
+ # supplied.
+ assert not hda_match.implicit_conversion
+ assert hda_match.hda == self.mock_hda
+
+ def test_valid_hda_implicit_convered( self ):
+ # Find conversion returns an HDA to an already implicitly converted
+ # dataset.
+ self.mock_hda.datatype_matches = False
+ converted_hda = model.HistoryDatasetAssociation()
+ self.mock_hda.conversion_destination = ( "tabular", converted_hda )
+ hda_match = self.test_context.hda_match( self.mock_hda )
+
+ assert hda_match
+ assert hda_match.implicit_conversion
+ assert hda_match.hda == converted_hda
+ assert hda_match.target_ext == "tabular"
+
+ def test_hda_match_implicit_can_convert( self ):
+ # Find conversion returns a target extension to convert to, but not
+ # a previously implicitly converted dataset.
+ self.mock_hda.datatype_matches = False
+ self.mock_hda.conversion_destination = ( "tabular", None )
+ hda_match = self.test_context.hda_match( self.mock_hda )
+
+ assert hda_match
+ assert hda_match.implicit_conversion
+ assert hda_match.hda == self.mock_hda
+ assert hda_match.target_ext == "tabular"
+
+ def test_hda_match_properly_skips_conversion( self ):
+ self.mock_hda.datatype_matches = False
+ self.mock_hda.conversion_destination = ( "tabular", bunch.Bunch() )
+ hda_match = self.test_context.hda_match( self.mock_hda, check_implicit_conversions=False )
+ assert not hda_match
+
+ def test_data_destination_tools_require_public( self ):
+ self.tool.tool_type = "data_destination"
+
+ # Public datasets okay and valid
+ self.app.security_agent.dataset_is_public = lambda dataset: True
+ hda_match = self.test_context.hda_match( self.mock_hda )
+ assert hda_match
+
+ # Non-public datasets not valid
+ self.app.security_agent.dataset_is_public = lambda dataset: False
+ hda_match = self.test_context.hda_match( self.mock_hda )
+ assert not hda_match
+
+ def test_filtered_hda_matched_key( self ):
+ self.filtered_param = True
+ data1_val = model.HistoryDatasetAssociation()
+ data1_val.dbkey = "hg18"
+ self.other_values = { "data1": data1_val }
+ assert self.test_context.filter_value == "hg18"
+
+ # mock_hda is hg19, other is hg18 so should not be "valid hda"
+ hda_match = self.test_context.hda_match( self.mock_hda )
+ assert not hda_match
+
+ def test_filtered_hda_unmatched_key( self ):
+ self.filtered_param = True
+ data1_val = model.HistoryDatasetAssociation()
+ data1_val.dbkey = "hg19"
+ self.other_values = { "data1": data1_val }
+
+ # Other param value and this dataset both hg19, should be valid
+ hda_match = self.test_context.hda_match( self.mock_hda )
+ assert hda_match
+
+ def setUp( self ):
+ self.setup_app()
+ self.mock_hda = MockHistoryDatasetAssociation()
+ self.tool = bunch.Bunch(
+ app=self.app,
+ tool_type="default",
+ )
+ self.current_user_roles = []
+ self.other_values = {}
+
+ # Reset lazily generated stuff
+ self.filtered_param = False
+ self._test_context = None
+ self.param = None
+
+ @property
+ def test_context( self ):
+ if self._test_context is None:
+ option_xml = ""
+ if self.filtered_param:
+ option_xml = '''<options><filter type="data_meta" ref="data1" key="dbkey" /></options>'''
+ param_xml = XML( '''<param name="data2" type="data" ext="txt">%s</param>''' % option_xml )
+ self.param = basic.DataToolParameter(
+ tool=self.tool,
+ elem=param_xml,
+ )
+
+ self._test_context = dataset_matcher.DatasetMatcher(
+ trans=bunch.Bunch(
+ app=self.app,
+ get_current_user_roles=lambda: self.current_user_roles,
+ workflow_building_mode=True,
+ ),
+ param=self.param,
+ value=[ ],
+ other_values=self.other_values
+ )
+
+ return self._test_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
commit/galaxy-central: carlfeberhard: Embedded histories: refactor and clean up
by commits-noreply@bitbucket.org 21 Feb '14
by commits-noreply@bitbucket.org 21 Feb '14
21 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2403d6f67500/
Changeset: 2403d6f67500
User: carlfeberhard
Date: 2014-02-21 23:19:19
Summary: Embedded histories: refactor and clean up
Affected #: 10 files
diff -r 6b6c7de6bbe10721674f50ebb5e8a600d8586416 -r 2403d6f67500ec35b16ce604142d98766286b65a lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -753,21 +753,7 @@
history.annotation = self.get_item_annotation_str( trans.sa_session, history.user, history )
for dataset in datasets:
dataset.annotation = self.get_item_annotation_str( trans.sa_session, history.user, dataset )
-
- user_is_owner = trans.user == history.user
- history.annotation = self.get_item_annotation_str( trans.sa_session, history.user, history )
-
- hda_dicts = []
- datasets = self.get_history_datasets( trans, history )
- for hda in datasets:
- hda_dict = self.get_hda_dict( trans, hda )
- hda_dict[ 'annotation' ] = self.get_item_annotation_str( trans.sa_session, history.user, hda )
- hda_dicts.append( hda_dict )
- history_dict = self.get_history_dict( trans, history, hda_dictionaries=hda_dicts )
- history_dict[ 'annotation' ] = history.annotation
-
- return trans.fill_template( "history/item_content.mako", item=history, item_data=datasets,
- user_is_owner=user_is_owner, history_dict=history_dict, hda_dicts=hda_dicts )
+ return trans.stream_template_mako( "/history/item_content.mako", item = history, item_data = datasets )
@web.expose
def name_autocomplete_data( self, trans, q=None, limit=None, timestamp=None ):
diff -r 6b6c7de6bbe10721674f50ebb5e8a600d8586416 -r 2403d6f67500ec35b16ce604142d98766286b65a lib/galaxy/webapps/galaxy/controllers/page.py
--- a/lib/galaxy/webapps/galaxy/controllers/page.py
+++ b/lib/galaxy/webapps/galaxy/controllers/page.py
@@ -721,27 +721,52 @@
def get_item( self, trans, id ):
return self.get_page( trans, id )
+ def _get_embedded_history_html( self, trans, id ):
+ """
+ Returns html suitable for embedding in another page.
+ """
+ history = self.get_history( trans, id, False, True )
+ if not history:
+ return None
+
+ # create ownership flag for template, dictify models
+ # note: adding original annotation since this is published - get_dict returns user-based annos
+ user_is_owner = trans.user == history.user
+ history.annotation = self.get_item_annotation_str( trans.sa_session, history.user, history )
+
+ hda_dicts = []
+ datasets = self.get_history_datasets( trans, history )
+ for hda in datasets:
+ hda_dict = self.get_hda_dict( trans, hda )
+ hda_dict[ 'annotation' ] = self.get_item_annotation_str( trans.sa_session, history.user, hda )
+ hda_dicts.append( hda_dict )
+ history_dict = self.get_history_dict( trans, history, hda_dictionaries=hda_dicts )
+ history_dict[ 'annotation' ] = history.annotation
+
+ filled = trans.fill_template( "history/embed.mako", item=history, item_data=datasets,
+ user_is_owner=user_is_owner, history_dict=history_dict, hda_dicts=hda_dicts )
+ return filled
+
def _get_embed_html( self, trans, item_class, item_id ):
""" Returns HTML for embedding an item in a page. """
item_class = self.get_class( item_class )
if item_class == model.History:
- history = self.get_history( trans, item_id, False, True )
- history.annotation = self.get_item_annotation_str( trans.sa_session, history.user, history )
- if history:
- datasets = self.get_history_datasets( trans, history )
- return trans.fill_template( "history/embed.mako", item=history, item_data=datasets )
+ return self._get_embedded_history_html( trans, item_id )
+
elif item_class == model.HistoryDatasetAssociation:
dataset = self.get_dataset( trans, item_id, False, True )
dataset.annotation = self.get_item_annotation_str( trans.sa_session, dataset.history.user, dataset )
if dataset:
data = self.get_data( dataset )
return trans.fill_template( "dataset/embed.mako", item=dataset, item_data=data )
+
elif item_class == model.StoredWorkflow:
workflow = self.get_stored_workflow( trans, item_id, False, True )
workflow.annotation = self.get_item_annotation_str( trans.sa_session, workflow.user, workflow )
if workflow:
self.get_stored_workflow_steps( trans, workflow )
return trans.fill_template( "workflow/embed.mako", item=workflow, item_data=workflow.latest_workflow.steps )
+
elif item_class == model.Visualization:
visualization = self.get_visualization( trans, item_id, False, True )
visualization.annotation = self.get_item_annotation_str( trans.sa_session, visualization.user, visualization )
diff -r 6b6c7de6bbe10721674f50ebb5e8a600d8586416 -r 2403d6f67500ec35b16ce604142d98766286b65a static/scripts/mvc/history/readonly-history-panel.js
--- a/static/scripts/mvc/history/readonly-history-panel.js
+++ b/static/scripts/mvc/history/readonly-history-panel.js
@@ -107,6 +107,9 @@
// ---- handle models passed on init
if( this.model ){
+ if( this.logger ){
+ this.model.logger = this.logger;
+ }
this._setUpWebStorage( attributes.initiallyExpanded, attributes.show_deleted, attributes.show_hidden );
this._setUpModelEventHandlers();
}
@@ -302,6 +305,9 @@
newHistoryJSON.user = Galaxy.currUser.toJSON();
}
this.model = new historyModel.History( newHistoryJSON, newHdaJSON, attributes );
+ if( this.logger ){
+ this.model.logger = this.logger;
+ }
this._setUpWebStorage( attributes.initiallyExpanded, attributes.show_deleted, attributes.show_hidden );
this._setUpModelEventHandlers();
this.selectedHdaIds = [];
diff -r 6b6c7de6bbe10721674f50ebb5e8a600d8586416 -r 2403d6f67500ec35b16ce604142d98766286b65a static/scripts/packed/mvc/history/readonly-history-panel.js
--- a/static/scripts/packed/mvc/history/readonly-history-panel.js
+++ b/static/scripts/packed/mvc/history/readonly-history-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/history/history-model","mvc/dataset/hda-base"],function(e,a){var d=SessionStorageModel.extend({defaults:{expandedHdas:{},show_deleted:false,show_hidden:false},addExpandedHda:function(f){this.save("expandedHdas",_.extend(this.get("expandedHdas"),_.object([f],[true])))},removeExpandedHda:function(f){this.save("expandedHdas",_.omit(this.get("expandedHdas"),f))},toString:function(){return"HistoryPrefs("+this.id+")"}});d.historyStorageKey=function c(f){if(!f){throw new Error("HistoryPrefs.historyStorageKey needs valid id: "+f)}return("history:"+f)};var b=Backbone.View.extend(LoggableMixin).extend({HDAViewClass:a.HDABaseView,tagName:"div",className:"history-panel",fxSpeed:"fast",datasetsSelector:".datasets-list",msgsSelector:".message-container",emptyMsgSelector:".empty-history-message",emptyMsg:_l("This history is empty"),noneFoundMsg:_l("No matching datasets found"),initialize:function(f){f=f||{};if(f.logger){this.logger=f.logger}this.log(this+".initialize:",f);this.linkTarget=f.linkTarget||"_blank";this.fxSpeed=_.has(f,"fxSpeed")?(f.fxSpeed):(this.fxSpeed);this.hdaViews={};this.indicator=new LoadingIndicator(this.$el);this.filters=[];this.searchFor="";this._setUpListeners();if(this.model){this._setUpWebStorage(f.initiallyExpanded,f.show_deleted,f.show_hidden);this._setUpModelEventHandlers()}if(f.onready){f.onready.call(this)}},_setUpListeners:function(){this.on("error",function(g,j,f,i,h){this.errorHandler(g,j,f,i,h)});this.on("loading-history",function(){this.showLoadingIndicator("loading history...",40)});this.on("loading-done",function(){this.hideLoadingIndicator(40);if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});if(this.logger){this.on("all",function(f){this.log(this+"",arguments)},this)}},errorHandler:function(h,k,g,j,i){var f=this._parseErrorMessage(h,k,g,j,i);if(k&&k.status===0&&k.readyState===0){}else{if(k&&k.status===502){}else{if(!this.$el.find(this.msgsSelector).is(":visible")){this.once("rendered",function(){this.displayMessage("error",f.message,f.details)})}else{this.displayMessage("error",f.message,f.details)}}}},_parseErrorMessage:function(i,m,h,l,k){var g=Galaxy.currUser,f={message:this._bePolite(l),details:{user:(g instanceof User)?(g.toJSON()):(g+""),source:(i instanceof Backbone.Model)?(i.toJSON()):(i+""),xhr:m,options:(m)?(_.omit(h,"xhr")):(h)}};_.extend(f.details,k||{});if(m&&_.isFunction(m.getAllResponseHeaders)){var j=m.getAllResponseHeaders();j=_.compact(j.split("\n"));j=_.map(j,function(n){return n.split(": ")});f.details.xhr.responseHeaders=_.object(j)}return f},_bePolite:function(f){f=f||_l("An error occurred while getting updates from the server");return f+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadHistoryWithHDADetails:function(i,h,g,k){var f=this,j=function(l){return f.getExpandedHdaIds(l.id)};return this.loadHistory(i,h,g,k,j)},loadHistory:function(i,h,g,l,j){this.trigger("loading-history",this);h=h||{};var f=this;var k=e.History.getHistoryData(i,{historyFn:g,hdaFn:l,hdaDetailIds:h.initiallyExpanded||j});return this._loadHistoryFromXHR(k,h).fail(function(o,m,n){f.trigger("error",f,o,h,_l("An error was encountered while "+m),{historyId:i,history:n||{}})}).always(function(){f.trigger("loading-done",f)})},_loadHistoryFromXHR:function(h,g){var f=this;h.then(function(i,j){f.setModel(i,j,g)});h.fail(function(j,i){f.render()});return h},setModel:function(h,f,g){g=g||{};if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.hdaViews={};if(Galaxy&&Galaxy.currUser){h.user=Galaxy.currUser.toJSON()}this.model=new e.History(h,f,g);this._setUpWebStorage(g.initiallyExpanded,g.show_deleted,g.show_hidden);this._setUpModelEventHandlers();this.selectedHdaIds=[];this.trigger("new-model",this);this.render();return this},_setUpWebStorage:function(g,f,h){this.storage=new d({id:d.historyStorageKey(this.model.get("id"))});if(_.isObject(g)){this.storage.set("exandedHdas",g)}if(_.isBoolean(f)){this.storage.set("show_deleted",f)}if(_.isBoolean(h)){this.storage.set("show_hidden",h)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get())},clearWebStorage:function(){for(var f in sessionStorage){if(f.indexOf("history:")===0){sessionStorage.removeItem(f)}}},getStoredOptions:function(g){if(!g||g==="current"){return(this.storage)?(this.storage.get()):({})}var f=sessionStorage.getItem(d.historyStorageKey(g));return(f===null)?({}):(JSON.parse(f))},getExpandedHdaIds:function(f){var g=this.getStoredOptions(f).expandedHdas;return((_.isEmpty(g))?([]):(_.keys(g)))},_setUpModelEventHandlers:function(){this.model.hdas.on("add",this.addHdaView,this);this.model.on("error error:hdas",function(g,i,f,h){this.errorHandler(g,i,f,h)},this)},render:function(h,i){h=(h===undefined)?(this.fxSpeed):(h);var f=this,g;if(this.model){g=this.renderModel()}else{g=this.renderWithoutModel()}$(f).queue("fx",[function(j){if(h&&f.$el.is(":visible")){f.$el.fadeOut(h,j)}else{j()}},function(j){f.$el.empty();if(g){f.$el.append(g.children())}j()},function(j){if(h&&!f.$el.is(":visible")){f.$el.fadeIn(h,j)}else{j()}},function(j){if(i){i.call(this)}f.trigger("rendered",this);j()}]);return this},renderWithoutModel:function(){var f=$("<div/>"),g=$("<div/>").addClass("message-container").css({"margin-left":"4px","margin-right":"4px"});return f.append(g)},renderModel:function(){var f=$("<div/>");f.append(b.templates.historyPanel(this.model.toJSON()));f.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(f);this.renderHdas(f);return f},_renderSearchButton:function(f){return faIconButton({title:_l("Search datasets"),classes:"history-search-btn",faIcon:"fa-search"})},_setUpBehaviours:function(f){f=f||this.$el;f.find("[title]").tooltip({placement:"bottom"})},createHdaView:function(g){var f=g.get("id"),h=new this.HDAViewClass({model:g,linkTarget:this.linkTarget,expanded:this.storage.get("expandedHdas")[f],hasUser:this.model.ownedByCurrUser(),logger:this.logger});this._setUpHdaListeners(h);return h},_setUpHdaListeners:function(g){var f=this;g.on("body-expanded",function(h){f.storage.addExpandedHda(h)});g.on("body-collapsed",function(h){f.storage.removeExpandedHda(h)});g.on("error",function(i,k,h,j){f.errorHandler(i,k,h,j)})},renderHdas:function(g){g=g||this.$el;var f=this,i={},h=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"),this.filters);g.find(this.datasetsSelector).empty();if(h.length){h.each(function(k){var j=k.get("id"),l=f.createHdaView(k);i[j]=l;if(_.contains(f.selectedHdaIds,j)){l.selected=true}f.attachHdaView(l.render(),g)});g.find(this.emptyMsgSelector).hide()}else{g.find(this.emptyMsgSelector).text((this.model.hdas.length&&this.searchFor)?(this.noneFoundMsg):(this.emptyMsg)).show()}this.hdaViews=i;return this.hdaViews},attachHdaView:function(h,g){g=g||this.$el;var f=g.find(this.datasetsSelector);f.prepend(h.$el)},addHdaView:function(i){this.log("add."+this,i);var g=this;if(!i.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return}$({}).queue([function h(k){var j=g.$el.find(g.emptyMsgSelector);if(j.is(":visible")){j.fadeOut(g.fxSpeed,k)}else{k()}},function f(k){g.scrollToTop();var j=g.$el.find(g.datasetsSelector),l=g.createHdaView(i);g.hdaViews[i.id]=l;l.render().$el.hide().prependTo(j).slideDown(g.fxSpeed)}])},refreshHdas:function(g,f){if(this.model){return this.model.refresh(g,f)}return $.when()},events:{"click .message-container":"clearMessages","click .history-search-btn":"toggleSearchControls"},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(f){f.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.renderHdas();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.renderHdas();return this.storage.get("show_hidden")},setUpSearchInput:function(g){var h=this,k=".history-search-input";function j(l){h.searchFor=l;h.filters=[function(m){return m.matchesAll(h.searchFor)}];h.trigger("search:searching",l,h);h.renderHdas()}function f(l){if(h.model.hdas.haveDetails()){j(l);return}h.$el.find(k).searchInput("toggle-loading");h.model.hdas.fetchAllDetails({silent:true}).always(function(){h.$el.find(k).searchInput("toggle-loading")}).done(function(){j(l)})}function i(){h.searchFor="";h.filters=[];h.trigger("search:clear",h);h.renderHdas()}g.searchInput({initialVal:h.searchFor,name:"history-search",placeholder:"search datasets",classes:"history-search",onfirstsearch:f,onsearch:j,onclear:i});return g},showSearchControls:function(g){g=(g===undefined)?(this.fxSpeed):(g);var f=this.$el.find(".history-search-controls"),h=f.find(".history-search-input");if(!h.children().size()){this.setUpSearchInput(h)}f.slideDown(g,function(){$(this).find("input").focus()})},hideSearchControls:function(f){f=(f===undefined)?(this.fxSpeed):(f);this.$el.find(".history-search-controls").slideUp(f)},toggleSearchControls:function(f){speed=(jQuery.type(f)==="number")?(f):(this.fxSpeed);if(this.$el.find(".history-search-controls").is(":visible")){this.hideSearchControls(speed)}else{this.showSearchControls(speed)}},showLoadingIndicator:function(g,f,h){f=(f!==undefined)?(f):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,h)}else{this.$el.fadeOut(f);this.indicator.show(g,f,h)}},hideLoadingIndicator:function(f,g){f=(f!==undefined)?(f):(this.fxSpeed);if(this.indicator){this.indicator.hide(f,g)}},displayMessage:function(k,l,j){var h=this;this.scrollToTop();var i=this.$el.find(this.msgsSelector),f=$("<div/>").addClass(k+"message").html(l);if(!_.isEmpty(j)){var g=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(h._messageToModalOptions(k,l,j));return false});f.append(" ",g)}return i.html(f)},_messageToModalOptions:function(j,l,i){var f=this,k=$("<div/>"),h={title:"Details"};function g(m){m=_.omit(m,_.functions(m));return["<table>",_.map(m,function(o,n){o=(_.isObject(o))?(g(o)):(o);return'<tr><td style="vertical-align: top; color: grey">'+n+'</td><td style="padding-left: 8px">'+o+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(i)){h.body=k.append(g(i))}else{h.body=k.html(i)}h.buttons={Ok:function(){Galaxy.modal.hide();f.clearMessages()}};return h},clearMessages:function(){var f=this.$el.find(this.msgsSelector);f.empty()},scrollPosition:function(){return this.$el.scrollTop()},scrollTo:function(f){this.$el.scrollTop(f);return this},scrollToTop:function(){this.$el.scrollTop(0);return this},scrollIntoView:function(k,g){if(g===undefined){this.scrollTo(k);return this}var f=window,j=this.$el.parent(),i=$(f).innerHeight(),h=(i/2)-(g/2);this.scrollTo(k-h);return this},scrollToId:function(g){if((!g)||(!this.hdaViews[g])){return this}var f=this.hdaViews[g].$el;this.scrollIntoView(f.offset().top,f.outerHeight());return this},scrollToHid:function(f){var g=this.model.hdas.getByHid(f);if(!g){return this}return this.scrollToId(g.id)},toString:function(){return"ReadOnlyHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});b.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};return{ReadOnlyHistoryPanel:b}});
\ No newline at end of file
+define(["mvc/history/history-model","mvc/dataset/hda-base"],function(e,a){var d=SessionStorageModel.extend({defaults:{expandedHdas:{},show_deleted:false,show_hidden:false},addExpandedHda:function(f){this.save("expandedHdas",_.extend(this.get("expandedHdas"),_.object([f],[true])))},removeExpandedHda:function(f){this.save("expandedHdas",_.omit(this.get("expandedHdas"),f))},toString:function(){return"HistoryPrefs("+this.id+")"}});d.historyStorageKey=function c(f){if(!f){throw new Error("HistoryPrefs.historyStorageKey needs valid id: "+f)}return("history:"+f)};var b=Backbone.View.extend(LoggableMixin).extend({HDAViewClass:a.HDABaseView,tagName:"div",className:"history-panel",fxSpeed:"fast",datasetsSelector:".datasets-list",msgsSelector:".message-container",emptyMsgSelector:".empty-history-message",emptyMsg:_l("This history is empty"),noneFoundMsg:_l("No matching datasets found"),initialize:function(f){f=f||{};if(f.logger){this.logger=f.logger}this.log(this+".initialize:",f);this.linkTarget=f.linkTarget||"_blank";this.fxSpeed=_.has(f,"fxSpeed")?(f.fxSpeed):(this.fxSpeed);this.hdaViews={};this.indicator=new LoadingIndicator(this.$el);this.filters=[];this.searchFor="";this._setUpListeners();if(this.model){if(this.logger){this.model.logger=this.logger}this._setUpWebStorage(f.initiallyExpanded,f.show_deleted,f.show_hidden);this._setUpModelEventHandlers()}if(f.onready){f.onready.call(this)}},_setUpListeners:function(){this.on("error",function(g,j,f,i,h){this.errorHandler(g,j,f,i,h)});this.on("loading-history",function(){this.showLoadingIndicator("loading history...",40)});this.on("loading-done",function(){this.hideLoadingIndicator(40);if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});if(this.logger){this.on("all",function(f){this.log(this+"",arguments)},this)}},errorHandler:function(h,k,g,j,i){var f=this._parseErrorMessage(h,k,g,j,i);if(k&&k.status===0&&k.readyState===0){}else{if(k&&k.status===502){}else{if(!this.$el.find(this.msgsSelector).is(":visible")){this.once("rendered",function(){this.displayMessage("error",f.message,f.details)})}else{this.displayMessage("error",f.message,f.details)}}}},_parseErrorMessage:function(i,m,h,l,k){var g=Galaxy.currUser,f={message:this._bePolite(l),details:{user:(g instanceof User)?(g.toJSON()):(g+""),source:(i instanceof Backbone.Model)?(i.toJSON()):(i+""),xhr:m,options:(m)?(_.omit(h,"xhr")):(h)}};_.extend(f.details,k||{});if(m&&_.isFunction(m.getAllResponseHeaders)){var j=m.getAllResponseHeaders();j=_.compact(j.split("\n"));j=_.map(j,function(n){return n.split(": ")});f.details.xhr.responseHeaders=_.object(j)}return f},_bePolite:function(f){f=f||_l("An error occurred while getting updates from the server");return f+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadHistoryWithHDADetails:function(i,h,g,k){var f=this,j=function(l){return f.getExpandedHdaIds(l.id)};return this.loadHistory(i,h,g,k,j)},loadHistory:function(i,h,g,l,j){this.trigger("loading-history",this);h=h||{};var f=this;var k=e.History.getHistoryData(i,{historyFn:g,hdaFn:l,hdaDetailIds:h.initiallyExpanded||j});return this._loadHistoryFromXHR(k,h).fail(function(o,m,n){f.trigger("error",f,o,h,_l("An error was encountered while "+m),{historyId:i,history:n||{}})}).always(function(){f.trigger("loading-done",f)})},_loadHistoryFromXHR:function(h,g){var f=this;h.then(function(i,j){f.setModel(i,j,g)});h.fail(function(j,i){f.render()});return h},setModel:function(h,f,g){g=g||{};if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.hdaViews={};if(Galaxy&&Galaxy.currUser){h.user=Galaxy.currUser.toJSON()}this.model=new e.History(h,f,g);if(this.logger){this.model.logger=this.logger}this._setUpWebStorage(g.initiallyExpanded,g.show_deleted,g.show_hidden);this._setUpModelEventHandlers();this.selectedHdaIds=[];this.trigger("new-model",this);this.render();return this},_setUpWebStorage:function(g,f,h){this.storage=new d({id:d.historyStorageKey(this.model.get("id"))});if(_.isObject(g)){this.storage.set("exandedHdas",g)}if(_.isBoolean(f)){this.storage.set("show_deleted",f)}if(_.isBoolean(h)){this.storage.set("show_hidden",h)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get())},clearWebStorage:function(){for(var f in sessionStorage){if(f.indexOf("history:")===0){sessionStorage.removeItem(f)}}},getStoredOptions:function(g){if(!g||g==="current"){return(this.storage)?(this.storage.get()):({})}var f=sessionStorage.getItem(d.historyStorageKey(g));return(f===null)?({}):(JSON.parse(f))},getExpandedHdaIds:function(f){var g=this.getStoredOptions(f).expandedHdas;return((_.isEmpty(g))?([]):(_.keys(g)))},_setUpModelEventHandlers:function(){this.model.hdas.on("add",this.addHdaView,this);this.model.on("error error:hdas",function(g,i,f,h){this.errorHandler(g,i,f,h)},this)},render:function(h,i){h=(h===undefined)?(this.fxSpeed):(h);var f=this,g;if(this.model){g=this.renderModel()}else{g=this.renderWithoutModel()}$(f).queue("fx",[function(j){if(h&&f.$el.is(":visible")){f.$el.fadeOut(h,j)}else{j()}},function(j){f.$el.empty();if(g){f.$el.append(g.children())}j()},function(j){if(h&&!f.$el.is(":visible")){f.$el.fadeIn(h,j)}else{j()}},function(j){if(i){i.call(this)}f.trigger("rendered",this);j()}]);return this},renderWithoutModel:function(){var f=$("<div/>"),g=$("<div/>").addClass("message-container").css({"margin-left":"4px","margin-right":"4px"});return f.append(g)},renderModel:function(){var f=$("<div/>");f.append(b.templates.historyPanel(this.model.toJSON()));f.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(f);this.renderHdas(f);return f},_renderSearchButton:function(f){return faIconButton({title:_l("Search datasets"),classes:"history-search-btn",faIcon:"fa-search"})},_setUpBehaviours:function(f){f=f||this.$el;f.find("[title]").tooltip({placement:"bottom"})},createHdaView:function(g){var f=g.get("id"),h=new this.HDAViewClass({model:g,linkTarget:this.linkTarget,expanded:this.storage.get("expandedHdas")[f],hasUser:this.model.ownedByCurrUser(),logger:this.logger});this._setUpHdaListeners(h);return h},_setUpHdaListeners:function(g){var f=this;g.on("body-expanded",function(h){f.storage.addExpandedHda(h)});g.on("body-collapsed",function(h){f.storage.removeExpandedHda(h)});g.on("error",function(i,k,h,j){f.errorHandler(i,k,h,j)})},renderHdas:function(g){g=g||this.$el;var f=this,i={},h=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"),this.filters);g.find(this.datasetsSelector).empty();if(h.length){h.each(function(k){var j=k.get("id"),l=f.createHdaView(k);i[j]=l;if(_.contains(f.selectedHdaIds,j)){l.selected=true}f.attachHdaView(l.render(),g)});g.find(this.emptyMsgSelector).hide()}else{g.find(this.emptyMsgSelector).text((this.model.hdas.length&&this.searchFor)?(this.noneFoundMsg):(this.emptyMsg)).show()}this.hdaViews=i;return this.hdaViews},attachHdaView:function(h,g){g=g||this.$el;var f=g.find(this.datasetsSelector);f.prepend(h.$el)},addHdaView:function(i){this.log("add."+this,i);var g=this;if(!i.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return}$({}).queue([function h(k){var j=g.$el.find(g.emptyMsgSelector);if(j.is(":visible")){j.fadeOut(g.fxSpeed,k)}else{k()}},function f(k){g.scrollToTop();var j=g.$el.find(g.datasetsSelector),l=g.createHdaView(i);g.hdaViews[i.id]=l;l.render().$el.hide().prependTo(j).slideDown(g.fxSpeed)}])},refreshHdas:function(g,f){if(this.model){return this.model.refresh(g,f)}return $.when()},events:{"click .message-container":"clearMessages","click .history-search-btn":"toggleSearchControls"},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(f){f.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.renderHdas();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.renderHdas();return this.storage.get("show_hidden")},setUpSearchInput:function(g){var h=this,k=".history-search-input";function j(l){h.searchFor=l;h.filters=[function(m){return m.matchesAll(h.searchFor)}];h.trigger("search:searching",l,h);h.renderHdas()}function f(l){if(h.model.hdas.haveDetails()){j(l);return}h.$el.find(k).searchInput("toggle-loading");h.model.hdas.fetchAllDetails({silent:true}).always(function(){h.$el.find(k).searchInput("toggle-loading")}).done(function(){j(l)})}function i(){h.searchFor="";h.filters=[];h.trigger("search:clear",h);h.renderHdas()}g.searchInput({initialVal:h.searchFor,name:"history-search",placeholder:"search datasets",classes:"history-search",onfirstsearch:f,onsearch:j,onclear:i});return g},showSearchControls:function(g){g=(g===undefined)?(this.fxSpeed):(g);var f=this.$el.find(".history-search-controls"),h=f.find(".history-search-input");if(!h.children().size()){this.setUpSearchInput(h)}f.slideDown(g,function(){$(this).find("input").focus()})},hideSearchControls:function(f){f=(f===undefined)?(this.fxSpeed):(f);this.$el.find(".history-search-controls").slideUp(f)},toggleSearchControls:function(f){speed=(jQuery.type(f)==="number")?(f):(this.fxSpeed);if(this.$el.find(".history-search-controls").is(":visible")){this.hideSearchControls(speed)}else{this.showSearchControls(speed)}},showLoadingIndicator:function(g,f,h){f=(f!==undefined)?(f):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,h)}else{this.$el.fadeOut(f);this.indicator.show(g,f,h)}},hideLoadingIndicator:function(f,g){f=(f!==undefined)?(f):(this.fxSpeed);if(this.indicator){this.indicator.hide(f,g)}},displayMessage:function(k,l,j){var h=this;this.scrollToTop();var i=this.$el.find(this.msgsSelector),f=$("<div/>").addClass(k+"message").html(l);if(!_.isEmpty(j)){var g=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(h._messageToModalOptions(k,l,j));return false});f.append(" ",g)}return i.html(f)},_messageToModalOptions:function(j,l,i){var f=this,k=$("<div/>"),h={title:"Details"};function g(m){m=_.omit(m,_.functions(m));return["<table>",_.map(m,function(o,n){o=(_.isObject(o))?(g(o)):(o);return'<tr><td style="vertical-align: top; color: grey">'+n+'</td><td style="padding-left: 8px">'+o+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(i)){h.body=k.append(g(i))}else{h.body=k.html(i)}h.buttons={Ok:function(){Galaxy.modal.hide();f.clearMessages()}};return h},clearMessages:function(){var f=this.$el.find(this.msgsSelector);f.empty()},scrollPosition:function(){return this.$el.scrollTop()},scrollTo:function(f){this.$el.scrollTop(f);return this},scrollToTop:function(){this.$el.scrollTop(0);return this},scrollIntoView:function(k,g){if(g===undefined){this.scrollTo(k);return this}var f=window,j=this.$el.parent(),i=$(f).innerHeight(),h=(i/2)-(g/2);this.scrollTo(k-h);return this},scrollToId:function(g){if((!g)||(!this.hdaViews[g])){return this}var f=this.hdaViews[g].$el;this.scrollIntoView(f.offset().top,f.outerHeight());return this},scrollToHid:function(f){var g=this.model.hdas.getByHid(f);if(!g){return this}return this.scrollToId(g.id)},toString:function(){return"ReadOnlyHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});b.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};return{ReadOnlyHistoryPanel:b}});
\ No newline at end of file
diff -r 6b6c7de6bbe10721674f50ebb5e8a600d8586416 -r 2403d6f67500ec35b16ce604142d98766286b65a static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1652,7 +1652,7 @@
.history-panel .message-container{cursor:pointer}
.history-panel .message-container [class$=message]{margin:0px;margin-bottom:8px}
.history-panel .history-controls{margin:10px;padding:0px}.history-panel .history-controls .history-search-controls{display:none;padding:0px 0px 8px 0px}
-.history-panel .history-controls .history-title{margin-bottom:4px}
+.history-panel .history-controls .history-title{margin-bottom:8px}
.history-panel .history-controls .history-name{word-wrap:break-word;font-weight:bold}
.history-panel .history-controls .history-title input{width:100%;margin:-2px 0 -2px -4px;font-weight:bold}
.history-panel .history-controls .history-subtitle{margin-bottom:8px}
@@ -1688,8 +1688,8 @@
.dataset.state-discarded{background:#eee}.dataset.state-discarded .state-icon:before{content:"\f014"}
.dataset.state-noPermission{background:#eee;filter:alpha(opacity=60);-moz-opacity:.60;opacity:.60}.dataset.state-noPermission .state-icon{font-size:20px}.dataset.state-noPermission .state-icon:before{content:"\f023"}
.dataset.state-new{background:#eee}.dataset.state-new .state-icon:before{content:"\f06a"}
-.annotated-history-panel{padding-top:10px}.annotated-history-panel [class$=messagesmall]{margin:8px 0px 8px 0px}
-.annotated-history-panel .history-controls{margin:0px 0px 16px 4px;padding:0px}.annotated-history-panel .history-controls .history-name{font-size:150%}
+.annotated-history-panel [class$=messagesmall]{margin:8px 0px 8px 0px}
+.annotated-history-panel .history-controls{margin:0px 0px 16px 4px;padding:0px}.annotated-history-panel .history-controls .history-name{font-size:150%;margin-bottom:4px}
.annotated-history-panel .history-controls .history-subtitle{margin:0px;padding:0px 0px 0px 4px;padding-left:4px}
.annotated-history-panel .history-controls .history-annotation{border:1px solid lightgrey;border-width:1px 0px 0px 0px;padding:4px 0px 4px 0px;margin:4px;white-space:pre-wrap}
.annotated-history-panel .history-controls .history-annotation:empty{display:none}
diff -r 6b6c7de6bbe10721674f50ebb5e8a600d8586416 -r 2403d6f67500ec35b16ce604142d98766286b65a static/style/src/less/history.less
--- a/static/style/src/less/history.less
+++ b/static/style/src/less/history.less
@@ -411,7 +411,7 @@
}
.history-title {
- margin-bottom: 4px;
+ margin-bottom: 8px;
}
.history-name {
word-wrap: break-word;
@@ -692,7 +692,6 @@
.annotated-history-panel {
//TODO: most of these styles are specific to history/display.mako and not to this type of panel in general
//TODO: some of these styles are also overrides of history-panel - remove those from hpanel and revisit this
- padding-top: 10px;
[class$=messagesmall] {
margin: 8px 0px 8px 0px;
@@ -704,6 +703,7 @@
.history-name {
font-size: 150%;
+ margin-bottom: 4px;
}
.history-subtitle {
margin: 0px;
diff -r 6b6c7de6bbe10721674f50ebb5e8a600d8586416 -r 2403d6f67500ec35b16ce604142d98766286b65a templates/display_base.mako
--- a/templates/display_base.mako
+++ b/templates/display_base.mako
@@ -36,7 +36,8 @@
${h.js( "libs/jquery/jstorage", "libs/jquery/jquery.autocomplete", "libs/jquery/jquery.rating",
"galaxy.autocom_tagging" )}
${history_panel_javascripts()}
- ${h.js( "galaxy.panels", "libs/jquery/jstorage", "libs/jquery/jquery.event.drag", "libs/jquery/jquery.event.hover","libs/jquery/jquery.mousewheel", "libs/jquery/jquery-ui", "libs/require", "libs/farbtastic" )}
+ ${h.js( "galaxy.panels", "libs/jquery/jstorage", "libs/jquery/jquery.event.drag", "libs/jquery/jquery.event.hover",
+ "libs/jquery/jquery.mousewheel", "libs/jquery/jquery-ui", "libs/require", "libs/farbtastic" )}
<script type="text/javascript">
@@ -152,18 +153,6 @@
border-right-style: solid;
border-right-color: #66AA66;
}
-
- .embedded-item.history .item-content {
- padding: 8px;
- background-color: white;
- border-radius: 0px 0px 4px 4px;
- }
- .embedded-item.history hr {
- margin-bottom: 2px;
- }
- .embedded-item.history .history-panel {
- padding: 2px 0px 8px 0px;
- }
</style></%def>
diff -r 6b6c7de6bbe10721674f50ebb5e8a600d8586416 -r 2403d6f67500ec35b16ce604142d98766286b65a templates/webapps/galaxy/history/display.mako
--- a/templates/webapps/galaxy/history/display.mako
+++ b/templates/webapps/galaxy/history/display.mako
@@ -15,6 +15,9 @@
<%def name="stylesheets()">
${parent.stylesheets()}
<style type="text/css">
+ .history-panel {
+ margin-top: 8px;
+ }
</style></%def>
@@ -48,7 +51,7 @@
historyJSON = ${h.to_json_string( history_dict )},
hdaJSON = ${h.to_json_string( hda_dicts )};
//window.historyJSON = historyJSON;
- window.hdaJSON = hdaJSON;
+ //window.hdaJSON = hdaJSON;
require.config({
baseUrl : "${h.url_for( '/static/scripts' )}"
diff -r 6b6c7de6bbe10721674f50ebb5e8a600d8586416 -r 2403d6f67500ec35b16ce604142d98766286b65a templates/webapps/galaxy/history/embed.mako
--- a/templates/webapps/galaxy/history/embed.mako
+++ b/templates/webapps/galaxy/history/embed.mako
@@ -1,13 +1,73 @@
-<%inherit file="/embed_base.mako"/>
-<%!
- from galaxy.web.framework.helpers import iff
+##<%inherit file="/embed_base.mako"/>
+<%namespace file="/display_common.mako" import="*" />
+
+## Some duplication with embed_base here, needed a way to override the main embedded-item html for histories
+<%
+ encoded_history_id = trans.security.encode_id( item.id )
+ import_href = h.url_for( controller='history', action='imp', id=encoded_history_id )
+ display_href = h.url_for( controller='history', action='display_by_username_and_slug',
+ username=item.user.username, slug=item.slug )
%>
+<div id="history-${encoded_history_id}" class='embedded-item display history'>
+ <div class='title'>
+ <div style="float: left">
+ <a class="expand-content-btn icon-button toggle-expand" href="${display_href}"
+ title="Show or hide history contents"></a>
+ </div>
+ <div style="float: right;">
+ <a title="Import history" class="icon-button import" href="${import_href}"></a>
+ <a title="View history" class="icon-button go-to-full-screen" href="${display_href}"></a>
+ </div>
+ <h4>
+ <a class="toggle-embed" href="${display_href}" title="Show or hide history contents">
+ Galaxy History | ${get_item_name( item )}
+ </a>
+ </h4>
+ %if hasattr( item, "annotation") and item.annotation:
+ <div class="annotation">${item.annotation}</div>
+ %endif
+ </div>
+ <div class='summary-content'>
+ ## currently, no summary content for history
+ </div>
+ <div class='expanded-content'>
+ <div class='item-content'>
+ <div class='history-panel'></div>
+ </div>
+ </div>
+</div>
-<%def name="render_summary_content( history, datasets )">
+<script type="text/javascript">
-## <ul>
-## <% num_datasets = len ( datasets ) %>
-## <li>${num_datasets} dataset${iff( num_datasets != 1, "s", "" )}
-## <li>Operations: ...
-## </ul>
-</%def>
+require.config({
+ baseUrl : "${h.url_for( '/static/scripts' )}"
+});
+require([ 'mvc/history/annotated-history-panel' ], function( panelMod ){
+
+ function toggleExpanded( ev ){
+ var $embeddedHistory = $( "#history-${encoded_history_id}" );
+ $embeddedHistory.find( '.expand-content-btn' ).toggleClass( 'toggle-expand' ).toggleClass( 'toggle' );
+ $embeddedHistory.find( ".summary-content" ).slideToggle( "fast" );
+ $embeddedHistory.find( ".annotation" ).slideToggle( "fast" );
+ $embeddedHistory.find( ".expanded-content" ).slideToggle( "fast" );
+ ev.preventDefault();
+ }
+
+ $(function(){
+ var debugging = JSON.parse( sessionStorage.getItem( 'debugging' ) ) || false,
+ historyModel = require( 'mvc/history/history-model' ),
+ $embeddedHistory = $( "#history-${encoded_history_id}" ),
+ panel = new panelMod.AnnotatedHistoryPanel({
+ el : $embeddedHistory.find( ".history-panel" ),
+ model : new historyModel.History(
+ ${h.to_json_string( history_dict )},
+ ${h.to_json_string( hda_dicts )},
+ { logger: ( debugging )?( console ):( null ) }
+ )
+ }).render();
+
+ $embeddedHistory.find( '.expand-content-btn' ).click( toggleExpanded );
+ $embeddedHistory.find( '.toggle-embed' ).click( toggleExpanded );
+ });
+});
+</script>
diff -r 6b6c7de6bbe10721674f50ebb5e8a600d8586416 -r 2403d6f67500ec35b16ce604142d98766286b65a templates/webapps/galaxy/page/display.mako
--- a/templates/webapps/galaxy/page/display.mako
+++ b/templates/webapps/galaxy/page/display.mako
@@ -5,12 +5,12 @@
<script type="text/javascript">
$(function() {
-
// Setup embedded content:
// (a) toggles for showing/hiding embedded content;
// (b) ...
$('.embedded-item').each( function() {
var container = $(this);
+ if( container.hasClass( 'history' ) ){ return; }
// Show embedded item.
var show_embedded_item = function() {
@@ -88,9 +88,12 @@
<%def name="stylesheets()">
${parent.stylesheets()}
- ${h.css( "base", "history", "autocomplete_tagging" )}
+ ${h.css( "base", "autocomplete_tagging" )}
<style type="text/css">
.toggle { display: none; }
+ .embedded-item .title {
+ padding-top: 1px;
+ }
.embedded-item h4 {
margin: 0px;
}
@@ -119,6 +122,30 @@
.embedded-item .trackster-nav {
position: inherit;
}
+
+ /* ---------------------------- histories */
+ .embedded-item.history .toggle {
+ display: inline;
+ }
+ .embedded-item.history .expanded-content {
+ /* generates a fake wide border */
+ padding: 4px;
+ }
+ /** wraps around the history */
+ .embedded-item.history .item-content {
+ background-color: white;
+ padding: 8px;
+ border-radius: 0px 0px 4px 4px;
+ }
+ .embedded-item.history .history-panel .datasets-list {
+ margin-bottom: 8px;
+ }
+ .embedded-item.history .history-panel .errormessage {
+ margin-top: 8px;
+ }
+ .annotated-history-panel .history-controls {
+ margin: 0px 0px 16px 0px;
+ }
</style></%def>
@@ -131,4 +158,4 @@
<%def name="render_item( page, page_data=None )">
${page_data}
-</%def>
\ No newline at end of file
+</%def>
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/c80947795972/
Changeset: c80947795972
Branch: stable
User: jeremy goecks
Date: 2014-02-21 22:57:59
Summary: Fix styles for embedded objects in Pages; these were broken during the last style upgrade.
Affected #: 3 files
diff -r dfcae0da21f7c3885f92c478bc0a44ba75f5f8b6 -r c809477959724304e2342ed5fbdba9d4b412b347 static/style/blue/embed_item.css
--- a/static/style/blue/embed_item.css
+++ b/static/style/blue/embed_item.css
@@ -1,5 +1,5 @@
.embedded-item{margin:0em auto;width:90%;-moz-border-radius:0.5em;-webkit-border-radius:0.5em;border-radius:0.5em}
-.embedded-item.display{padding:2px}
+.embedded-item.display{padding:5px 10px 10px 10px}
.embedded-item.history{background-color:#c1c9e5}
.embedded-item.history p{background:#c1c9e5 no-repeat 2px 2px;margin-top:0;margin-bottom:0}
.embedded-item.dataset{background-color:#cfc}
@@ -8,10 +8,10 @@
.embedded-item.workflow p{background:#fbddb3 no-repeat 2px 2px;margin-top:0;margin-bottom:0}
.embedded-item.visualization{background-color:#bbb}
.embedded-item.visualization p{background:#bbb no-repeat 2px 2px;margin-top:0;margin-bottom:0}
-.embedded-item .expanded-content{display:none}
+.embedded-item .expanded-content{display:none;background-color:white;padding:5px}
.embedded-item .item-content{max-height:25em;overflow:auto}
.embedded-item.visualization .item-content{overflow:hidden}
-.embedded-item .title{vertical-align:top;text-align:center;font-weight:bold;padding-bottom:2px}
+.embedded-item .title{vertical-align:top;text-align:center;font-weight:bold;padding-bottom:5px}
.embedded-item.placeholder .content{padding:0.5em 0.5em;font-style:italic;text-align:center}
table.annotated-item{width:100%;border-collapse:collapse}
table.annotated-item td,th{padding:0}
diff -r dfcae0da21f7c3885f92c478bc0a44ba75f5f8b6 -r c809477959724304e2342ed5fbdba9d4b412b347 static/style/src/less/embed_item.less
--- a/static/style/src/less/embed_item.less
+++ b/static/style/src/less/embed_item.less
@@ -7,7 +7,7 @@
}
.embedded-item.display {
- padding: 2px;
+ padding: 5px 10px 10px 10px;
}
.embedded-item.history {
@@ -53,6 +53,8 @@
.embedded-item .expanded-content {
display: none;
+ background-color: white;
+ padding: 5px;
}
.embedded-item .item-content {
@@ -68,7 +70,7 @@
vertical-align: top;
text-align: center;
font-weight: bold;
- padding-bottom: 2px;
+ padding-bottom: 5px;
}
.embedded-item.placeholder .content {
diff -r dfcae0da21f7c3885f92c478bc0a44ba75f5f8b6 -r c809477959724304e2342ed5fbdba9d4b412b347 templates/embed_base.mako
--- a/templates/embed_base.mako
+++ b/templates/embed_base.mako
@@ -14,7 +14,6 @@
${self.render_summary_content( item, item_data )}
</div><div class='expanded-content'>
- <hr/><div class='item-content'></div></div></div>
https://bitbucket.org/galaxy/galaxy-central/commits/6b6c7de6bbe1/
Changeset: 6b6c7de6bbe1
User: jeremy goecks
Date: 2014-02-21 22:58:46
Summary: Automated merge of stable branch to default.
Affected #: 3 files
diff -r 1beac989dac959139f421353a5f33f53c1e78d96 -r 6b6c7de6bbe10721674f50ebb5e8a600d8586416 static/style/blue/embed_item.css
--- a/static/style/blue/embed_item.css
+++ b/static/style/blue/embed_item.css
@@ -1,5 +1,5 @@
.embedded-item{margin:0em auto;width:90%;-moz-border-radius:0.5em;-webkit-border-radius:0.5em;border-radius:0.5em}
-.embedded-item.display{padding:2px}
+.embedded-item.display{padding:5px 10px 10px 10px}
.embedded-item.history{background-color:#c1c9e5}
.embedded-item.history p{background:#c1c9e5 no-repeat 2px 2px;margin-top:0;margin-bottom:0}
.embedded-item.dataset{background-color:#cfc}
@@ -8,10 +8,10 @@
.embedded-item.workflow p{background:#fbddb3 no-repeat 2px 2px;margin-top:0;margin-bottom:0}
.embedded-item.visualization{background-color:#bbb}
.embedded-item.visualization p{background:#bbb no-repeat 2px 2px;margin-top:0;margin-bottom:0}
-.embedded-item .expanded-content{display:none}
+.embedded-item .expanded-content{display:none;background-color:white;padding:5px}
.embedded-item .item-content{max-height:25em;overflow:auto}
.embedded-item.visualization .item-content{overflow:hidden}
-.embedded-item .title{vertical-align:top;text-align:center;font-weight:bold;padding-bottom:2px}
+.embedded-item .title{vertical-align:top;text-align:center;font-weight:bold;padding-bottom:5px}
.embedded-item.placeholder .content{padding:0.5em 0.5em;font-style:italic;text-align:center}
table.annotated-item{width:100%;border-collapse:collapse}
table.annotated-item td,th{padding:0}
diff -r 1beac989dac959139f421353a5f33f53c1e78d96 -r 6b6c7de6bbe10721674f50ebb5e8a600d8586416 static/style/src/less/embed_item.less
--- a/static/style/src/less/embed_item.less
+++ b/static/style/src/less/embed_item.less
@@ -7,7 +7,7 @@
}
.embedded-item.display {
- padding: 2px;
+ padding: 5px 10px 10px 10px;
}
.embedded-item.history {
@@ -53,6 +53,8 @@
.embedded-item .expanded-content {
display: none;
+ background-color: white;
+ padding: 5px;
}
.embedded-item .item-content {
@@ -68,7 +70,7 @@
vertical-align: top;
text-align: center;
font-weight: bold;
- padding-bottom: 2px;
+ padding-bottom: 5px;
}
.embedded-item.placeholder .content {
diff -r 1beac989dac959139f421353a5f33f53c1e78d96 -r 6b6c7de6bbe10721674f50ebb5e8a600d8586416 templates/embed_base.mako
--- a/templates/embed_base.mako
+++ b/templates/embed_base.mako
@@ -14,7 +14,6 @@
${self.render_summary_content( item, item_data )}
</div><div class='expanded-content'>
- <hr/><div class='item-content'></div></div></div>
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: davebgx: Fix the install database connection specification for the install and test framework.
by commits-noreply@bitbucket.org 21 Feb '14
by commits-noreply@bitbucket.org 21 Feb '14
21 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/1beac989dac9/
Changeset: 1beac989dac9
User: davebgx
Date: 2014-02-21 22:05:53
Summary: Fix the install database connection specification for the install and test framework.
Affected #: 2 files
diff -r 0a35b28844159fd534e49bbb71c0ab00c4dfb367 -r 1beac989dac959139f421353a5f33f53c1e78d96 test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py
@@ -66,6 +66,11 @@
default_galaxy_test_file_dir = "test-data"
os.environ[ 'GALAXY_INSTALL_TEST_TMP_DIR' ] = galaxy_test_tmp_dir
+# Use separate databases for Galaxy and tool shed install info by default,
+# set GALAXY_TEST_INSTALL_DB_MERGED to True to revert to merged databases
+# behavior.
+default_install_db_merged = False
+
# This script can be run in such a way that no Tool Shed database records should be changed.
if '-info_only' in sys.argv or 'GALAXY_INSTALL_TEST_INFO_ONLY' in os.environ:
can_update_tool_shed = False
@@ -421,9 +426,9 @@
if 'GALAXY_INSTALL_TEST_INSTALL_DBURI' in os.environ:
install_database_connection = os.environ[ 'GALAXY_INSTALL_TEST_INSTALL_DBURI' ]
elif asbool( os.environ.get( 'GALAXY_TEST_INSTALL_DB_MERGED', default_install_db_merged ) ):
- install_database_connection = galaxy_database_connection
+ install_database_connection = database_connection
else:
- install_db_path = os.path.join( galaxy_db_path, 'install.sqlite' )
+ install_galaxy_db_path = os.path.join( galaxy_db_path, 'install.sqlite' )
install_database_connection = 'sqlite:///%s' % install_galaxy_db_path
kwargs = {}
for dir in [ galaxy_test_tmp_dir ]:
diff -r 0a35b28844159fd534e49bbb71c0ab00c4dfb367 -r 1beac989dac959139f421353a5f33f53c1e78d96 test/install_and_test_tool_shed_repositories/tool_dependency_definitions/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/tool_dependency_definitions/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/tool_dependency_definitions/functional_tests.py
@@ -65,6 +65,11 @@
default_galaxy_test_file_dir = "test-data"
os.environ[ 'GALAXY_INSTALL_TEST_TMP_DIR' ] = galaxy_test_tmp_dir
+# Use separate databases for Galaxy and tool shed install info by default,
+# set GALAXY_TEST_INSTALL_DB_MERGED to True to revert to merged databases
+# behavior.
+default_install_db_merged = False
+
# This script can be run in such a way that no Tool Shed database records should be changed.
if '-info_only' in sys.argv or 'GALAXY_INSTALL_TEST_INFO_ONLY' in os.environ:
can_update_tool_shed = False
@@ -273,9 +278,9 @@
if 'GALAXY_INSTALL_TEST_INSTALL_DBURI' in os.environ:
install_database_connection = os.environ[ 'GALAXY_INSTALL_TEST_INSTALL_DBURI' ]
elif asbool( os.environ.get( 'GALAXY_TEST_INSTALL_DB_MERGED', default_install_db_merged ) ):
- install_database_connection = galaxy_database_connection
+ install_database_connection = database_connection
else:
- install_db_path = os.path.join( galaxy_db_path, 'install.sqlite' )
+ install_galaxy_db_path = os.path.join( galaxy_db_path, 'install.sqlite' )
install_database_connection = 'sqlite:///%s' % install_galaxy_db_path
kwargs = {}
for dir in [ galaxy_test_tmp_dir ]:
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: Fix Python 2.7ism in test_evaluation.py.
by commits-noreply@bitbucket.org 21 Feb '14
by commits-noreply@bitbucket.org 21 Feb '14
21 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0a35b2884415/
Changeset: 0a35b2884415
User: jmchilton
Date: 2014-02-21 21:57:09
Summary: Fix Python 2.7ism in test_evaluation.py.
Affected #: 1 file
diff -r c5be84ef148e7866bfe31610cea5c9f1bae09fe0 -r 0a35b28844159fd534e49bbb71c0ab00c4dfb367 test/unit/tools/test_evaluation.py
--- a/test/unit/tools/test_evaluation.py
+++ b/test/unit/tools/test_evaluation.py
@@ -168,7 +168,7 @@
if "new_file_path" not in kwds:
kwds[ "new_file_path" ] = self.app.config.new_file_path
self.evaluator.set_compute_environment( TestComputeEnviornment( **kwds ) )
- self.assertIn( "exec_before_job", self.tool.hooks_called )
+ assert "exec_before_job" in self.tool.hooks_called
def _setup_test_bwa_job( self ):
self.job.input_datasets = [ self._job_dataset( 'input1', '/galaxy/files/dataset_1.dat' ) ]
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