galaxy-commits
Threads by month
- ----- 2024 -----
- 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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5dac6a566615/
Changeset: 5dac6a566615
User: jeremy goecks
Date: 2014-02-28 22:18:05
Summary: Add header and line demarcation to tabular chunked data view.
Affected #: 1 file
diff -r edff37d76463a468753477080f65886d4a53619e -r 5dac6a566615bf747a8515f72ec21be15957647f static/scripts/mvc/data.js
--- a/static/scripts/mvc/data.js
+++ b/static/scripts/mvc/data.js
@@ -115,23 +115,29 @@
*/
var TabularDatasetChunkedView = Backbone.View.extend({
- initialize: function(options)
- {
+ initialize: function(options) {
+ // Row count for rendering.
+ this.row_count = 0;
+
+ // CSS colors used in table.
+ this.header_color = '#AAA';
+ this.dark_row_color = '#DDD';
+
// load trackster button
new TabularButtonTracksterView(options);
},
- render: function()
- {
+ render: function() {
// Add data table and header.
var data_table = $('<table/>').attr({
id: 'content_table',
cellpadding: 0
});
this.$el.append(data_table);
- var column_names = this.model.get_metadata('column_names');
+ var column_names = this.model.get_metadata('column_names'),
+ header_row = $('<tr/>').css('background-color', this.header_color).appendTo(data_table);
if (column_names) {
- data_table.append('<tr><th>' + column_names.join('</th><th>') + '</th></tr>');
+ header_row.append('<th>' + column_names.join('</th><th>') + '</th>');
}
// Add first chunk.
@@ -199,6 +205,11 @@
var cells = line.split('\t'),
row = $('<tr>'),
num_columns = this.model.get_metadata('columns');
+
+ if (this.row_count % 2 !== 0) {
+ row.css('background-color', this.dark_row_color);
+ }
+
if (cells.length === num_columns) {
_.each(cells, function(cell_contents, index) {
row.append(this._renderCell(cell_contents, index));
@@ -222,6 +233,8 @@
// Comment line, just return the one cell.
row.append(this._renderCell(line, 0, num_columns));
}
+
+ this.row_count++;
return row;
},
https://bitbucket.org/galaxy/galaxy-central/commits/eafb4208db66/
Changeset: eafb4208db66
User: jeremy goecks
Date: 2014-02-28 23:03:52
Summary: Automated merge
Affected #: 2 files
diff -r 5dac6a566615bf747a8515f72ec21be15957647f -r eafb4208db665dfeed7d8f3e6f0d2b61ce2f4fc8 test/unit/tools/test_select_parameters.py
--- a/test/unit/tools/test_select_parameters.py
+++ b/test/unit/tools/test_select_parameters.py
@@ -48,6 +48,24 @@
self.options_xml = '''<options><filter type="data_meta" ref="input_bam" key="dbkey"/></options>'''
assert self.param.need_late_validation( self.trans, { "series": [ { "my_name": "42", "input_bam": basic.RuntimeValue() } ] } )
+ def test_filter_param_value( self ):
+ self.options_xml = '''<options from_data_table="test_table"><filter type="param_value" ref="input_bam" column="0" /></options>'''
+ assert ("testname1", "testpath1", False) in self.param.get_options( self.trans, { "input_bam": "testname1" } )
+ assert ("testname2", "testpath2", False) in self.param.get_options( self.trans, { "input_bam": "testname2" } )
+ assert len( self.param.get_options( self.trans, { "input_bam": "testname3" } ) ) == 0
+
+ def test_filter_param_value2( self ):
+ # Same test as above, but filtering on a different column.
+ self.options_xml = '''<options from_data_table="test_table"><filter type="param_value" ref="input_bam" column="1" /></options>'''
+ assert ("testname1", "testpath1", False) in self.param.get_options( self.trans, { "input_bam": "testpath1" } )
+ assert ("testname2", "testpath2", False) in self.param.get_options( self.trans, { "input_bam": "testpath2" } )
+ assert len( self.param.get_options( self.trans, { "input_bam": "testpath3" } ) ) == 0
+
+ def test_filter_nested( self ):
+ # Test filtering a parameter inside a conditional (not currently supported.)
+ self.options_xml = '''<options from_data_table="test_table"><filter type="param_value" ref="input_bam" column="1" /></options>'''
+ assert ("testname1", "testpath1", False) in self.param.get_options( self.trans, {"condtional1" : { "input_bam": "testpath1", "my_name": 42 } } )
+
# TODO: Good deal of overlap here with DataToolParameterTestCase,
# refactor.
def setUp( self ):
@@ -59,6 +77,7 @@
self.test_history = model.History()
self.app.model.context.add( self.test_history )
self.app.model.context.flush()
+ self.app.tool_data_tables[ "test_table" ] = MockToolDataTable()
self.trans = bunch.Bunch(
app=self.app,
get_history=lambda: self.test_history,
@@ -91,3 +110,16 @@
self._param = basic.SelectToolParameter( self.mock_tool, self.param_xml )
return self._param
+
+
+class MockToolDataTable( object ):
+
+ def __init__( self ):
+ self.columns = dict(
+ name=0,
+ value=1,
+ )
+ self.missing_index_file = None
+
+ def get_fields( self ):
+ return [ [ "testname1", "testpath1" ], [ "testname2", "testpath2" ] ]
diff -r 5dac6a566615bf747a8515f72ec21be15957647f -r eafb4208db665dfeed7d8f3e6f0d2b61ce2f4fc8 test/unit/tools_support.py
--- a/test/unit/tools_support.py
+++ b/test/unit/tools_support.py
@@ -121,6 +121,7 @@
from galaxy.security import GalaxyRBACAgent
self.job_queue = NoopQueue()
self.security_agent = GalaxyRBACAgent( self.model )
+ self.tool_data_tables = {}
class MockContext(object):
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: Test cases for filtering tool parameters on other parameter values.
by commits-noreply@bitbucket.org 28 Feb '14
by commits-noreply@bitbucket.org 28 Feb '14
28 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/01933aab375c/
Changeset: 01933aab375c
User: jmchilton
Date: 2014-02-28 21:49:46
Summary: Test cases for filtering tool parameters on other parameter values.
Includes test case that is broken without JJ's contributions in pull request #343.
Affected #: 2 files
diff -r edff37d76463a468753477080f65886d4a53619e -r 01933aab375c87302106e851a77e425e51d0394a test/unit/tools/test_select_parameters.py
--- a/test/unit/tools/test_select_parameters.py
+++ b/test/unit/tools/test_select_parameters.py
@@ -48,6 +48,24 @@
self.options_xml = '''<options><filter type="data_meta" ref="input_bam" key="dbkey"/></options>'''
assert self.param.need_late_validation( self.trans, { "series": [ { "my_name": "42", "input_bam": basic.RuntimeValue() } ] } )
+ def test_filter_param_value( self ):
+ self.options_xml = '''<options from_data_table="test_table"><filter type="param_value" ref="input_bam" column="0" /></options>'''
+ assert ("testname1", "testpath1", False) in self.param.get_options( self.trans, { "input_bam": "testname1" } )
+ assert ("testname2", "testpath2", False) in self.param.get_options( self.trans, { "input_bam": "testname2" } )
+ assert len( self.param.get_options( self.trans, { "input_bam": "testname3" } ) ) == 0
+
+ def test_filter_param_value2( self ):
+ # Same test as above, but filtering on a different column.
+ self.options_xml = '''<options from_data_table="test_table"><filter type="param_value" ref="input_bam" column="1" /></options>'''
+ assert ("testname1", "testpath1", False) in self.param.get_options( self.trans, { "input_bam": "testpath1" } )
+ assert ("testname2", "testpath2", False) in self.param.get_options( self.trans, { "input_bam": "testpath2" } )
+ assert len( self.param.get_options( self.trans, { "input_bam": "testpath3" } ) ) == 0
+
+ def test_filter_nested( self ):
+ # Test filtering a parameter inside a conditional (not currently supported.)
+ self.options_xml = '''<options from_data_table="test_table"><filter type="param_value" ref="input_bam" column="1" /></options>'''
+ assert ("testname1", "testpath1", False) in self.param.get_options( self.trans, {"condtional1" : { "input_bam": "testpath1", "my_name": 42 } } )
+
# TODO: Good deal of overlap here with DataToolParameterTestCase,
# refactor.
def setUp( self ):
@@ -59,6 +77,7 @@
self.test_history = model.History()
self.app.model.context.add( self.test_history )
self.app.model.context.flush()
+ self.app.tool_data_tables[ "test_table" ] = MockToolDataTable()
self.trans = bunch.Bunch(
app=self.app,
get_history=lambda: self.test_history,
@@ -91,3 +110,16 @@
self._param = basic.SelectToolParameter( self.mock_tool, self.param_xml )
return self._param
+
+
+class MockToolDataTable( object ):
+
+ def __init__( self ):
+ self.columns = dict(
+ name=0,
+ value=1,
+ )
+ self.missing_index_file = None
+
+ def get_fields( self ):
+ return [ [ "testname1", "testpath1" ], [ "testname2", "testpath2" ] ]
diff -r edff37d76463a468753477080f65886d4a53619e -r 01933aab375c87302106e851a77e425e51d0394a test/unit/tools_support.py
--- a/test/unit/tools_support.py
+++ b/test/unit/tools_support.py
@@ -121,6 +121,7 @@
from galaxy.security import GalaxyRBACAgent
self.job_queue = NoopQueue()
self.security_agent = GalaxyRBACAgent( self.model )
+ self.tool_data_tables = {}
class MockContext(object):
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: jeremy goecks: Trackster: replace custom config settings model and view with generic model/view from config.js. Improvements for generic config model/view. Whitespace fixes.
by commits-noreply@bitbucket.org 28 Feb '14
by commits-noreply@bitbucket.org 28 Feb '14
28 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/edff37d76463/
Changeset: edff37d76463
User: jeremy goecks
Date: 2014-02-28 21:27:59
Summary: Trackster: replace custom config settings model and view with generic model/view from config.js. Improvements for generic config model/view. Whitespace fixes.
Affected #: 4 files
diff -r e059dbc01b575b856509c2e2baccac3750b6eeb5 -r edff37d76463a468753477080f65886d4a53619e static/scripts/utils/config.js
--- a/static/scripts/utils/config.js
+++ b/static/scripts/utils/config.js
@@ -16,9 +16,14 @@
this.set(_.extend({}, defaults, options));
}
- // If type color and no value, get random color.
- if (this.get('type') === 'color' && !this.get('value')) {
- this.set('value', util_mod.get_random_color());
+ if (!this.get('value')) {
+ if (this.get('type') === 'color') {
+ // For color setting, set random color.
+ this.set('value', util_mod.get_random_color());
+ }
+ else {
+ this.set_value(this.get('default_value'));
+ }
}
},
@@ -90,23 +95,49 @@
}
return undefined;
- }
+ },
+
+ /**
+ * Set value for a setting.
+ */
+ set_value: function(key, value) {
+ var s = this.get(key);
+ if (s) {
+ return s.set_value(value);
+ }
+
+ return undefined;
+ },
+
+ /**
+ * Set default value for a setting.
+ */
+ set_default_value: function(key, default_value) {
+ var s = this.get(key);
+ if (s) {
+ return s.set('default_value', default_value);
+ }
+
+ return undefined;
+ }
},
{
/**
- * Utility function that creates a ConfigSettingsCollection from a standard dictionary
- * with configuration key-value pairs.
+ * Utility function that creates a ConfigSettingsCollection from a set of models
+ * and a saved_values dictionary.
*/
- from_config_dict: function(config_dict) {
- // Create a list of key-value dicts suitable for sending to a collection.
- var settings_list = _.map(_.keys(config_dict), function(key) {
- return {
- key: key,
- value: config_dict[key]
- };
- });
-
- return new ConfigSettingCollection(settings_list);
+ from_models_and_saved_values: function(models, saved_values) {
+ // Update models with saved values.
+ if (saved_values) {
+ _.each(models, function(m) {
+ if (saved_values[m.key]) {
+ // Found saved value, so update model.
+ m.value = saved_values[m.key];
+ }
+ });
+ }
+
+ return new ConfigSettingCollection(models);
}
});
@@ -265,7 +296,7 @@
var id = 'param_' + index;
var value = self.$el.find( '#' + id ).val();
if ( setting.get('type') === 'bool' ) {
- value = container.find( '#' + id ).is( ':checked' );
+ value = self.$el.find( '#' + id ).is( ':checked' );
}
setting.set_value(value);
}
diff -r e059dbc01b575b856509c2e2baccac3750b6eeb5 -r edff37d76463a468753477080f65886d4a53619e static/scripts/viz/trackster.js
--- a/static/scripts/viz/trackster.js
+++ b/static/scripts/viz/trackster.js
@@ -199,7 +199,7 @@
init_editor : function ()
{
// set title
- $("#center .unified-panel-title").text(view.prefs.name + " (" + view.dbkey + ")");
+ $("#center .unified-panel-title").text(view.config.get_value('name') + " (" + view.dbkey + ")");
// add dataset
if (galaxy_config.app.add_dataset)
@@ -208,7 +208,7 @@
data: { hda_ldda: 'hda', data_type: 'track_config' },
dataType: "json",
success: function(track_data) { view.add_drawable( trackster_ui.object_from_template(track_data, view, view) ); }
- });
+ });
// initialize icons
$("#add-bookmark-button").click(function()
diff -r e059dbc01b575b856509c2e2baccac3750b6eeb5 -r edff37d76463a468753477080f65886d4a53619e static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -1,7 +1,7 @@
define( ["libs/underscore", "viz/visualization", "viz/trackster/util",
"viz/trackster/slotting", "viz/trackster/painters", "viz/trackster/filters",
- "mvc/data", "mvc/tools" ],
- function(_, visualization, util, slotting, painters, filters_mod, data, tools_mod) {
+ "mvc/data", "mvc/tools", "utils/config" ],
+ function(_, visualization, util, slotting, painters, filters_mod, data, tools_mod, config_mod) {
var extend = _.extend;
@@ -207,26 +207,23 @@
// -- Set up drawable configuration. --
- this.config = new Config({
- params: this.config_params,
- onchange: this.config_onchange,
- saved_values: obj_dict.prefs
- });
- this.prefs = this.config.get('values');
-
+ this.config = config_mod.ConfigSettingCollection.from_models_and_saved_values(this.config_params, obj_dict.prefs);
+ console.log(obj_dict.prefs);
+ this.config.each(function(s) { console.log(s.id, s.get('value')) })
+
// If there's no saved name, use object name.
- if (!this.prefs.name) {
- this.prefs.name = obj_dict.name;
+ if (!this.config.get_value('name')) {
+ this.config.set_value('name', obj_dict.name);
}
if (this.config_onchange) {
- this.config.on('change:values', this.config_onchange, this);
+ this.config.on('change', this.config_onchange, this);
}
// Build Drawable HTML and behaviors.
this.container_div = this.build_container_div();
this.header_div = this.build_header_div();
- if (this.header_div) {
+ if (this.header_div) {
this.container_div.append(this.header_div);
// Icons container.
@@ -257,14 +254,14 @@
title: "Hide/show content",
css_class: "toggle",
on_click_fn: function(drawable) {
- if ( drawable.prefs.content_visible ) {
+ if ( drawable.config.get_value('content_visible') ) {
drawable.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");
drawable.hide_contents();
- drawable.prefs.content_visible = false;
- }
+ drawable.config.set_value('content_visible', false);
+ }
else {
drawable.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");
- drawable.prefs.content_visible = true;
+ drawable.config.set_value('content_visible', true);
drawable.show_contents();
}
}
@@ -275,10 +272,10 @@
title: "Edit settings",
css_class: "gear",
on_click_fn: function(drawable) {
- var view = new ConfigView({
- model: drawable.config
+ var view = new config_mod.ConfigSettingCollectionView({
+ collection: drawable.config
});
- view.render();
+ view.render_in_modal('Configure Track');
}
},
// Remove.
@@ -295,7 +292,7 @@
];
extend(Drawable.prototype, {
- config_params: [
+ config_params: [
{ key: 'name', label: 'Name', type: 'text', default_value: '' },
{ key: 'content_visible', type: 'bool', default_value: true, hidden: true }
],
@@ -311,7 +308,7 @@
},
can_draw: function() {
- if (this.enabled && this.prefs.content_visible) {
+ if (this.enabled && this.config.get_value('content_visible')) {
return true;
}
@@ -330,11 +327,11 @@
/**
* Set drawable name.
- */
+ */
set_name: function(new_name) {
- this.old_name = this.prefs.name;
- this.prefs.name = new_name;
- this.name_div.text(this.prefs.name);
+ this.old_name = this.config.get_value('name');
+ this.config.set_value('name', new_name);
+ this.name_div.text(new_name);
},
/**
@@ -342,8 +339,8 @@
*/
revert_name: function() {
if (this.old_name) {
- this.prefs.name = this.old_name;
- this.name_div.text(this.prefs.name);
+ this.config.set_value('name', this.old_name);
+ this.name_div.text(this.old_name);
}
},
@@ -355,7 +352,7 @@
this.container.remove_drawable(this);
var view = this.view;
- this.container_div.hide(0, function() {
+ this.container_div.hide(0, function() {
$(this).remove();
// HACK: is there a better way to update the view?
view.update_intro_div();
@@ -364,7 +361,7 @@
/**
* Build drawable's container div; this is the parent div for all drawable's elements.
- */
+ */
build_container_div: function() {},
/**
@@ -473,7 +470,7 @@
dictified_drawables.push(this.drawables[i].to_dict());
}
return {
- prefs: this.prefs,
+ prefs: this.config.to_key_value_dict(),
obj_type: this.obj_type,
drawables: dictified_drawables
};
@@ -668,7 +665,7 @@
build_header_div: function() {
var header_div = $("<div/>").addClass("track-header");
header_div.append($("<div/>").addClass(this.drag_handle_class));
- this.name_div = $("<div/>").addClass("track-name").text(this.prefs.name).appendTo(header_div);
+ this.name_div = $("<div/>").addClass("track-name").text(this.config.get_value('name')).appendTo(header_div);
return header_div;
},
@@ -829,7 +826,7 @@
*/
show_composite_track: function() {
var composite_track = new CompositeTrack(this.view, this.view, {
- name: this.prefs.name,
+ name: this.config.get_value('name'),
drawables: this.drawables
});
var index = this.container.replace_drawable(this, composite_track, true);
@@ -898,19 +895,15 @@
this.reset();
// Define track configuration
- this.config = new Config( {
- track: this,
- params: [
+ this.config = new config_mod.ConfigSettingCollection({
+ models: [
{ key: 'a_color', label: 'A Color', type: 'color', default_value: "#FF0000" },
{ key: 'c_color', label: 'C Color', type: 'color', default_value: "#00FF00" },
{ key: 'g_color', label: 'G Color', type: 'color', default_value: "#0000FF" },
{ key: 't_color', label: 'T Color', type: 'color', default_value: "#FF00FF" },
{ key: 'n_color', label: 'N Color', type: 'color', default_value: "#AAAAAA" }
- ],
+ ],
saved_values: obj_dict.prefs,
- onchange: function() {
- track.request_redraw({ clear_tile_cache: true });
- }
});
},
@@ -1819,7 +1812,7 @@
// already in group, add track to group.
if (current_track.container === view) {
// Create new group.
- var group = new DrawableGroup(view, view, { name: track.prefs.name });
+ var group = new DrawableGroup(view, view, { name: track.config.get_value('name') });
// Replace track with group.
var index = current_track.container.replace_drawable(current_track, group, false);
@@ -1923,241 +1916,6 @@
};
/**
- * Configuration object.
- */
-var Config = Backbone.Model.extend({
- initialize: function(options) {
- // values is a simple param_key-to-value dictionary used to store
- // param values.
- var values = {};
-
- // Set default values.
- _.each(options.params, function(p) {
- // For color parameters without a default value, assign a random color.
- values[p.key] = (p.type === 'color' && !p.default_value ? util.get_random_color() : p.default_value );
-
- });
-
- // Restore saved values.
- if (options.saved_values) {
- _.each( this.get('params'), function(p) {
- if (p.key in options.saved_values) {
- values[p.key] = options.saved_values[p.key];
- }
- });
- }
-
- this.set('values', values);
- },
-
- /**
- * Set default value for parameter.
- */
- set_param_default_value: function(key, default_value) {
- var param = _.find(this.get('params'), function(p) {
- return p.key === key;
- });
-
- if (param) {
- param.default_value = default_value;
- }
- },
-
- /**
- * Set a parameter's value. Returns true if value changed, false if value changed.
- */
- set_param_value: function(key, value) {
- // Find param.
- var param = _.find(this.get('params'), function(p) {
- return p.key === key;
- });
-
- if (param) {
- // Parse value from string.
- if (typeof value === "string" || value instanceof String) {
- // Parse string.
- if (value.trim() === '') {
- // If empty value, use default.
- value = param.default_value;
- } else if ( param.type === 'float' ) {
- value = parseFloat( value );
- } else if ( param.type === 'int' ) {
- value = parseInt( value, 10 );
- }
- }
- }
-
- // Set value and return true if changed, false otherwise.
- if (this.get('values')[key] !== value) {
- this.get('values')[key] = value;
- // HACK: custom event trigger needed to indicate that values were updated.
- this.trigger('change:values');
- return true;
- }
- else {
- return false;
- }
- }
-});
-
-var ConfigView = Backbone.View.extend({
-
- /**
- * Build and show form for modifying configuration. Currently uses Galaxy modals.
- */
- render: function() {
- //
- // Build config selection UI.
- //
-
- var track_config = this.model;
-
- // Prevent propagation of keydown events to viz to avoid inadvertent navigation.
- var container = $("<div/>").keydown(function(e) {
- e.stopPropagation();
- });
- var param;
- // Function to process parameters recursively
- function handle_params( params, container ) {
- for ( var index = 0; index < params.length; index++ ) {
- param = params[index];
- // Hidden params have no representation in the form
- if ( param.hidden ) { continue; }
- // Build row for param
- var id = 'param_' + index;
- var value = track_config.get('values')[ param.key ];
- var row = $("<div class='form-row' />").appendTo( container );
- row.append( $('<label />').attr("for", id ).text( param.label + ":" ) );
- // Draw parameter as checkbox
- if ( param.type === 'bool' ) {
- row.append( $('<input type="checkbox" />').attr("id", id ).attr("name", id ).attr( 'checked', value ) );
- // Draw parameter as textbox
- }
- else if ( param.type === 'text' ) {
- row.append( $('<input type="text"/>').attr("id", id ).val(value).click( function() { $(this).select(); }));
- // Draw paramter as select area
- }
- else if ( param.type === 'select' ) {
- var select = $('<select />').attr("id", id);
- for ( var i = 0; i < param.options.length; i++ ) {
- $("<option/>").text( param.options[i].label ).attr( "value", param.options[i].value ).appendTo( select );
- }
- select.val( value );
- row.append( select );
- // Draw parameter as color picker
- }
- else if ( param.type === 'color' ) {
- var
- container_div = $("<div/>").appendTo(row),
- input = $('<input/>').attr({
- id: id,
- name: id
- }).val( value ).addClass('color-input')
- .appendTo(container_div).click(function(e) {
- // Hide other pickers.
- $(".tooltip").removeClass( "in" );
-
- // Show input's color picker.
- var tip = $(this).siblings(".tooltip").addClass( "in" );
- tip.css( {
- // left: $(this).position().left + ( $(input).width() / 2 ) - 60,
- // top: $(this).position().top + $(this.height)
- left: $(this).position().left + $(this).width() + 5,
- top: $(this).position().top + Galaxy.modal.scrollTop() - ( $(tip).height() / 2 ) + ( $(this).height() / 2 )
- } ).show();
- // Click management:
-
- // Keep showing tip if clicking in tip.
- tip.click(function(e) {
- e.stopPropagation();
- });
-
- // Hide tip if clicking outside of tip.
- $(document).bind( "click.color-picker", function() {
- tip.hide();
- $(document).unbind( "click.color-picker" );
- });
-
- // No propagation to avoid triggering document click (and tip hiding) above.
- e.stopPropagation();
- }),
- // Icon for setting a new random color; behavior set below.
- new_color_icon = $("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(container_div)
- .attr("title", "Set new random color").tooltip(),
- // Color picker in tool tip style.
- tip = $( "<div class='tooltip right' style='position: absolute;' />" ).appendTo(container_div).hide(),
- // Inner div for padding purposes
- tip_inner = $("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(tip),
- tip_arrow = $("<div class='tooltip-arrow'></div>").appendTo(tip),
- farb_obj = $.farbtastic(tip_inner, { width: 100, height: 100, callback: input, color: value });
-
- // Clear floating.
- container_div.append( $("<div/>").css("clear", "both"));
-
- // Use function to fix farb_obj value.
- (function(fixed_farb_obj) {
- new_color_icon.click(function() {
- fixed_farb_obj.setColor(util.get_random_color());
- });
- })(farb_obj);
-
- }
- else {
- row.append( $('<input />').attr("id", id ).attr("name", id ).val( value ) );
- }
- // Help text
- if ( param.help ) {
- row.append( $("<div class='help'/>").text( param.help ) );
- }
- }
- }
- // Handle top level parameters in order
- handle_params( track_config.get('params'), container );
-
- //
- // Use Galaxy modal to display config.
- //
-
- var self = this,
- cancel_fn = function() { Galaxy.modal.hide(); $(window).unbind("keypress.check_enter_esc"); },
- ok_fn = function() {
- self.update_from_form( $(Galaxy.modal.el) );
- Galaxy.modal.hide();
- $(window).unbind("keypress.check_enter_esc");
- },
- check_enter_esc = function(e) {
- if ((e.keyCode || e.which) === 27) { // Escape key
- cancel_fn();
- } else if ((e.keyCode || e.which) === 13) { // Enter key
- ok_fn();
- }
- };
-
- $(window).bind("keypress.check_enter_esc", check_enter_esc);
- Galaxy.modal.show({title: "Configure", body: container, buttons : {'Cancel' : cancel_fn, 'Ok' : ok_fn } });
- },
-
- /**
- * Update configuration from form.
- */
- update_from_form: function( container ) {
- var model = this.model;
- var changed = false;
- _.each(model.get('params'), function(param, index) {
- if ( !param.hidden ) {
- // Get value from form element.
- var id = 'param_' + index;
- var value = container.find( '#' + id ).val();
- if ( param.type === 'bool' ) {
- value = container.find( '#' + id ).is( ':checked' );
- }
- changed = model.set_param_value(param.key, value) || changed;
- }
- });
- }
-});
-
-/**
* Tiles drawn by tracks.
*/
var Tile = function(track, region, w_scale, canvas, data) {
@@ -2376,8 +2134,8 @@
this.data_url_extra_params = {};
this.data_query_wait = ('data_query_wait' in obj_dict ? obj_dict.data_query_wait : DEFAULT_DATA_QUERY_WAIT);
// A little ugly creating data manager right now due to transition to Backbone-based objects.
- this.data_manager = ('data_manager' in obj_dict ?
- obj_dict.data_manager :
+ this.data_manager = ('data_manager' in obj_dict ?
+ obj_dict.data_manager :
new visualization.GenomeDataManager({
dataset: this.dataset,
// HACK: simulate 'genome' attributes from view for now.
@@ -2395,13 +2153,13 @@
// Height attributes: min height, max height, and visible height.
this.min_height_px = 16;
this.max_height_px = 800;
- this.visible_height_px = this.prefs.height;
+ this.visible_height_px = this.config.get_value('height');
//
// Create content div, which is where track is displayed, and add to container if available.
//
this.content_div = $("<div class='track-content'>").appendTo(this.container_div);
- if (this.container) {
+ if (this.container) {
this.container.content_div.append(this.container_div);
if ( !("resize" in obj_dict) || obj_dict.resize ) {
this.add_resize_handle();
@@ -2459,7 +2217,7 @@
// Update track name.
if (track.tool.is_visible()) {
- track.set_name(track.prefs.name + track.tool_region_and_parameters_str());
+ track.set_name(track.config.get_value('name') + track.tool_region_and_parameters_str());
}
else {
track.revert_name();
@@ -2475,8 +2233,8 @@
css_class: "arrow-split",
on_click_fn: function(track) {
var template =
- '<strong>Tool</strong>: <%= track.tool.get("name") %><br/>' +
- '<strong>Dataset</strong>: <%= track.prefs.name %><br/>' +
+ '<strong>Tool</strong>: <%= track.tool.get("name") %><br/>' +
+ '<strong>Dataset</strong>: <%= track.config.get("name") %><br/>' +
'<strong>Region(s)</strong>: <select name="regions">' +
'<option value="cur">current viewing area</option>' +
'<option value="bookmarks">bookmarks</option>' +
@@ -2492,7 +2250,7 @@
start: view.low,
end: view.high
}),
- bookmarked_regions = _.map($(".bookmark"), function(elt) {
+ bookmarked_regions = _.map($(".bookmark"), function(elt) {
return new visualization.GenomeRegion({from_str: $(elt).children(".position").text()});
});
@@ -2548,8 +2306,8 @@
build_header_div: function() {
var header_div = $("<div class='track-header'/>");
if (this.view.editor) { this.drag_div = $("<div/>").addClass(this.drag_handle_class).appendTo(header_div); }
- this.name_div = $("<div/>").addClass("track-name").appendTo(header_div).text(this.prefs.name)
- .attr( "id", this.prefs.name.replace(/\s+/g,'-').replace(/[^a-zA-Z0-9\-]/g,'').toLowerCase() );
+ this.name_div = $("<div/>").addClass("track-name").appendTo(header_div).text(this.config.get_value('name'))
+ .attr( "id", this.config.get_value('name').replace(/\s+/g,'-').replace(/[^a-zA-Z0-9\-]/g,'').toLowerCase() );
return header_div;
},
@@ -2578,7 +2336,7 @@
var drag_control = $( "<div class='track-resize'>" );
// Control shows on hover over track, stays while dragging
$(track.container_div).hover( function() {
- if ( track.prefs.content_visible ) {
+ if ( track.config.get_value('content_visible') ) {
in_handle = true;
drag_control.show();
}
@@ -2597,10 +2355,10 @@
track.visible_height_px = (track.max_height_px === new_height ? 0 : new_height);
track.on_resize();
}).bind( "dragend", function( e, d ) {
- track.tile_cache.clear();
+ track.tile_cache.clear();
in_drag = false;
if (!in_handle) { drag_control.hide(); }
- track.config.get('values').height = track.visible_height_px;
+ track.config.set('height', track.visible_height_px);
track.changed();
}).appendTo(track.container_div);
},
@@ -2611,16 +2369,15 @@
set_display_modes: function(new_modes, init_mode) {
// Set modes, init mode.
this.display_modes = new_modes;
- this.mode = (init_mode ? init_mode :
- (this.config && this.config.get('values').mode ?
- this.config.get('values').mode : this.display_modes[0])
+ this.mode = (init_mode ? init_mode :
+ (this.config && this.config.get_value('mode') ?
+ this.config.get_value('mode') : this.display_modes[0])
);
this.action_icons.mode_icon.attr("title", "Set display mode (now: " + this.mode + ")");
// Setup popup menu for changing modes.
- var
- track = this,
+ var track = this,
mode_mapping = {};
for (var i = 0, len = track.display_modes.length; i < len; i++) {
var mode = track.display_modes[i];
@@ -2822,10 +2579,10 @@
min_value = Math.floor( Math.min( 0, Math.max( min_value, data.mean - 2 * data.sd ) ) );
max_value = Math.ceil( Math.max( 0, Math.min( max_value, data.mean + 2 * data.sd ) ) );
// Update config, prefs
- track.config.set_param_default_value('min_value', min_value);
- track.config.set_param_default_value('max_value', max_value);
- track.prefs.min_value = min_value;
- track.prefs.max_value = max_value;
+ track.config.set_default_value('min_value', min_value);
+ track.config.set_default_value('max_value', max_value);
+ track.config.set_value('min_value', min_value);
+ track.config.set_value('max_value', max_value);
}
});
},
@@ -2879,7 +2636,7 @@
// Add tiles_div, overlay_div to content_div.
this.tiles_div = $("<div/>").addClass("tiles").appendTo(this.content_div);
- if (!this.prefs.content_visible) {
+ if (!this.config.get_value('content_visible')) {
this.tiles_div.hide();
}
this.overlay_div = $("<div/>").addClass("overlay").appendTo(this.content_div);
@@ -2934,13 +2691,14 @@
* Use from_dict to recreate object.
*/
to_dict: function() {
+ console.log(this.config.to_key_value_dict());
return {
track_type: this.get_type(),
dataset: {
id: this.dataset.id,
hda_ldda: this.dataset.get('hda_ldda')
},
- prefs: this.prefs,
+ prefs: this.config.to_key_value_dict(),
mode: this.mode,
filters: this.filters_manager.to_dict(),
tool_state: (this.tool ? this.tool.state_dict() : {})
@@ -2958,7 +2716,8 @@
high: track.view.max_high, hda_ldda: track.dataset.get('hda_ldda') },
function(result) {
var data = result.data;
- if ( isNaN(parseFloat(track.prefs.min_value)) || isNaN(parseFloat(track.prefs.max_value)) ) {
+ if ( isNaN(parseFloat(track.config.get_value('min_value'))) ||
+ isNaN(parseFloat(track.config.get_value('max_value'))) ) {
// Compute default minimum and maximum values
var min_value = data.min,
max_value = data.max;
@@ -2967,8 +2726,8 @@
min_value = Math.floor( Math.min( 0, Math.max( min_value, data.mean - 2 * data.sd ) ) );
max_value = Math.ceil( Math.max( 0, Math.min( max_value, data.mean + 2 * data.sd ) ) );
// Update the prefs
- track.prefs.min_value = min_value;
- track.prefs.max_value = max_value;
+ track.config.set_value('min_value', min_value);
+ track.config.set_value('max_value', max_value);
}
});
},
@@ -2980,7 +2739,7 @@
var track = this;
// TODO: is it necessary to store the mode in two places (.mode and track_config)?
track.mode = new_mode;
- track.config.get('values').mode = new_mode;
+ track.config.set_value('mode', new_mode);
// FIXME: find a better way to get Auto data w/o clearing cache; using mode in the
// data manager would work if Auto data were checked for compatibility when a specific
// mode is chosen.
@@ -3151,11 +2910,11 @@
if (label.length !== 0) {
// Label already exists, so update value.
- label.text(track.prefs[pref_name]);
+ label.text(track.config.get_value(pref_name));
}
else {
// Add label.
- label = $("<div/>").text(track.prefs[pref_name]).make_text_editable({
+ label = $("<div/>").text(track.config.get_value(pref_name)).make_text_editable({
num_cols: 12,
on_finish: function(new_val) {
$(".tooltip").remove();
@@ -3163,7 +2922,7 @@
on_change();
},
help_text: "Set " + text + " value"
- }).addClass('yaxislabel ' + css_class).css("color", this.prefs.label_color);
+ }).addClass('yaxislabel ' + css_class).css("color", this.config.get_value('label_color'));
this.container_div.prepend(label);
}
},
@@ -3376,7 +3135,7 @@
*/
_draw_line_track_tile: function(result, ctx, mode, region, w_scale) {
var canvas = ctx.canvas,
- painter = new painters.LinePainter(result.data, region.get('start'), region.get('end'), this.prefs, mode);
+ painter = new painters.LinePainter(result.data, region.get('start'), region.get('end'), this.config.to_key_value_dict(), mode);
painter.draw(ctx, canvas.width, canvas.height, w_scale);
return new LineTrackTile(this, region, w_scale, canvas, result.data);
@@ -3691,7 +3450,7 @@
show_group: function() {
// Create group with individual tracks.
var group = new DrawableGroup(this.view, this.container, {
- name: this.prefs.name
+ name: this.config.get_value('name')
}),
track;
for (var i = 0; i < this.drawables.length; i++) {
@@ -3718,16 +3477,16 @@
//
// Get smallest min, biggest max.
- var min = _.min(_.map(this.drawables, function(d) { return d.prefs.min_value; })),
- max = _.max(_.map(this.drawables, function(d) { return d.prefs.max_value; }));
+ var min = _.min(_.map(this.drawables, function(d) { return d.config.get_value('min_value'); })),
+ max = _.max(_.map(this.drawables, function(d) { return d.config.get_value('max_value') }));
- this.prefs.min_value = min;
- this.prefs.max_value = max;
+ this.config.set_value('min_value', min);
+ this.config.set_value('max_value', max);
// Set all tracks to smallest min, biggest max.
_.each(this.drawables, function(d) {
- d.prefs.min_value = min;
- d.prefs.max_value = max;
+ d.config.set_value('min_value', min);
+ d.config.set_value('max_value', max);
});
},
@@ -3735,10 +3494,12 @@
* Update minimum, maximum for component tracks.
*/
update_all_min_max: function() {
- var track = this;
+ var track = this,
+ min_value = this.config.get_value('min_value'),
+ max_value = this.config.get_value('max_value');
_.each(this.drawables, function(d) {
- d.prefs.min_value = track.prefs.min_value;
- d.prefs.max_value = track.prefs.max_value;
+ d.config.set_value('min_value', min_value);
+ d.config.set_value('max_value', max_value);
});
this.request_draw({ clear_tile_cache: true });
},
@@ -3861,16 +3622,16 @@
display_modes: CONTINUOUS_DATA_MODES,
config_params: _.union( Drawable.prototype.config_params, [
- { key: 'color', label: 'Color', type: 'color' },
- { key: 'min_value', label: 'Min Value', type: 'float', default_value: undefined },
- { key: 'max_value', label: 'Max Value', type: 'float', default_value: undefined },
- { key: 'mode', type: 'string', default_value: this.mode, hidden: true },
- { key: 'height', type: 'int', default_value: 30, hidden: true }
+ { key: 'color', label: 'Color', type: 'color' },
+ { key: 'min_value', label: 'Min Value', type: 'float', default_value: undefined },
+ { key: 'max_value', label: 'Max Value', type: 'float', default_value: undefined },
+ { key: 'mode', type: 'string', default_value: this.mode, hidden: true },
+ { key: 'height', type: 'int', default_value: 30, hidden: true }
] ),
config_onchange: function() {
- this.set_name(this.prefs.name);
- this.request_draw({ clear_tile_cache: true });
+ this.set_name(this.config.get_value('name'));
+ this.request_draw({ clear_tile_cache: true });
},
/**
@@ -3924,7 +3685,7 @@
] ),
config_onchange: function() {
- this.set_name(this.prefs.name);
+ this.set_name(this.config.get_value('name'));
this.request_draw({ clear_tile_cache: true });
},
@@ -3934,7 +3695,7 @@
draw_tile: function(result, ctx, mode, region, w_scale) {
// Paint onto canvas.
var canvas = ctx.canvas,
- painter = new painters.DiagonalHeatmapPainter(result.data, region.get('start'), region.get('end'), this.prefs, mode);
+ painter = new painters.DiagonalHeatmapPainter(result.data, region.get('start'), region.get('end'), this.config.to_key_value_dict(), mode);
painter.draw(ctx, canvas.width, canvas.height, w_scale);
return new Tile(this, region, w_scale, canvas, result.data);
@@ -3973,7 +3734,7 @@
] ),
config_onchange: function() {
- this.set_name(this.prefs.name);
+ this.set_name(this.config.get_value('name'));
this.set_painter_from_config();
this.request_draw({ clear_tile_cache: true });
},
@@ -4158,7 +3919,7 @@
var rows_required = this.incremental_slots(w_scale, result.data, mode);
// HACK: use dummy painter to get required height. Painter should be extended so that get_required_height
// works as a static function.
- var dummy_painter = new (this.painter)(null, null, null, this.prefs, mode);
+ var dummy_painter = new (this.painter)(null, null, null, this.config.to_key_value_dict(), mode);
return Math.max(this.min_height_px, dummy_painter.get_required_height(rows_required, canvas_width) );
}
},
@@ -4219,14 +3980,14 @@
// Create painter.
var filter_alpha_scaler = (this.filters_manager.alpha_filter ? new FilterScaler(this.filters_manager.alpha_filter) : null),
filter_height_scaler = (this.filters_manager.height_filter ? new FilterScaler(this.filters_manager.height_filter) : null),
- painter = new (this.painter)(filtered, tile_low, tile_high, this.prefs, mode, filter_alpha_scaler, filter_height_scaler,
+ painter = new (this.painter)(filtered, tile_low, tile_high, this.config.to_key_value_dict(), mode, filter_alpha_scaler, filter_height_scaler,
// HACK: ref_seq only be defined for ReadTracks, and only the ReadPainter accepts that argument
ref_seq,
// Only the ReadPainer will use this function
function(b) { return track.view.get_base_color(b); });
var feature_mapper = null;
- ctx.fillStyle = this.prefs.block_color;
+ ctx.fillStyle = this.config.get_value('block_color');
ctx.font = ctx.canvas.manager.default_font;
ctx.textAlign = "right";
@@ -4262,11 +4023,11 @@
{ key: 'show_labels', label: 'Show summary and sample labels', type: 'bool', default_value: true },
{ key: 'summary_height', label: 'Locus summary height', type: 'float', default_value: 20 },
{ key: 'mode', type: 'string', default_value: this.mode, hidden: true },
- { key: 'height', type: 'int', default_value: 0, hidden: true }
+ { key: 'height', type: 'int', default_value: 32, hidden: true }
] ),
config_onchange: function() {
- this.set_name(this.prefs.name);
+ this.set_name(this.config.get_value('name'));
this.request_draw({ clear_tile_cache: true });
},
@@ -4280,7 +4041,7 @@
}
else { // result.dataset_type === 'variant'
var view = this.view,
- painter = new (this.painter)(result.data, region.get('start'), region.get('end'), this.prefs, mode,
+ painter = new (this.painter)(result.data, region.get('start'), region.get('end'), this.config.to_key_value_dict(), mode,
function(b) { return view.get_base_color(b); });
painter.draw(ctx, ctx.canvas.width, ctx.canvas.height, w_scale);
return new Tile(this, region, w_scale, ctx.canvas, result.data);
@@ -4312,7 +4073,7 @@
}
}
- var dummy_painter = new (this.painter)(null, null, null, this.prefs, mode);
+ var dummy_painter = new (this.painter)(null, null, null, this.config.to_key_value_dict(), mode);
return dummy_painter.get_required_height(num_samples);
}
},
@@ -4343,7 +4104,7 @@
// Add summary/sample labels if needed and not already included.
var sample_names = this.dataset.get_metadata('sample_names');
- if (line_track_tiles.length === 0 && this.prefs.show_labels && sample_names && sample_names.length > 1) {
+ if (line_track_tiles.length === 0 && this.config.get_value('show_labels') && sample_names && sample_names.length > 1) {
var font_size;
// Add and/or style labels.
@@ -4351,21 +4112,21 @@
// Add summary and sample labels.
// Add summary label to middle of summary area.
- font_size = this.prefs.summary_height / 2;
+ font_size = this.config.get_value('summary_height') / 2;
this.tiles_div.prepend(
$("<div/>").text('Summary').addClass('yaxislabel variant top').css({
'font-size': font_size + 'px',
- 'top': (this.prefs.summary_height - font_size) / 2 + 'px'
+ 'top': (this.config.get_value('summary_height') - font_size) / 2 + 'px'
})
);
// Show sample labels.
- if (this.prefs.show_sample_data) {
+ if (this.config.get_value('show_sample_data')) {
var samples_div_html = sample_names.join('<br/>');
this.tiles_div.prepend(
$("<div/>").html(samples_div_html).addClass('yaxislabel variant top sample').css({
- 'top': this.prefs.summary_height,
+ 'top': this.config.get_value('summary_height')
})
);
}
@@ -4380,7 +4141,7 @@
'line-height': font_size
});
// Color labels to preference color.
- $(this.tiles_div).find('.yaxislabel').css('color', this.prefs.label_color);
+ $(this.tiles_div).find('.yaxislabel').css('color', this.config.get_value('label_color'));
}
else {
// Remove all labels.
@@ -4414,7 +4175,7 @@
] ),
config_onchange: function() {
- this.set_name(this.prefs.name);
+ this.set_name(this.config.get_value('name'));
this.request_draw({ clear_tile_cache: true });
}
});
diff -r e059dbc01b575b856509c2e2baccac3750b6eeb5 -r edff37d76463a468753477080f65886d4a53619e static/scripts/viz/trackster_ui.js
--- a/static/scripts/viz/trackster_ui.js
+++ b/static/scripts/viz/trackster_ui.js
@@ -75,7 +75,7 @@
});
// FIXME: give unique IDs to Drawables and save overview as ID.
- var overview_track_name = (view.overview_drawable ? view.overview_drawable.prefs.name : null),
+ var overview_track_name = (view.overview_drawable ? view.overview_drawable.config.get_value('name') : null),
viz_config = {
'view': view.to_dict(),
'viewport': { 'chrom': view.chrom, 'start': view.low , 'end': view.high, 'overview': overview_track_name },
@@ -86,9 +86,9 @@
url: galaxy_config.root + "visualization/save",
type: "POST",
dataType: "json",
- data: {
+ data: {
'id' : view.vis_id,
- 'title' : view.prefs.name,
+ 'title' : view.config.get_value('name'),
'dbkey' : view.dbkey,
'type' : 'trackster',
'vis_json' : JSON.stringify(viz_config)
@@ -265,7 +265,7 @@
// Set overview.
var overview_drawable;
for (var i = 0; i < view.drawables.length; i++) {
- if (view.drawables[i].prefs.name === overview_drawable_name) {
+ if (view.drawables[i].config.get_value('name') === overview_drawable_name) {
view.set_overview(view.drawables[i]);
break;
}
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: dan: UI fixes for Configure workflow menu.
by commits-noreply@bitbucket.org 28 Feb '14
by commits-noreply@bitbucket.org 28 Feb '14
28 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e059dbc01b57/
Changeset: e059dbc01b57
User: dan
Date: 2014-02-28 21:02:07
Summary: UI fixes for Configure workflow menu.
Affected #: 2 files
diff -r 410a13e7e8ddabf9a00ffb8ba3bc75d4948447e4 -r e059dbc01b575b856509c2e2baccac3750b6eeb5 lib/galaxy/webapps/galaxy/controllers/workflow.py
--- a/lib/galaxy/webapps/galaxy/controllers/workflow.py
+++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py
@@ -1557,23 +1557,28 @@
m.stored_workflow = q.get( id )
user.stored_workflow_menu_entries.append( m )
sess.flush()
- return trans.show_message( "Menu updated", refresh_frames=['tools'] )
+ message = "Menu updated"
+ refresh_frames = ['tools']
else:
- user = trans.get_user()
- ids_in_menu = set( [ x.stored_workflow_id for x in user.stored_workflow_menu_entries ] )
- workflows = trans.sa_session.query( model.StoredWorkflow ) \
- .filter_by( user=user, deleted=False ) \
- .order_by( desc( model.StoredWorkflow.table.c.update_time ) ) \
- .all()
- shared_by_others = trans.sa_session \
- .query( model.StoredWorkflowUserShareAssociation ) \
- .filter_by( user=user ) \
- .filter( model.StoredWorkflow.deleted == False ) \
- .all()
- return trans.fill_template( "workflow/configure_menu.mako",
- workflows=workflows,
- shared_by_others=shared_by_others,
- ids_in_menu=ids_in_menu )
+ message = None
+ refresh_frames = []
+ user = trans.get_user()
+ ids_in_menu = set( [ x.stored_workflow_id for x in user.stored_workflow_menu_entries ] )
+ workflows = trans.sa_session.query( model.StoredWorkflow ) \
+ .filter_by( user=user, deleted=False ) \
+ .order_by( desc( model.StoredWorkflow.table.c.update_time ) ) \
+ .all()
+ shared_by_others = trans.sa_session \
+ .query( model.StoredWorkflowUserShareAssociation ) \
+ .filter_by( user=user ) \
+ .filter( model.StoredWorkflow.deleted == False ) \
+ .all()
+ return trans.fill_template( "workflow/configure_menu.mako",
+ workflows=workflows,
+ shared_by_others=shared_by_others,
+ ids_in_menu=ids_in_menu,
+ message=message,
+ refresh_frames=['tools'] )
def _workflow_to_svg_canvas( self, trans, stored ):
workflow = stored.latest_workflow
diff -r 410a13e7e8ddabf9a00ffb8ba3bc75d4948447e4 -r e059dbc01b575b856509c2e2baccac3750b6eeb5 templates/webapps/galaxy/workflow/configure_menu.mako
--- a/templates/webapps/galaxy/workflow/configure_menu.mako
+++ b/templates/webapps/galaxy/workflow/configure_menu.mako
@@ -1,7 +1,19 @@
-<%inherit file="/base.mako"/>
+<%inherit file="/webapps/galaxy/base_panels.mako"/>
+
+<%def name="init()">
+<%
+ self.has_left_panel=False
+ self.has_right_panel=False
+ self.active_view="workflow"
+ self.message_box_visible=False
+%>
+</%def><%def name="title()">Configure workflow menu</%def>
+<%def name="center_panel()">
+ <div style="overflow: auto; height: 100%;">
+ <div class="page-container" style="padding: 10px;">
%if message:
<%
try:
@@ -69,9 +81,18 @@
%endif
+%if not workflows and not shared_by_others:
+ <tr>
+ <td colspan="4">You do not have any accessible workflows.</td>
+ </tr>
+%endif
+
</table><p />
-<input type="Submit" />
+<input type="Submit" value="Save" /></form>
+ </div>
+ </div>
+</%def>
\ 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: jmchilton: Add test cases for need_late_validation of select parameters.
by commits-noreply@bitbucket.org 28 Feb '14
by commits-noreply@bitbucket.org 28 Feb '14
28 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/410a13e7e8dd/
Changeset: 410a13e7e8dd
User: jmchilton
Date: 2014-02-28 19:42:30
Summary: Add test cases for need_late_validation of select parameters.
Two of these fail without JJ's work in pull request 336, additionally these verify 336 doesn't break GATK support for instance.
Affected #: 1 file
diff -r 3981b0070af02af108ce81091866d531e66b8fd1 -r 410a13e7e8ddabf9a00ffb8ba3bc75d4948447e4 test/unit/tools/test_select_parameters.py
--- /dev/null
+++ b/test/unit/tools/test_select_parameters.py
@@ -0,0 +1,93 @@
+from unittest import TestCase
+from galaxy.util import bunch
+from galaxy import model
+from galaxy.tools.parameters import basic
+from elementtree.ElementTree import XML
+
+import tools_support
+
+
+class SelectToolParameterTestCase( TestCase, tools_support.UsesApp ):
+
+ def test_dep_dummy_datasets_need_late_validation( self ):
+ self.options_xml = '''<options><filter type="data_meta" ref="input_bam" key="dbkey"/></options>'''
+ assert self.param.need_late_validation( self.trans, { "input_bam": basic.DummyDataset() } )
+
+ def test_dep_runtime_values_need_late_validation( self ):
+ self.options_xml = '''<options><filter type="data_meta" ref="input_bam" key="dbkey"/></options>'''
+ assert self.param.need_late_validation( self.trans, { "input_bam": basic.RuntimeValue() } )
+
+ def test_dep_unvalidated_values_need_late_validation( self ):
+ self.options_xml = '''<options><filter type="data_meta" ref="input_bam" key="dbkey"/></options>'''
+ assert self.param.need_late_validation( self.trans, { "input_bam": basic.UnvalidatedValue( "42" ) } )
+
+ def test_dep_real_datasets_no_late_validation( self ):
+ self.options_xml = '''<options><filter type="data_meta" ref="input_bam" key="dbkey"/></options>'''
+ assert not self.param.need_late_validation( self.trans, { "input_bam": model.HistoryDatasetAssociation() } )
+
+ def test_nested_context_validation_needed( self ):
+ self.options_xml = '''<options><filter type="data_meta" ref="input_bam" key="dbkey"/></options>'''
+ # Data ref currently must be same level, if not at top level.
+ assert self.param.need_late_validation( self.trans, { "reference_source": { "my_name": "42", "input_bam": basic.RuntimeValue() } } )
+
+ def test_nested_context_validation_not_needed( self ):
+ self.options_xml = '''<options><filter type="data_meta" ref="input_bam" key="dbkey"/></options>'''
+ # Data ref currently must be same level, if not at top level.
+ assert not self.param.need_late_validation( self.trans, { "reference_source": { "my_name": "42", "input_bam": model.HistoryDatasetAssociation() } } )
+
+ # Following test will fail due to bug in Galaxy.
+ def test_nested_context_validation_needed_in_repeat( self ):
+ self.type = "data_column"
+ self.set_ref_text = True
+ self.options_xml = '''<options><filter type="data_meta" ref="input_bam" key="dbkey"/></options>'''
+ assert not self.param.need_late_validation( self.trans, { "series": [ { "my_name": "42", "input_bam": model.HistoryDatasetAssociation() } ] } )
+
+ def test_nested_context_validation_not_needed_in_repeat( self ):
+ self.type = "data_column"
+ self.set_ref_text = True
+ self.options_xml = '''<options><filter type="data_meta" ref="input_bam" key="dbkey"/></options>'''
+ assert self.param.need_late_validation( self.trans, { "series": [ { "my_name": "42", "input_bam": basic.RuntimeValue() } ] } )
+
+ # TODO: Good deal of overlap here with DataToolParameterTestCase,
+ # refactor.
+ 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.type = "select"
+ self.set_data_ref = False
+ self.multiple = False
+ self.optional = False
+ self.options_xml = ""
+ self._param = None
+
+ @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"'
+ options_text = self.options_xml
+ data_ref_text = ""
+ if self.set_data_ref:
+ data_ref_text = 'data_ref="input_bam"'
+ template_xml = '''<param name="my_name" type="%s" %s %s %s>%s</param>'''
+ self.param_xml = XML( template_xml % ( self.type, data_ref_text, multi_text, optional_text, options_text ) )
+ self._param = basic.SelectToolParameter( self.mock_tool, self.param_xml )
+
+ return self._param
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
5 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/82c43e74d316/
Changeset: 82c43e74d316
Branch: jjohnson/allow-jobs-to-be-filtered-by-tool_id-and-1391011677231
User: jjohnson
Date: 2014-01-29 17:09:12
Summary: Allow jobs to be filtered by tool_id and history_id as well as by state. The tool_id is compared with the like operator.
Affected #: 1 file
diff -r 07dceba219c315e2857f105abfdaf030efa1f16c -r 82c43e74d31617ca3efda965d6c069c7e99ae63b lib/galaxy/webapps/galaxy/api/jobs.py
--- a/lib/galaxy/webapps/galaxy/api/jobs.py
+++ b/lib/galaxy/webapps/galaxy/api/jobs.py
@@ -22,7 +22,7 @@
@expose_api
def index( self, trans, **kwd ):
"""
- index( trans, state=None )
+ index( trans, state=None, tool_id=None, history_id=None )
* GET /api/jobs:
return jobs for current user
@@ -31,6 +31,12 @@
Valid Galaxy job states include:
'new', 'upload', 'waiting', 'queued', 'running', 'ok', 'error', 'paused', 'deleted', 'deleted_new'
+ :type tool_id: string or list
+ :param tool_id: limit listing of jobs to those that match one of the included tool_ids. If none, all are returned.
+
+ :type history_id: string
+ :param history_id: limit listing of jobs to those that match the history_id. If none, all are returned.
+
:rtype: list
:returns: list of dictionaries containing summary job information
"""
@@ -48,6 +54,24 @@
t.append( trans.app.model.Job.state == s )
query = query.filter( or_( *t ) )
+ tool_id = kwd.get( 'tool_id', None )
+ if tool_id is not None:
+ if isinstance( tool_id, basestring ):
+ query = query.filter( trans.app.model.Job.tool_id.like('%' + tool_id + '%') )
+ elif isinstance( tool_id, list ):
+ t = []
+ for s in tool_id:
+ t.append( trans.app.model.Job.tool_id.like('%' + s + '%') )
+ query = query.filter( or_( *t ) )
+
+ history_id = kwd.get( 'history_id', None )
+ if history_id is not None:
+ try:
+ decoded_history_id = trans.security.decode_id(history_id)
+ query = query.filter( trans.app.model.Job.history_id == decoded_history_id )
+ except:
+ raise exceptions.ObjectAttributeInvalidException()
+
out = []
for job in query.order_by(
trans.app.model.Job.update_time.desc()
https://bitbucket.org/galaxy/galaxy-central/commits/b6cc7ffa9f4c/
Changeset: b6cc7ffa9f4c
Branch: jjohnson/allow-jobs-to-be-filtered-by-tool_id-and-1391011677231
User: jmchilton
Date: 2014-02-28 16:57:53
Summary: Reduce a little code dup in api/jobs.py.
Affected #: 1 file
diff -r 82c43e74d31617ca3efda965d6c069c7e99ae63b -r b6cc7ffa9f4c615b0724d5a3a52270ae5087e649 lib/galaxy/webapps/galaxy/api/jobs.py
--- a/lib/galaxy/webapps/galaxy/api/jobs.py
+++ b/lib/galaxy/webapps/galaxy/api/jobs.py
@@ -12,6 +12,7 @@
from galaxy.web.base.controller import UsesHistoryDatasetAssociationMixin
from galaxy.web.base.controller import UsesLibraryMixinItems
from galaxy import exceptions
+from galaxy import util
import logging
log = logging.getLogger( __name__ )
@@ -45,24 +46,22 @@
query = trans.sa_session.query( trans.app.model.Job ).filter(
trans.app.model.Job.user == trans.user
)
- if state is not None:
- if isinstance( state, basestring ):
- query = query.filter( trans.app.model.Job.state == state )
- elif isinstance( state, list ):
- t = []
- for s in state:
- t.append( trans.app.model.Job.state == s )
- query = query.filter( or_( *t ) )
+
+ def build_and_apply_filters( query, objects, filter_func ):
+ if objects is not None:
+ if isinstance( objects, basestring ):
+ query = query.filter( filter_func( objects ) )
+ elif isinstance( objects, list ):
+ t = []
+ for obj in objects:
+ t.append( filter_func( obj ) )
+ query = query.filter( or_( *t ) )
+ return query
+
+ query = build_and_apply_filters( query, state, lambda s: trans.app.model.Job.state == s )
tool_id = kwd.get( 'tool_id', None )
- if tool_id is not None:
- if isinstance( tool_id, basestring ):
- query = query.filter( trans.app.model.Job.tool_id.like('%' + tool_id + '%') )
- elif isinstance( tool_id, list ):
- t = []
- for s in tool_id:
- t.append( trans.app.model.Job.tool_id.like('%' + s + '%') )
- query = query.filter( or_( *t ) )
+ query = build_and_apply_filters( query, tool_id, lambda t: trans.app.model.Job.tool_id.like('%' + t + '%') )
history_id = kwd.get( 'history_id', None )
if history_id is not None:
https://bitbucket.org/galaxy/galaxy-central/commits/7bdfa44e7edc/
Changeset: 7bdfa44e7edc
Branch: jjohnson/allow-jobs-to-be-filtered-by-tool_id-and-1391011677231
User: jmchilton
Date: 2014-02-28 17:02:29
Summary: Modify jobs index to allow exact or inexact tool id filtering.
Discussed this with JJ and Dannon. Formerly this was only inexact matchings, I was a little worried about API users expected exact tool id matches when using a parameter called tool_id. JJ's original intended behavior can be accessed using tool_id_like.
Affected #: 1 file
diff -r b6cc7ffa9f4c615b0724d5a3a52270ae5087e649 -r 7bdfa44e7edcb7a299dcd31943be7c55babfaedc lib/galaxy/webapps/galaxy/api/jobs.py
--- a/lib/galaxy/webapps/galaxy/api/jobs.py
+++ b/lib/galaxy/webapps/galaxy/api/jobs.py
@@ -60,8 +60,8 @@
query = build_and_apply_filters( query, state, lambda s: trans.app.model.Job.state == s )
- tool_id = kwd.get( 'tool_id', None )
- query = build_and_apply_filters( query, tool_id, lambda t: trans.app.model.Job.tool_id.like('%' + t + '%') )
+ query = build_and_apply_filters( query, kwd.get( 'tool_id', None ), lambda t: trans.app.model.Job.tool_id == t )
+ query = build_and_apply_filters( query, kwd.get( 'tool_id_like', None ), lambda t: trans.app.model.Job.tool_id.like(t) )
history_id = kwd.get( 'history_id', None )
if history_id is not None:
https://bitbucket.org/galaxy/galaxy-central/commits/3981b0070af0/
Changeset: 3981b0070af0
User: jmchilton
Date: 2014-02-28 17:08:26
Summary: Merge JJ's pull request #315 (with minor modifications discussed with JJ).
Affected #: 1 file
diff -r 6a633b37c4c47bba640d05fef72fd73f41ae5086 -r 3981b0070af02af108ce81091866d531e66b8fd1 lib/galaxy/webapps/galaxy/api/jobs.py
--- a/lib/galaxy/webapps/galaxy/api/jobs.py
+++ b/lib/galaxy/webapps/galaxy/api/jobs.py
@@ -12,6 +12,7 @@
from galaxy.web.base.controller import UsesHistoryDatasetAssociationMixin
from galaxy.web.base.controller import UsesLibraryMixinItems
from galaxy import exceptions
+from galaxy import util
import logging
log = logging.getLogger( __name__ )
@@ -22,7 +23,7 @@
@expose_api
def index( self, trans, **kwd ):
"""
- index( trans, state=None )
+ index( trans, state=None, tool_id=None, history_id=None )
* GET /api/jobs:
return jobs for current user
@@ -31,6 +32,12 @@
Valid Galaxy job states include:
'new', 'upload', 'waiting', 'queued', 'running', 'ok', 'error', 'paused', 'deleted', 'deleted_new'
+ :type tool_id: string or list
+ :param tool_id: limit listing of jobs to those that match one of the included tool_ids. If none, all are returned.
+
+ :type history_id: string
+ :param history_id: limit listing of jobs to those that match the history_id. If none, all are returned.
+
:rtype: list
:returns: list of dictionaries containing summary job information
"""
@@ -39,14 +46,30 @@
query = trans.sa_session.query( trans.app.model.Job ).filter(
trans.app.model.Job.user == trans.user
)
- if state is not None:
- if isinstance( state, basestring ):
- query = query.filter( trans.app.model.Job.state == state )
- elif isinstance( state, list ):
- t = []
- for s in state:
- t.append( trans.app.model.Job.state == s )
- query = query.filter( or_( *t ) )
+
+ def build_and_apply_filters( query, objects, filter_func ):
+ if objects is not None:
+ if isinstance( objects, basestring ):
+ query = query.filter( filter_func( objects ) )
+ elif isinstance( objects, list ):
+ t = []
+ for obj in objects:
+ t.append( filter_func( obj ) )
+ query = query.filter( or_( *t ) )
+ return query
+
+ query = build_and_apply_filters( query, state, lambda s: trans.app.model.Job.state == s )
+
+ query = build_and_apply_filters( query, kwd.get( 'tool_id', None ), lambda t: trans.app.model.Job.tool_id == t )
+ query = build_and_apply_filters( query, kwd.get( 'tool_id_like', None ), lambda t: trans.app.model.Job.tool_id.like(t) )
+
+ history_id = kwd.get( 'history_id', None )
+ if history_id is not None:
+ try:
+ decoded_history_id = trans.security.decode_id(history_id)
+ query = query.filter( trans.app.model.Job.history_id == decoded_history_id )
+ except:
+ raise exceptions.ObjectAttributeInvalidException()
out = []
for job in query.order_by(
https://bitbucket.org/galaxy/galaxy-central/commits/6d799bd3e8c8/
Changeset: 6d799bd3e8c8
Branch: jjohnson/allow-jobs-to-be-filtered-by-tool_id-and-1391011677231
User: jmchilton
Date: 2014-02-28 17:08:46
Summary: Close branch.
Affected #: 0 files
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: greg: Minor fixes for installing tool dependencies and counting repositories processed during the tool shed's install and test runs.
by commits-noreply@bitbucket.org 28 Feb '14
by commits-noreply@bitbucket.org 28 Feb '14
28 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6a633b37c4c4/
Changeset: 6a633b37c4c4
User: greg
Date: 2014-02-28 14:52:52
Summary: Minor fixes for installing tool dependencies and counting repositories processed during the tool shed's install and test runs.
Affected #: 3 files
diff -r 95517f976cca49f984b89c9fdd5b9208b1a11fcb -r 6a633b37c4c47bba640d05fef72fd73f41ae5086 lib/tool_shed/galaxy_install/tool_dependencies/td_common_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/td_common_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/td_common_util.py
@@ -15,7 +15,7 @@
log = logging.getLogger( __name__ )
# Set no activity timeout to 20 minutes.
-NO_OUTPUT_TIMEOUT = 1200
+NO_OUTPUT_TIMEOUT = 1200.0
class CompressedFile( object ):
@@ -473,7 +473,7 @@
( str( download_url ), NO_OUTPUT_TIMEOUT )
raise Exception( err_msg )
except Exception, e:
- err_msg = err_msg = 'Error downloading from URL %s: %s' % ( str( download_url ), NO_OUTPUT_TIMEOUT )
+ err_msg = err_msg = 'Error downloading from URL\n%s:\n%s' % ( str( download_url ), str( e ) )
raise Exception( err_msg )
finally:
if src:
diff -r 95517f976cca49f984b89c9fdd5b9208b1a11fcb -r 6a633b37c4c47bba640d05fef72fd73f41ae5086 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
@@ -181,6 +181,7 @@
changeset_revision = str( repository_dict.get( 'changeset_revision', '' ) )
print "Processing revision %s of repository %s owned by %s..." % ( changeset_revision, name, owner )
repository_identifier_tup = ( name, owner, changeset_revision )
+ install_and_test_statistics_dict[ 'total_repositories_processed' ] += 1
# Retrieve the stored list of tool_test_results_dicts.
tool_test_results_dicts, error_message = \
install_and_test_base_util.get_tool_test_results_dicts( install_and_test_base_util.galaxy_tool_shed_url,
@@ -215,7 +216,6 @@
start_time = time.time()
tool_test_results_dict = install_and_test_base_util.initialize_tool_tests_results_dict( app, tool_test_results_dict )
repository, error_message = install_and_test_base_util.install_repository( app, repository_dict )
- install_and_test_statistics_dict[ 'total_repositories_processed' ] += 1
if error_message:
remove_tests( app, repository )
# The repository installation failed.
diff -r 95517f976cca49f984b89c9fdd5b9208b1a11fcb -r 6a633b37c4c47bba640d05fef72fd73f41ae5086 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
@@ -112,6 +112,7 @@
changeset_revision = str( repository_dict.get( 'changeset_revision', '' ) )
print "Processing revision %s of repository %s owned by %s..." % ( changeset_revision, name, owner )
repository_identifier_tup = ( name, owner, changeset_revision )
+ install_and_test_statistics_dict[ 'total_repositories_processed' ] += 1
# Retrieve the stored list of tool_test_results_dicts.
tool_test_results_dicts, error_message = \
install_and_test_base_util.get_tool_test_results_dicts( install_and_test_base_util.galaxy_tool_shed_url,
@@ -146,7 +147,6 @@
start_time = time.time()
tool_test_results_dict = install_and_test_base_util.initialize_tool_tests_results_dict( app, tool_test_results_dict )
repository, error_message = install_and_test_base_util.install_repository( app, repository_dict )
- install_and_test_statistics_dict[ 'total_repositories_processed' ] += 1
if error_message:
# The repository installation failed.
print 'Installation failed for revision %s of repository %s owned by %s.' % ( changeset_revision, name, owner )
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/507055a4ddc4/
Changeset: 507055a4ddc4
User: jeremy goecks
Date: 2014-02-27 22:56:03
Summary: Trackster: track mouse with vertical line to support visual alignment.
Affected #: 3 files
diff -r cb00a217028c903a0868bad0b370b325893eb708 -r 507055a4ddc4dc226d976e735e48b77c9151877b static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -1091,8 +1091,7 @@
}
});
- // Dragging in the top label track allows selecting a region
- // to zoom in
+ // Dragging in the top label track allows selecting a region to zoom in on selected region.
this.top_labeltrack.bind( "dragstart", function( e, d ) {
return $("<div/>").addClass('zoom-area').css(
"height", view.browser_content_div.height() + view.top_labeltrack.height() + view.nav_labeltrack.height() + 1
@@ -1116,6 +1115,27 @@
$(d.proxy).remove();
view.request_redraw();
});
+
+ // For vertical alignment, track mouse with simple line.
+ var mouse_tracker_div = $('<div/>').addClass('mouse-pos').appendTo(parent_element);
+
+ // Show tracker only when hovering over view.
+ parent_element.hover(
+ function() {
+ mouse_tracker_div.show();
+ parent_element.mousemove(function(e) {
+ mouse_tracker_div.css({
+ // -1 makes it appear next to the mouse w/o obscuring clicking
+ // and dragging on view elements.
+ left: e.pageX - 1
+ });
+ });
+ },
+ function() {
+ parent_element.off('mousemove');
+ mouse_tracker_div.hide();
+ }
+ );
this.add_label_track( new LabelTrack( this, { content_div: this.top_labeltrack } ) );
this.add_label_track( new LabelTrack( this, { content_div: this.nav_labeltrack } ) );
diff -r cb00a217028c903a0868bad0b370b325893eb708 -r 507055a4ddc4dc226d976e735e48b77c9151877b static/style/blue/trackster.css
--- a/static/style/blue/trackster.css
+++ b/static/style/blue/trackster.css
@@ -79,5 +79,6 @@
.feature-popup{position:absolute;z-index:2;padding:5px;font-size:10px;filter:alpha(opacity=80);background-repeat:no-repeat;background-image:url(../images/tipsy.gif);background-position:top center}
.feature-popup-inner{padding:5px 8px 4px 8px;background-color:black;color:white}
.zoom-area{position:absolute;top:0px;background-color:#ccf;opacity:0.5;z-index:2}
+.mouse-pos{position:absolute;top:0px;background-color:black;opacity:0.15;height:100%;width:1px}
.draghandle{margin-top:2px;cursor:move;float:left;background:transparent url(../images/visualization/draggable_horizontal.png) center center no-repeat;width:10px;height:12px}
.dragging{border:1px solid blue}
diff -r cb00a217028c903a0868bad0b370b325893eb708 -r 507055a4ddc4dc226d976e735e48b77c9151877b static/style/src/less/trackster.less
--- a/static/style/src/less/trackster.less
+++ b/static/style/src/less/trackster.less
@@ -531,6 +531,15 @@
z-index: @overlay-index;
}
+.mouse-pos {
+ position: absolute;
+ top: 0px;
+ background-color: black;
+ opacity: 0.15;
+ height: 100%;
+ width: 1px;
+}
+
.draghandle {
margin-top: 2px;
cursor: move;
https://bitbucket.org/galaxy/galaxy-central/commits/95517f976cca/
Changeset: 95517f976cca
User: jeremy goecks
Date: 2014-02-27 22:56:25
Summary: Automated merge
Affected #: 2 files
diff -r 507055a4ddc4dc226d976e735e48b77c9151877b -r 95517f976cca49f984b89c9fdd5b9208b1a11fcb 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
@@ -5,6 +5,7 @@
import os
import Queue
import shutil
+import stat
import subprocess
import sys
import tempfile
@@ -72,10 +73,10 @@
self.install_dir = install_dir
self.return_code = 0
- def append_line( self, skip_if_contained=True, make_executable=True, **kwd ):
+ def append_line( self, make_executable=True, **kwd ):
env_var_dict = dict( **kwd )
env_entry, env_file = self.create_or_update_env_shell_file( self.install_dir, env_var_dict )
- return_code = file_append( env_entry, env_file, skip_if_contained=skip_if_contained, make_executable=make_executable )
+ return_code = file_append( env_entry, env_file, make_executable=make_executable )
self.return_code = self.return_code or return_code
return self.return_code
@@ -194,42 +195,56 @@
stderr_queue.put( output )
stderr_queue.put( None )
-def file_append( text, file_path, skip_if_contained=True, make_executable=True ):
+def file_append( text, file_path, make_executable=True ):
"""
- Append a line to a file unless skip_if_contained is True and the line already exists in the file.
- This method creates the file if it doesn't exist. If make_executable is True, the permissions on
- the file are set to executable by the owner.
+ Append a line to a file unless the line already exists in the file. This method creates the file if
+ it doesn't exist. If make_executable is True, the permissions on the file are set to executable by
+ the owner.
"""
- if not os.path.exists( file_path ):
- return_code = handle_simple_command( 'touch %s' % file_path )
- if return_code:
- return return_code
+ file_dir = os.path.dirname( file_path )
+ if not os.path.exists( file_dir ):
+ try:
+ os.makedirs( file_dir )
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
+ if os.path.exists( file_path ):
+ try:
+ new_env_file_contents = []
+ env_file_contents = file( file_path, 'a+' ).readlines()
+ # Clean out blank lines from the env.sh file.
+ for line in env_file_contents:
+ line = line.rstrip()
+ if line:
+ new_env_file_contents.append( line )
+ env_file_contents = new_env_file_contents
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
+ else:
+ env_file_handle = open( file_path, 'w' )
+ env_file_handle.close()
+ env_file_contents = []
if make_executable:
- # Explicitly set the file to the received mode if valid.
- with settings( hide( 'everything' ), warn_only=True ):
- return_code = handle_simple_command( 'chmod +x %s' % file_path )
- if return_code:
- return return_code
+ # Explicitly set the file's executable bits.
+ try:
+ os.chmod( file_path, int( '111', base=8) | os.stat( file_path )[ stat.ST_MODE ] )
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
return_code = 0
# Convert the received text to a list, in order to support adding one or more lines to the file.
if isinstance( text, basestring ):
text = [ text ]
for line in text:
- # Build a regex to search for the relevant line in env.sh.
- regex = td_common_util.egrep_escape( line )
- if skip_if_contained:
- # If the line exists in the file, egrep will return a success.
- with settings( hide( 'everything' ), warn_only=True ):
- egrep_cmd = 'egrep "^%s$" %s' % ( regex, file_path )
- return_code = handle_simple_command( egrep_cmd )
- if return_code == 0:
- continue
- # Append the current line to the file, escaping any single quotes in the line.
- line = line.replace( "'", r"'\\''" )
- return_code = handle_simple_command( "echo '%s' >> %s" % ( line, file_path ) )
- if return_code:
- # Return upon the first error encountered.
- return return_code
+ line = line.rstrip()
+ if line not in env_file_contents:
+ env_file_contents.append( line )
+ try:
+ file( file_path, 'w' ).write( '\n'.join( env_file_contents ) )
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
return return_code
def filter_actions_after_binary_installation( actions ):
@@ -278,8 +293,8 @@
"""
Wrap subprocess.Popen in such a way that the stderr and stdout from running a shell command will
be captured and logged in nearly real time. This is similar to fabric.local, but allows us to
- retain control over the process. This method is considered "complex" because it uses queues and
- threads - see handle_simple_command().
+ retain control over the process. This method is named "complex" because it uses queues and
+ threads to execute a command while capturing and displaying the output.
"""
wrapped_command = shlex.split( "/bin/sh -c '%s'" % str( command ) )
# Launch the command as subprocess. A bufsize of 1 means line buffered.
@@ -456,30 +471,6 @@
env_var_dict[ 'value' ] = env_var_value
return env_var_dict
-def handle_simple_command( command ):
- """
- Use this instead of fabric.local to retain control over the process spawned to run the
- received command.
- """
- wrapped_command = shlex.split( "/bin/sh -c '%s'" % str( command ) )
- # Launch the command as subprocess. A bufsize of 1 means line buffered.
- try:
- process_handle = subprocess.Popen( wrapped_command,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- bufsize=1,
- close_fds=False,
- cwd=state.env[ 'lcwd' ] )
- except OSError, e:
- # We don't have a working directory.
- process_handle = subprocess.Popen( wrapped_command,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE )
- stdout, stderr = process_handle.communicate()
- if stderr:
- log.debug( "Problem executing command %s: %s." % ( wrapped_command, stderr ) )
- return process_handle.returncode
-
def install_virtualenv( app, venv_dir ):
if not os.path.exists( venv_dir ):
with make_tmp_dir() as work_dir:
@@ -951,7 +942,10 @@
work_dir = tempfile.mkdtemp( prefix="tmp-toolshed-mtd" )
yield work_dir
if os.path.exists( work_dir ):
- return_code = handle_simple_command( 'rm -rf %s' % work_dir )
+ try:
+ shutil.rmtree( work_dir )
+ except Exception, e:
+ log.exception( str( e ) )
def set_galaxy_environment( galaxy_user, tool_dependency_dir, host='localhost', shell='/bin/bash -l -c' ):
"""General Galaxy environment configuration. This method is not currently used."""
diff -r 507055a4ddc4dc226d976e735e48b77c9151877b -r 95517f976cca49f984b89c9fdd5b9208b1a11fcb lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
@@ -884,7 +884,7 @@
if env_var_version == '1.0':
# Create this tool dependency's env.sh file.
env_file_builder = fabric_util.EnvFileBuilder( install_dir )
- return_code = env_file_builder.append_line( skip_if_contained=True, make_executable=True, **env_var_dict )
+ return_code = env_file_builder.append_line( make_executable=True, **env_var_dict )
if return_code:
error_message = 'Error creating env.sh file for tool dependency %s, return_code: %s' % \
( str( tool_dependency.name ), str( return_code ) )
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: Eliminate the use of shell commands to perform functions that can be done internally with the elimination of fabric.local for tool dependency installation.
by commits-noreply@bitbucket.org 27 Feb '14
by commits-noreply@bitbucket.org 27 Feb '14
27 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/739287adeac8/
Changeset: 739287adeac8
User: davebgx
Date: 2014-02-27 21:46:03
Summary: Eliminate the use of shell commands to perform functions that can be done internally with the elimination of fabric.local for tool dependency installation.
Affected #: 2 files
diff -r cb00a217028c903a0868bad0b370b325893eb708 -r 739287adeac8561c32d6dcf24d7eb9309d992da3 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
@@ -5,6 +5,7 @@
import os
import Queue
import shutil
+import stat
import subprocess
import sys
import tempfile
@@ -72,10 +73,10 @@
self.install_dir = install_dir
self.return_code = 0
- def append_line( self, skip_if_contained=True, make_executable=True, **kwd ):
+ def append_line( self, make_executable=True, **kwd ):
env_var_dict = dict( **kwd )
env_entry, env_file = self.create_or_update_env_shell_file( self.install_dir, env_var_dict )
- return_code = file_append( env_entry, env_file, skip_if_contained=skip_if_contained, make_executable=make_executable )
+ return_code = file_append( env_entry, env_file, make_executable=make_executable )
self.return_code = self.return_code or return_code
return self.return_code
@@ -194,42 +195,56 @@
stderr_queue.put( output )
stderr_queue.put( None )
-def file_append( text, file_path, skip_if_contained=True, make_executable=True ):
+def file_append( text, file_path, make_executable=True ):
"""
- Append a line to a file unless skip_if_contained is True and the line already exists in the file.
- This method creates the file if it doesn't exist. If make_executable is True, the permissions on
- the file are set to executable by the owner.
+ Append a line to a file unless the line already exists in the file. This method creates the file if
+ it doesn't exist. If make_executable is True, the permissions on the file are set to executable by
+ the owner.
"""
- if not os.path.exists( file_path ):
- return_code = handle_simple_command( 'touch %s' % file_path )
- if return_code:
- return return_code
+ file_dir = os.path.dirname( file_path )
+ if not os.path.exists( file_dir ):
+ try:
+ os.makedirs( file_dir )
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
+ if os.path.exists( file_path ):
+ try:
+ new_env_file_contents = []
+ env_file_contents = file( file_path, 'a+' ).readlines()
+ # Clean out blank lines from the env.sh file.
+ for line in env_file_contents:
+ line = line.rstrip()
+ if line:
+ new_env_file_contents.append( line )
+ env_file_contents = new_env_file_contents
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
+ else:
+ env_file_handle = open( file_path, 'w' )
+ env_file_handle.close()
+ env_file_contents = []
if make_executable:
- # Explicitly set the file to the received mode if valid.
- with settings( hide( 'everything' ), warn_only=True ):
- return_code = handle_simple_command( 'chmod +x %s' % file_path )
- if return_code:
- return return_code
+ # Explicitly set the file's executable bits.
+ try:
+ os.chmod( file_path, int( '111', base=8) | os.stat( file_path )[ stat.ST_MODE ] )
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
return_code = 0
# Convert the received text to a list, in order to support adding one or more lines to the file.
if isinstance( text, basestring ):
text = [ text ]
for line in text:
- # Build a regex to search for the relevant line in env.sh.
- regex = td_common_util.egrep_escape( line )
- if skip_if_contained:
- # If the line exists in the file, egrep will return a success.
- with settings( hide( 'everything' ), warn_only=True ):
- egrep_cmd = 'egrep "^%s$" %s' % ( regex, file_path )
- return_code = handle_simple_command( egrep_cmd )
- if return_code == 0:
- continue
- # Append the current line to the file, escaping any single quotes in the line.
- line = line.replace( "'", r"'\\''" )
- return_code = handle_simple_command( "echo '%s' >> %s" % ( line, file_path ) )
- if return_code:
- # Return upon the first error encountered.
- return return_code
+ line = line.rstrip()
+ if line not in env_file_contents:
+ env_file_contents.append( line )
+ try:
+ file( file_path, 'w' ).write( '\n'.join( env_file_contents ) )
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
return return_code
def filter_actions_after_binary_installation( actions ):
@@ -278,8 +293,8 @@
"""
Wrap subprocess.Popen in such a way that the stderr and stdout from running a shell command will
be captured and logged in nearly real time. This is similar to fabric.local, but allows us to
- retain control over the process. This method is considered "complex" because it uses queues and
- threads - see handle_simple_command().
+ retain control over the process. This method is named "complex" because it uses queues and
+ threads to execute a command while capturing and displaying the output.
"""
wrapped_command = shlex.split( "/bin/sh -c '%s'" % str( command ) )
# Launch the command as subprocess. A bufsize of 1 means line buffered.
@@ -456,30 +471,6 @@
env_var_dict[ 'value' ] = env_var_value
return env_var_dict
-def handle_simple_command( command ):
- """
- Use this instead of fabric.local to retain control over the process spawned to run the
- received command.
- """
- wrapped_command = shlex.split( "/bin/sh -c '%s'" % str( command ) )
- # Launch the command as subprocess. A bufsize of 1 means line buffered.
- try:
- process_handle = subprocess.Popen( wrapped_command,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- bufsize=1,
- close_fds=False,
- cwd=state.env[ 'lcwd' ] )
- except OSError, e:
- # We don't have a working directory.
- process_handle = subprocess.Popen( wrapped_command,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE )
- stdout, stderr = process_handle.communicate()
- if stderr:
- log.debug( "Problem executing command %s: %s." % ( wrapped_command, stderr ) )
- return process_handle.returncode
-
def install_virtualenv( app, venv_dir ):
if not os.path.exists( venv_dir ):
with make_tmp_dir() as work_dir:
@@ -951,7 +942,10 @@
work_dir = tempfile.mkdtemp( prefix="tmp-toolshed-mtd" )
yield work_dir
if os.path.exists( work_dir ):
- return_code = handle_simple_command( 'rm -rf %s' % work_dir )
+ try:
+ shutil.rmtree( work_dir )
+ except Exception, e:
+ log.exception( str( e ) )
def set_galaxy_environment( galaxy_user, tool_dependency_dir, host='localhost', shell='/bin/bash -l -c' ):
"""General Galaxy environment configuration. This method is not currently used."""
diff -r cb00a217028c903a0868bad0b370b325893eb708 -r 739287adeac8561c32d6dcf24d7eb9309d992da3 lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
@@ -884,7 +884,7 @@
if env_var_version == '1.0':
# Create this tool dependency's env.sh file.
env_file_builder = fabric_util.EnvFileBuilder( install_dir )
- return_code = env_file_builder.append_line( skip_if_contained=True, make_executable=True, **env_var_dict )
+ return_code = env_file_builder.append_line( make_executable=True, **env_var_dict )
if return_code:
error_message = 'Error creating env.sh file for tool dependency %s, return_code: %s' % \
( str( tool_dependency.name ), str( return_code ) )
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: greg: Improve time management and process handling when installing repositories and tool dependencies from the tool shed and completely eliminate the tuse of fabric.local when installing tool dependencies.
by commits-noreply@bitbucket.org 27 Feb '14
by commits-noreply@bitbucket.org 27 Feb '14
27 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/cb00a217028c/
Changeset: cb00a217028c
User: greg
Date: 2014-02-27 18:14:53
Summary: Improve time management and process handling when installing repositories and tool dependencies from the tool shed and completely eliminate the tuse of fabric.local when installing tool dependencies.
Affected #: 2 files
diff -r a3db4f68660384e96212f7ebb0ff1856db40278b -r cb00a217028c903a0868bad0b370b325893eb708 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
@@ -29,7 +29,6 @@
from fabric.api import env
from fabric.api import hide
from fabric.api import lcd
-from fabric.api import local
from fabric.api import settings
from fabric.api import prefix
from fabric.operations import _AttributeString
@@ -37,7 +36,6 @@
log = logging.getLogger( __name__ )
INSTALLATION_LOG = 'INSTALLATION.log'
-NO_CMD_OUTPUT_TIMEOUT = 600.0
VIRTUALENV_URL = 'https://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.9.1.tar.gz'
@@ -55,10 +53,13 @@
def run( self ):
"""Read lines and put them on the queue."""
+ thread_lock = threading.Lock()
+ thread_lock.acquire()
for line in iter( self._fd.readline, '' ):
stripped_line = line.rstrip()
self.lines.append( stripped_line )
self._queue.put( stripped_line )
+ thread_lock.release()
def installation_complete( self ):
"""Make sure there is more installation and compilation logging content expected."""
@@ -156,6 +157,24 @@
if int( version.split( "." )[ 0 ] ) < 1:
raise NotImplementedError( "Install Fabric version 1.0 or later." )
+def close_file_descriptor( fd ):
+ """Attempt to close a file descriptor."""
+ start_timer = time.time()
+ error = ''
+ while True:
+ try:
+ fd.close()
+ break
+ except IOError, e:
+ # Undoubtedly close() was called during a concurrent operation on the same file object.
+ log.debug( 'Error closing file descriptor: %s' % str( e ) )
+ time.sleep( .5 )
+ current_wait_time = time.time() - start_timer
+ if current_wait_time >= 600:
+ error = 'Error closing file descriptor: %s' % str( e )
+ break
+ return error
+
def enqueue_output( stdout, stdout_queue, stderr, stderr_queue ):
"""
This method places streamed stdout and stderr into a threaded IPC queue target. Received data
@@ -177,16 +196,20 @@
def file_append( text, file_path, skip_if_contained=True, make_executable=True ):
"""
- Append a line to a file unless skip_if_contained is True and the line already exists in the file. This method creates the file
- if it doesn't exist. If make_executable is True, the permissions on the file are set to executable by the owner. This method
- is similar to a local version of fabric.contrib.files.append.
+ Append a line to a file unless skip_if_contained is True and the line already exists in the file.
+ This method creates the file if it doesn't exist. If make_executable is True, the permissions on
+ the file are set to executable by the owner.
"""
if not os.path.exists( file_path ):
- local( 'touch %s' % file_path )
+ return_code = handle_simple_command( 'touch %s' % file_path )
+ if return_code:
+ return return_code
if make_executable:
# Explicitly set the file to the received mode if valid.
with settings( hide( 'everything' ), warn_only=True ):
- local( 'chmod +x %s' % file_path )
+ return_code = handle_simple_command( 'chmod +x %s' % file_path )
+ if return_code:
+ return return_code
return_code = 0
# Convert the received text to a list, in order to support adding one or more lines to the file.
if isinstance( text, basestring ):
@@ -198,12 +221,12 @@
# If the line exists in the file, egrep will return a success.
with settings( hide( 'everything' ), warn_only=True ):
egrep_cmd = 'egrep "^%s$" %s' % ( regex, file_path )
- contains_line = local( egrep_cmd ).succeeded
- if contains_line:
+ return_code = handle_simple_command( egrep_cmd )
+ if return_code == 0:
continue
# Append the current line to the file, escaping any single quotes in the line.
line = line.replace( "'", r"'\\''" )
- return_code = local( "echo '%s' >> %s" % ( line, file_path ) ).return_code
+ return_code = handle_simple_command( "echo '%s' >> %s" % ( line, file_path ) )
if return_code:
# Return upon the first error encountered.
return return_code
@@ -225,7 +248,7 @@
def handle_command( app, tool_dependency, install_dir, cmd, return_output=False ):
context = app.install_model.context
- output = run_local_command( cmd )
+ output = handle_complex_command( cmd )
log_results( cmd, output, os.path.join( install_dir, INSTALLATION_LOG ) )
stdout = output.stdout
stderr = output.stderr
@@ -251,6 +274,96 @@
return output
return output.return_code
+def handle_complex_command( command ):
+ """
+ Wrap subprocess.Popen in such a way that the stderr and stdout from running a shell command will
+ be captured and logged in nearly real time. This is similar to fabric.local, but allows us to
+ retain control over the process. This method is considered "complex" because it uses queues and
+ threads - see handle_simple_command().
+ """
+ wrapped_command = shlex.split( "/bin/sh -c '%s'" % str( command ) )
+ # Launch the command as subprocess. A bufsize of 1 means line buffered.
+ process_handle = subprocess.Popen( wrapped_command,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ bufsize=1,
+ close_fds=False,
+ cwd=state.env[ 'lcwd' ] )
+ pid = process_handle.pid
+ # Launch the asynchronous readers of the process' stdout and stderr.
+ stdout_queue = Queue.Queue()
+ stdout_reader = AsynchronousReader( process_handle.stdout, stdout_queue )
+ stdout_reader.start()
+ stderr_queue = Queue.Queue()
+ stderr_reader = AsynchronousReader( process_handle.stderr, stderr_queue )
+ stderr_reader.start()
+ # Place streamed stdout and stderr into a threaded IPC queue target so it can
+ # be printed and stored for later retrieval when generating the INSTALLATION.log.
+ stdio_thread = threading.Thread( target=enqueue_output,
+ args=( process_handle.stdout,
+ stdout_queue,
+ process_handle.stderr,
+ stderr_queue ) )
+ thread_lock = threading.Lock()
+ thread_lock.acquire()
+ stdio_thread.start()
+ # Check the queues for output until there is nothing more to get.
+ start_timer = time.time()
+ while not stdout_reader.installation_complete() or not stderr_reader.installation_complete():
+ # Show what we received from standard output.
+ while not stdout_queue.empty():
+ try:
+ line = stdout_queue.get()
+ except Queue.Empty:
+ line = None
+ break
+ if line:
+ print line
+ start_timer = time.time()
+ else:
+ break
+ # Show what we received from standard error.
+ while not stderr_queue.empty():
+ try:
+ line = stderr_queue.get()
+ except Queue.Empty:
+ line = None
+ break
+ if line:
+ print line
+ start_timer = time.time()
+ else:
+ stderr_queue.task_done()
+ break
+ # Sleep a bit before asking the readers again.
+ time.sleep( .1 )
+ current_wait_time = time.time() - start_timer
+ if stdout_queue.empty() and stderr_queue.empty() and current_wait_time > td_common_util.NO_OUTPUT_TIMEOUT:
+ err_msg = "\nShutting down process id %s because it generated no output for the defined timeout period of %.1f seconds.\n" % \
+ ( pid, td_common_util.NO_OUTPUT_TIMEOUT )
+ stderr_reader.lines.append( err_msg )
+ process_handle.kill()
+ break
+ thread_lock.release()
+ # Wait until each of the threads we've started terminate. The following calls will block each thread
+ # until it terminates either normally, through an unhandled exception, or until the timeout occurs.
+ stdio_thread.join( td_common_util.NO_OUTPUT_TIMEOUT )
+ stdout_reader.join( td_common_util.NO_OUTPUT_TIMEOUT )
+ stderr_reader.join( td_common_util.NO_OUTPUT_TIMEOUT )
+ # Close subprocess' file descriptors.
+ error = close_file_descriptor( process_handle.stdout )
+ error = close_file_descriptor( process_handle.stderr )
+ stdout = '\n'.join( stdout_reader.lines )
+ stderr = '\n'.join( stderr_reader.lines )
+ # Handle error condition (deal with stdout being None, too)
+ output = _AttributeString( stdout.strip() if stdout else "" )
+ errors = _AttributeString( stderr.strip() if stderr else "" )
+ # Make sure the process has finished.
+ process_handle.poll()
+ output.return_code = process_handle.returncode
+ output.stderr = errors
+ return output
+
def handle_environment_variables( app, tool_dependency, install_dir, env_var_dict, set_prior_environment_commands ):
"""
This method works with with a combination of three tool dependency definition tag sets, which are defined in the tool_dependencies.xml file in the
@@ -343,6 +456,30 @@
env_var_dict[ 'value' ] = env_var_value
return env_var_dict
+def handle_simple_command( command ):
+ """
+ Use this instead of fabric.local to retain control over the process spawned to run the
+ received command.
+ """
+ wrapped_command = shlex.split( "/bin/sh -c '%s'" % str( command ) )
+ # Launch the command as subprocess. A bufsize of 1 means line buffered.
+ try:
+ process_handle = subprocess.Popen( wrapped_command,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ bufsize=1,
+ close_fds=False,
+ cwd=state.env[ 'lcwd' ] )
+ except OSError, e:
+ # We don't have a working directory.
+ process_handle = subprocess.Popen( wrapped_command,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE )
+ stdout, stderr = process_handle.communicate()
+ if stderr:
+ log.debug( "Problem executing command %s: %s." % ( wrapped_command, stderr ) )
+ return process_handle.returncode
+
def install_virtualenv( app, venv_dir ):
if not os.path.exists( venv_dir ):
with make_tmp_dir() as work_dir:
@@ -623,8 +760,6 @@
# </action>
filtered_actions = [ a for a in actions ]
dir = install_dir
- # We need to be careful in determining if the value of dir is a valid directory because we're dealing with 2 environments, the fabric local
- # environment and the python environment. Checking the path as follows should work.
full_path_to_dir = os.path.abspath( os.path.join( work_dir, dir ) )
if not os.path.exists( full_path_to_dir ):
os.makedirs( full_path_to_dir )
@@ -795,8 +930,7 @@
def log_results( command, fabric_AttributeString, file_path ):
"""
- Write attributes of fabric.operations._AttributeString (which is the output of executing command using fabric's local() method)
- to a specified log file.
+ Write attributes of fabric.operations._AttributeString to a specified log file.
"""
if os.path.exists( file_path ):
logfile = open( file_path, 'ab' )
@@ -817,104 +951,7 @@
work_dir = tempfile.mkdtemp( prefix="tmp-toolshed-mtd" )
yield work_dir
if os.path.exists( work_dir ):
- local( 'rm -rf %s' % work_dir )
-
-def run_local_command( command ):
- """
- Wrap subprocess.Popen in such a way that the stderr and stdout from running a shell command will
- be captured and logged in nearly real time. This is similar to fabric.local, but allows us to
- retain control over the process.
- """
- wrapped_command = shlex.split( "/bin/sh -c '%s'" % str( command ) )
- # Launch the command as subprocess. A bufsize of 1 means line buffered.
- process_handle = subprocess.Popen( wrapped_command,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- bufsize=1,
- close_fds=False,
- cwd=state.env[ 'lcwd' ] )
- pid = process_handle.pid
- # Launch the asynchronous readers of the process' stdout and stderr.
- stdout_queue = Queue.Queue()
- stdout_reader = AsynchronousReader( process_handle.stdout, stdout_queue )
- stdout_reader.start()
- stderr_queue = Queue.Queue()
- stderr_reader = AsynchronousReader( process_handle.stderr, stderr_queue )
- stderr_reader.start()
- # Place streamed stdout and stderr into a threaded IPC queue target so it can
- # be printed and stored for later retrieval when generating the INSTALLATION.log.
- stdio_thread = threading.Thread( target=enqueue_output,
- args=( process_handle.stdout,
- stdout_queue,
- process_handle.stderr,
- stderr_queue ) )
- stdio_thread.start()
- # Check the queues for output until there is nothing more to get.
- start_timer = time.time()
- while not stdout_reader.installation_complete() or not stderr_reader.installation_complete():
- # Show what we received from standard output.
- while not stdout_queue.empty():
- try:
- line = stdout_queue.get()
- 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
- stdout_reader.lines.append( err_msg )
- # Close subprocess' file descriptors.
- process_handle.stdout.close()
- process_handle.stderr.close()
- process_handle.kill()
- line = None
- break
- if line:
- print line
- start_timer = time.time()
- else:
- break
- # Show what we received from standard error.
- while not stderr_queue.empty():
- try:
- line = stderr_queue.get()
- 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
- stderr_reader.lines.append( err_msg )
- # Close subprocess' file descriptor.
- process_handle.stdout.close()
- process_handle.stderr.close()
- process_handle.kill()
- line = None
- break
- if line:
- print line
- start_timer = time.time()
- else:
- stderr_queue.task_done()
- break
- # Sleep a bit before asking the readers again.
- time.sleep( .1 )
- current_wait_time = time.time() - start_timer
- if stdout_queue.empty() and stderr_queue.empty() and current_wait_time < NO_CMD_OUTPUT_TIMEOUT:
- break
- # Wait until each of the threads we've started terminate. The following calls will block each thread
- # until it terminates either normally, through an unhandled exception, or until the timeout occurs.
- stdio_thread.join( NO_CMD_OUTPUT_TIMEOUT )
- stdout_reader.join( NO_CMD_OUTPUT_TIMEOUT )
- stderr_reader.join( NO_CMD_OUTPUT_TIMEOUT )
- # Close subprocess' file descriptors.
- process_handle.stdout.close()
- process_handle.stderr.close()
- stdout = '\n'.join( stdout_reader.lines )
- stderr = '\n'.join( stderr_reader.lines )
- # Handle error condition (deal with stdout being None, too)
- output = _AttributeString( stdout.strip() if stdout else "" )
- errors = _AttributeString( stderr.strip() if stderr else "" )
- process_handle.poll()
- output.return_code = process_handle.returncode
- output.stderr = errors
- return output
+ return_code = handle_simple_command( 'rm -rf %s' % work_dir )
def set_galaxy_environment( galaxy_user, tool_dependency_dir, host='localhost', shell='/bin/bash -l -c' ):
"""General Galaxy environment configuration. This method is not currently used."""
@@ -923,5 +960,4 @@
env.host_string = host
env.shell = shell
env.use_sudo = False
- env.safe_cmd = local
return env
diff -r a3db4f68660384e96212f7ebb0ff1856db40278b -r cb00a217028c903a0868bad0b370b325893eb708 lib/tool_shed/galaxy_install/tool_dependencies/td_common_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/td_common_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/td_common_util.py
@@ -4,6 +4,7 @@
import shutil
import sys
import tarfile
+import time
import traceback
import urllib2
import zipfile
@@ -13,9 +14,12 @@
log = logging.getLogger( __name__ )
+# Set no activity timeout to 20 minutes.
+NO_OUTPUT_TIMEOUT = 1200
+
class CompressedFile( object ):
-
+
def __init__( self, file_path, mode='r' ):
if istar( file_path ):
self.file_type = 'tar'
@@ -30,7 +34,7 @@
self.archive = getattr( self, method )( file_path, mode )
else:
raise NameError( 'File type %s specified, no open method found.' % self.file_type )
-
+
def extract( self, path ):
'''Determine the path to which the archive should be extracted.'''
contents = self.getmembers()
@@ -58,36 +62,36 @@
os.makedirs( extraction_path )
self.archive.extractall( os.path.join( extraction_path ) )
return os.path.abspath( extraction_path )
-
+
def getmembers_tar( self ):
return self.archive.getmembers()
-
+
def getmembers_zip( self ):
return self.archive.infolist()
-
+
def getname_tar( self, item ):
return item.name
-
+
def getname_zip( self, item ):
return item.filename
-
+
def getmember( self, name ):
for member in self.getmembers():
if self.getname( member ) == name:
return member
-
+
def getmembers( self ):
return getattr( self, 'getmembers_%s' % self.type )()
-
+
def getname( self, member ):
return getattr( self, 'getname_%s' % self.type )( member )
-
+
def isdir( self, member ):
return getattr( self, 'isdir_%s' % self.type )( member )
-
+
def isdir_tar( self, member ):
return member.isdir()
-
+
def isdir_zip( self, member ):
if member.filename.endswith( os.sep ):
return True
@@ -97,7 +101,7 @@
if not self.isdir( member ):
return True
return False
-
+
def open_tar( self, filepath, mode ):
return tarfile.open( filepath, mode, errorlevel=0 )
@@ -146,9 +150,7 @@
return None
def download_binary( url, work_dir ):
- '''
- Download a pre-compiled binary from the specified URL.
- '''
+ """Download a pre-compiled binary from the specified URL."""
downloaded_filename = os.path.split( url )[ -1 ]
dir = url_download( work_dir, downloaded_filename, url, extract=False )
return downloaded_filename
@@ -179,7 +181,6 @@
return os.path.abspath( os.path.join( root, name ) )
return None
-
def get_env_shell_file_paths( app, elem ):
# Currently only the following tag set is supported.
# <repository toolshed="http://localhost:9009/" name="package_numpy_1_7" owner="test" changeset_revision="c84c6a8be056">
@@ -455,6 +456,8 @@
file_path = os.path.join( install_dir, downloaded_file_name )
src = None
dst = None
+ # Set a timer so we don't sit here forever.
+ start_time = time.time()
try:
src = urllib2.urlopen( download_url )
dst = open( file_path, 'wb' )
@@ -464,8 +467,14 @@
dst.write( chunk )
else:
break
- except:
- raise
+ time_taken = time.time() - start_time
+ if time_taken > NO_OUTPUT_TIMEOUT:
+ err_msg = 'Downloading from URL %s took longer than the defined timeout period of %.1f seconds.' % \
+ ( str( download_url ), NO_OUTPUT_TIMEOUT )
+ raise Exception( err_msg )
+ except Exception, e:
+ err_msg = err_msg = 'Error downloading from URL %s: %s' % ( str( download_url ), NO_OUTPUT_TIMEOUT )
+ raise Exception( err_msg )
finally:
if src:
src.close()
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