diff --git a/client/galaxy/scripts/utils/config.js b/client/galaxy/scripts/utils/config.js index b1a5457eb0e..e060743d978 100644 --- a/client/galaxy/scripts/utils/config.js +++ b/client/galaxy/scripts/utils/config.js @@ -1,6 +1,10 @@ import * as _ from "libs/underscore"; +import * as Backbone from "libs/backbone"; import util_mod from "viz/trackster/util"; -import config_mod from "utils/config"; + +/* global $ */ +/* global Galaxy */ + /** * A configuration setting. Currently key is used as id. */ @@ -307,23 +311,22 @@ var ConfigSettingCollectionView = Backbone.View.extend({ // No propagation to avoid triggering document click (and tip hiding) above. e.stopPropagation(); }); - - var // Icon for setting a new random color; behavior set below. - new_color_icon = $("") + // Icon for setting a new random color; behavior set below. + var new_color_icon = $("") .addClass("icon-button arrow-circle") .appendTo(container_div) .attr("title", "Set new random color") .tooltip(); - var // Color picker in tool tip style. - tip = $("
") + // Color picker in tool tip style. + var tip = $("
") .appendTo(container_div) .hide(); - var // Inner div for padding purposes - tip_inner = $("
").appendTo(tip); + // Inner div for padding purposes + var tip_inner = $("
").appendTo(tip); - var tip_arrow = $("
").appendTo(tip); + $("
").appendTo(tip); var farb_obj = $.farbtastic(tip_inner, { width: 100, diff --git a/client/galaxy/scripts/viz/trackster.js b/client/galaxy/scripts/viz/trackster.js index 8640cce51f6..2b85b4a85ef 100644 --- a/client/galaxy/scripts/viz/trackster.js +++ b/client/galaxy/scripts/viz/trackster.js @@ -1,15 +1,15 @@ -import _l from "utils/localization"; /** * Top-level trackster code, used for creating/loading visualizations and user interface elements. */ -//import * as $ from 'jquery'; +import _l from "utils/localization"; import * as _ from "libs/underscore"; +import * as Backbone from "libs/backbone"; import tracks from "viz/trackster/tracks"; import visualization from "viz/visualization"; -import mod_icon_btn from "mvc/ui/icon-button"; +import IconButton from "mvc/ui/icon-button"; import query_string from "utils/query-string-parsing"; import GridView from "mvc/grid/grid-view"; -import mod_utils from "utils/utils"; +import Utils from "utils/utils"; import "libs/jquery/jquery.event.drag"; import "libs/jquery/jquery.event.hover"; import "libs/jquery/jquery.mousewheel"; @@ -20,44 +20,36 @@ import "libs/jquery/jquery.form"; import "libs/jquery/jquery.rating"; import "ui/editable-text"; -// trackster global variables -var ui = null; -var view = null; -var browser_router = null; - -/** - * Base Object/Model for inhertiance. - */ -var Base = function() { - if (this.initialize) { - this.initialize.apply(this, arguments); - } -}; -Base.extend = Backbone.Model.extend; +/* global Galaxy */ +/* global $ */ /** * User interface controls for trackster */ -var TracksterUI = Base.extend({ - initialize: function(baseURL) { - mod_utils.cssLoadFile("static/style/jquery.rating.css"); - mod_utils.cssLoadFile("static/style/autocomplete_tagging.css"); - mod_utils.cssLoadFile("static/style/jquery-ui/smoothness/jquery-ui.css"); - mod_utils.cssLoadFile("static/style/library.css"); - mod_utils.cssLoadFile("static/style/trackster.css"); +class TracksterUI extends Backbone.Model { + constructor(options) { + super(options); + } + + initialize(baseURL) { this.baseURL = baseURL; - }, + Utils.cssLoadFile("static/style/jquery.rating.css"); + Utils.cssLoadFile("static/style/autocomplete_tagging.css"); + Utils.cssLoadFile("static/style/jquery-ui/smoothness/jquery-ui.css"); + Utils.cssLoadFile("static/style/library.css"); + Utils.cssLoadFile("static/style/trackster.css"); + } /** * Save visualization, returning a Deferred object for the remote call to save. */ - save_viz: function() { + save_viz() { // show dialog Galaxy.modal.show({ title: "Saving...", body: "progress" }); // Save bookmarks. var bookmarks = []; - $(".bookmark").each(function() { + $(".bookmark").each(() => { bookmarks.push({ position: $(this) .children(".position") @@ -69,14 +61,16 @@ var TracksterUI = Base.extend({ }); // FIXME: give unique IDs to Drawables and save overview as ID. - var overview_track_name = view.overview_drawable ? view.overview_drawable.config.get_value("name") : null; + var overview_track_name = this.view.overview_drawable + ? this.view.overview_drawable.config.get_value("name") + : null; var viz_config = { - view: view.to_dict(), + view: this.view.to_dict(), viewport: { - chrom: view.chrom, - start: view.low, - end: view.high, + chrom: this.view.chrom, + start: this.view.low, + end: this.view.high, overview: overview_track_name }, bookmarks: bookmarks @@ -88,17 +82,17 @@ var TracksterUI = Base.extend({ type: "POST", dataType: "json", data: { - id: view.vis_id, - title: view.config.get_value("name"), - dbkey: view.dbkey, + id: this.view.vis_id, + title: this.view.config.get_value("name"), + dbkey: this.view.dbkey, type: "trackster", vis_json: JSON.stringify(viz_config) } }) .success(vis_info => { Galaxy.modal.hide(); - view.vis_id = vis_info.vis_id; - view.has_changes = false; + this.view.vis_id = vis_info.vis_id; + this.view.has_changes = false; // Needed to set URL when first saving a visualization. window.history.pushState({}, "", vis_info.url + window.top.location.hash); @@ -109,29 +103,27 @@ var TracksterUI = Base.extend({ title: _l("Could Not Save"), body: "Could not save visualization. Please try again later.", buttons: { - Cancel: function() { + Cancel: () => { Galaxy.modal.hide(); } } }); }); - }, + } /** * Create button menu */ - createButtonMenu: function() { - var self = this; - - var menu = mod_icon_btn.create_icon_buttons_menu( + createButtonMenu() { + var menu = IconButton.create_icon_buttons_menu( [ { icon_class: "plus-button", title: _l("Add tracks"), - on_click: function() { - visualization.select_datasets({ dbkey: view.dbkey }, new_tracks => { + on_click: () => { + visualization.select_datasets({ dbkey: this.view.dbkey }, new_tracks => { _.each(new_tracks, track => { - view.add_drawable(tracks.object_from_template(track, view, view)); + this.view.add_drawable(tracks.object_from_template(track, this.view, this.view)); }); }); } @@ -139,9 +131,9 @@ var TracksterUI = Base.extend({ { icon_class: "block--plus", title: _l("Add group"), - on_click: function() { - view.add_drawable( - new tracks.DrawableGroup(view, view, { + on_click: () => { + this.view.add_drawable( + new tracks.DrawableGroup(this.view, this.view, { name: "New Group" }) ); @@ -150,7 +142,7 @@ var TracksterUI = Base.extend({ { icon_class: "bookmarks", title: _l("Bookmarks"), - on_click: function() { + on_click: () => { // HACK -- use style to determine if panel is hidden and hide/show accordingly. window.force_right_panel($("div#right").css("right") == "0px" ? "hide" : "show"); } @@ -158,22 +150,22 @@ var TracksterUI = Base.extend({ { icon_class: "globe", title: _l("Circster"), - on_click: function() { - window.top.location = `${self.baseURL}visualization/circster?id=${view.vis_id}`; + on_click: () => { + window.top.location = `${this.baseURL}visualization/circster?id=${this.view.vis_id}`; } }, { icon_class: "disk--arrow", title: _l("Save"), - on_click: function() { - self.save_viz(); + on_click: () => { + this.save_viz(); } }, { icon_class: "cross-circle", title: _l("Close"), - on_click: function() { - self.handle_unsaved_changes(view); + on_click: () => { + this.handle_unsaved_changes(this.view); } } ], @@ -184,12 +176,12 @@ var TracksterUI = Base.extend({ this.buttonMenu = menu; return menu; - }, + } /** * Add bookmark. */ - add_bookmark: function(position, annotation, editable) { + add_bookmark(position, annotation, editable) { // Create HTML. var bookmarks_container = $("#right .unified-panel-body"); @@ -201,11 +193,12 @@ var TracksterUI = Base.extend({ .addClass("position") .appendTo(new_bookmark); - var position_link = $("
") + //position_link + $("") .text(position) .appendTo(position_div) .click(() => { - view.go_to(position); + this.view.go_to(position); return false; }); @@ -222,11 +215,12 @@ var TracksterUI = Base.extend({ // Remove bookmark. new_bookmark.slideUp("fast"); new_bookmark.remove(); - view.has_changes = true; + this.view.has_changes = true; return false; }); - var delete_icon = $("") + // delete_icon + $("") .addClass("icon-button delete") .appendTo(delete_icon_container); @@ -239,56 +233,50 @@ var TracksterUI = Base.extend({ .addClass("annotation"); } - view.has_changes = true; + this.view.has_changes = true; return new_bookmark; - }, + } /** * Create a complete Trackster visualization. Returns view. */ - create_visualization: function(view_config, viewport_config, drawables_config, bookmarks_config, editable) { + create_visualization(view_config, viewport_config, drawables_config, bookmarks_config, editable) { // Create view. - var self = this; + this.view = new tracks.TracksterView(_.extend(view_config, { header: false })); + this.view.editor = true; - view = new tracks.TracksterView(_.extend(view_config, { header: false })); - - view.editor = true; - $.when(view.load_chroms_deferred).then(chrom_info => { + $.when(this.view.load_chroms_deferred).then(chrom_info => { + var overview_drawable_name = null; // Viewport config. if (viewport_config) { var chrom = viewport_config.chrom; var start = viewport_config.start; var end = viewport_config.end; - var overview_drawable_name = viewport_config.overview; + overview_drawable_name = viewport_config.overview; if (chrom && start !== undefined && end) { - view.change_chrom(chrom, start, end); + this.view.change_chrom(chrom, start, end); } else { // No valid viewport, so use first chromosome. - view.change_chrom(chrom_info[0].chrom); + this.view.change_chrom(chrom_info[0].chrom); } } else { // No viewport, so use first chromosome. - view.change_chrom(chrom_info[0].chrom); + this.view.change_chrom(chrom_info[0].chrom); } // Add drawables to view. if (drawables_config) { // FIXME: can from_dict() be used to create view and add drawables? - var drawable_config; - - var drawable_type; - var drawable; - for (var i = 0; i < drawables_config.length; i++) { - view.add_drawable(tracks.object_from_template(drawables_config[i], view, view)); + for (let i = 0; i < drawables_config.length; i++) { + this.view.add_drawable(tracks.object_from_template(drawables_config[i], this.view, this.view)); } } // Set overview. - var overview_drawable; - for (var i = 0; i < view.drawables.length; i++) { - if (view.drawables[i].config.get_value("name") === overview_drawable_name) { - view.set_overview(view.drawables[i]); + for (let i = 0; i < this.view.drawables.length; i++) { + if (this.view.drawables[i].config.get_value("name") === overview_drawable_name) { + this.view.set_overview(this.view.drawables[i]); break; } } @@ -296,34 +284,35 @@ var TracksterUI = Base.extend({ // Load bookmarks. if (bookmarks_config) { var bookmark; - for (var i = 0; i < bookmarks_config.length; i++) { + for (let i = 0; i < bookmarks_config.length; i++) { bookmark = bookmarks_config[i]; - self.add_bookmark(bookmark["position"], bookmark["annotation"], editable); + this.add_bookmark(bookmark.position, bookmark.annotation, editable); } } // View has no changes as of yet. - view.has_changes = false; + this.view.has_changes = false; }); // Final initialization. - this.set_up_router({ view: view }); + this.set_up_router({ view: this.view }); - return view; - }, + // TODO: This is hopefully not necessary anymore, since we're using the instance view. Do it for compatibility for now. + return this.view; + } /** * Set up location router to use hashes as track browser locations. */ - set_up_router: function(options) { + set_up_router(options) { new visualization.TrackBrowserRouter(options); Backbone.history.start(); - }, + } /** * Set up keyboard navigation for a visualization. */ - init_keyboard_nav: function(view) { + init_keyboard_nav(view) { // Keyboard navigation. Scroll ~7% of height when scrolling up/down. $(document).keyup(e => { // Do not navigate if arrow keys used in input element. @@ -337,39 +326,38 @@ var TracksterUI = Base.extend({ view.move_fraction(0.25); break; case 38: - var change = Math.round(view.viewport_container.height() / 15.0); + // var change = Math.round(view.viewport_container.height() / 15.0); view.viewport_container.scrollTop(view.viewport_container.scrollTop() - 20); break; case 39: view.move_fraction(-0.25); break; case 40: - var change = Math.round(view.viewport_container.height() / 15.0); + // var change = Math.round(view.viewport_container.height() / 15.0); view.viewport_container.scrollTop(view.viewport_container.scrollTop() + 20); break; } }); - }, + } /** * Handle unsaved changes in visualization. */ - handle_unsaved_changes: function(view) { + handle_unsaved_changes(view) { if (view.has_changes) { - var self = this; Galaxy.modal.show({ title: _l("Close visualization"), body: "There are unsaved changes to your visualization which will be lost if you do not save them.", buttons: { - Cancel: function() { + Cancel: () => { Galaxy.modal.hide(); }, - "Leave without Saving": function() { + "Leave without Saving": () => { $(window).off("beforeunload"); window.top.location = `${Galaxy.root}visualization`; }, - Save: function() { - $.when(self.save_viz()).then(() => { + Save: () => { + $.when(this.save_viz()).then(() => { window.top.location = `${Galaxy.root}visualization`; }); } @@ -379,22 +367,25 @@ var TracksterUI = Base.extend({ window.top.location = `${Galaxy.root}visualization`; } } -}); +} -var TracksterView = Backbone.View.extend({ +class TracksterUIView extends Backbone.View { + constructor(options) { + super(options); + } // initalize trackster - initialize: function() { + initialize() { // load ui - ui = new TracksterUI(Galaxy.root); + this.ui = new TracksterUI(Galaxy.root); // create button menu - ui.createButtonMenu(); + this.ui.createButtonMenu(); // attach the button menu to the panel header and float it left - ui.buttonMenu.$el.attr("style", "float: right"); + this.ui.buttonMenu.$el.attr("style", "float: right"); // add to center panel - $("#center .unified-panel-header-inner").append(ui.buttonMenu.$el); + $("#center .unified-panel-header-inner").append(this.ui.buttonMenu.$el); // configure right panel $("#right .unified-panel-title").append("Bookmarks"); @@ -404,7 +395,7 @@ var TracksterView = Backbone.View.extend({ // resize view when showing/hiding right panel (bookmarks for now). $("#right-border").click(() => { - view.resize_window(); + this.ui.view.resize_window(); }); // hide right panel @@ -418,10 +409,9 @@ var TracksterView = Backbone.View.extend({ } else { this.view_new(); } - }, + } - choose_existing_or_new: function() { - var self = this; + choose_existing_or_new() { var dbkey = query_string.get("dbkey"); var listTracksParams = {}; @@ -442,21 +432,21 @@ var TracksterView = Backbone.View.extend({ body: `

    You can add this dataset as:
  • a new track to one of your existing, saved Trackster sessions if they share the genome build: ${dbkey || "Not available."}
  • or create a new session with this dataset as the only track

`, buttons: { - Cancel: function() { + Cancel: () => { window.top.location = `${Galaxy.root}visualizations/list`; }, - "View in saved visualization": function() { - self.view_in_saved(dataset_params); + "View in saved visualization": () => { + this.view_in_saved(dataset_params); }, - "View in new visualization": function() { - self.view_new(); + "View in new visualization": () => { + this.view_new(); } } }); - }, + } // view - view_in_saved: function(dataset_params) { + view_in_saved(dataset_params) { var tracks_grid = new GridView({ url_base: `${Galaxy.root}visualization/list_tracks`, embedded: true @@ -465,28 +455,28 @@ var TracksterView = Backbone.View.extend({ title: _l("Add Data to Saved Visualization"), body: tracks_grid.$el, buttons: { - Cancel: function() { + Cancel: () => { window.top.location = `${Galaxy.root}visualizations/list`; }, - "Add to visualization": function() { - $(parent.document) + "Add to visualization": () => { + $(window.parent.document) .find("input[name=id]:checked") - .each(function() { + .each(() => { dataset_params.id = $(this).val(); window.top.location = `${Galaxy.root}visualization/trackster?${$.param(dataset_params)}`; }); } } }); - }, + } // view - view_existing: function() { + view_existing() { // get config var viz_config = window.galaxy_config.app.viz_config; // view - view = ui.create_visualization( + this.ui.create_visualization( { container: $("#center .unified-panel-body"), name: viz_config.title, @@ -501,31 +491,28 @@ var TracksterView = Backbone.View.extend({ // initialize editor this.init_editor(); - }, + } // view - view_new: function() { - // reference this - var self = this; - + view_new() { // ajax $.ajax({ url: `${Galaxy.root}api/genomes?chrom_info=True`, data: {}, - error: function() { + error: () => { alert("Couldn't create new browser."); }, - success: function(response) { + success: response => { // show dialog Galaxy.modal.show({ title: _l("New Visualization"), - body: self.template_view_new(response), + body: this.template_view_new(response), buttons: { - Cancel: function() { + Cancel: () => { window.top.location = `${Galaxy.root}visualizations/list`; }, - Create: function() { - self.create_browser($("#new-title").val(), $("#new-dbkey").val()); + Create: () => { + this.create_browser($("#new-title").val(), $("#new-dbkey").val()); Galaxy.modal.hide(); } } @@ -548,10 +535,10 @@ var TracksterView = Backbone.View.extend({ $("#overlay").css("overflow", "auto"); } }); - }, + } // new browser form - template_view_new: function(response) { + template_view_new(response) { // start template var html = '
' + @@ -568,7 +555,7 @@ var TracksterView = Backbone.View.extend({ '`; + on_click_fn: track => { + var html = ` + Tool:${track.tool.get("name")}
+ Dataset:${track.config.get_value("name")}
+ Region(s): + + `; var cancel_fn = () => { Galaxy.modal.hide(); @@ -2454,22 +2461,22 @@ extend(Track.prototype, Drawable.prototype, { }; var ok_fn = () => { - var regions_to_use = $('select[name="regions"] option:selected').val(), - regions, - view_region = new visualization.GenomeRegion({ - chrom: view.chrom, - start: view.low, - end: view.high - }), - bookmarked_regions = _.map( - $(".bookmark"), - elt => - new visualization.GenomeRegion({ - from_str: $(elt) - .children(".position") - .text() - }) - ); + var regions_to_use = $('select[name="regions"] option:selected').val(); + var regions; + var view_region = new visualization.GenomeRegion({ + chrom: this.view.chrom, + start: this.view.low, + end: this.view.high + }); + var bookmarked_regions = _.map( + $(".bookmark"), + elt => + new visualization.GenomeRegion({ + from_str: $(elt) + .children(".position") + .text() + }) + ); // Get regions for visualization. if (regions_to_use === "cur") { @@ -2493,6 +2500,8 @@ extend(Track.prototype, Drawable.prototype, { })}`; }; + /* + * TODO: Re-enable this when functional. var check_enter_esc = e => { if ((e.keyCode || e.which) === 27) { // Escape key @@ -2502,6 +2511,7 @@ extend(Track.prototype, Drawable.prototype, { ok_fn(); } }; + */ // show dialog Galaxy.modal.show({ @@ -2732,7 +2742,7 @@ extend(Track.prototype, Drawable.prototype, { track.container_div.addClass("pending"); track.show_message(DATA_PENDING); //$("").attr("src", image_path + "/yui/rel_interstitial_loading.gif").appendTo(track.tiles_div); - setTimeout(() => { + window.setTimeout(() => { track.init(); }, track.data_query_wait); } else if (result === "data" || result.status === "data") { @@ -3040,7 +3050,7 @@ extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, { var clear_after = options && options.clear_after; var low = this.view.low; var high = this.view.high; - var range = high - low; + //var range = high - low; var width = this.view.container.width(); var w_scale = this.view.resolution_px_b; var resolution = 1 / w_scale; @@ -3049,7 +3059,7 @@ extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, { if (this.is_overview) { low = this.view.max_low; high = this.view.max_high; - w_scale = width / (view.max_high - view.max_low); + w_scale = width / (this.view.max_high - this.view.max_low); resolution = 1 / w_scale; } @@ -3105,17 +3115,16 @@ extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, { } // When all tiles are drawn, call post-draw actions. - var track = this; $.when.apply($, tile_promises).then(() => { // Step (c) for (re)moving tiles when clear_after is true: - track.tiles_div.children(".remove").remove(); + this.tiles_div.children(".remove").remove(); // Only do postdraw actions for tiles; instances where tiles may not be drawn include: // (a) ReferenceTrack without sufficient resolution; // (b) data_fetch = false. tiles = _.filter(tiles, t => t !== null); if (tiles.length !== 0) { - track.postdraw_actions(tiles, width, w_scale, clear_after); + this.postdraw_actions(tiles, width, w_scale, clear_after); } }); }, @@ -3124,18 +3133,17 @@ extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, { * Add a maximum/minimum label to track. */ _add_yaxis_label: function(type, on_change) { - var track = this; var css_class = type === "max" ? "top" : "bottom"; var text = type === "max" ? "max" : "min"; var pref_name = type === "max" ? "max_value" : "min_value"; var label = this.container_div.find(`.yaxislabel.${css_class}`); - var value = round(track.config.get_value(pref_name), 1); + var value = round(this.config.get_value(pref_name), 1); // Default action for on_change is to redraw track. on_change = on_change || (() => { - track.request_draw({ clear_tile_cache: true }); + this.request_draw({ clear_tile_cache: true }); }); if (label.length !== 0) { @@ -3149,7 +3157,7 @@ extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, { num_cols: 12, on_finish: function(new_val) { $(".tooltip").remove(); - track.config.set_value(pref_name, round(new_val, 1)); + this.config.set_value(pref_name, round(new_val, 1)); on_change(); }, help_text: `Set ${text} value` @@ -3176,18 +3184,17 @@ extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, { // Clear because this is set when drawing. this.max_height_px = 0; - var track = this; _.each(tiles, tile => { if (!(tile instanceof LineTrackTile)) { tile.html_elt.remove(); - track.draw_helper(tile.region, w_scale, { + this.draw_helper(tile.region, w_scale, { force: true, mode: "Coverage" }); } }); - track._add_yaxis_label("max"); + this._add_yaxis_label("max"); } else { // -- Drawing in non-Coverage mode. -- @@ -3247,19 +3254,16 @@ extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, { var mode = options.mode || this.mode; var resolution = 1 / w_scale; - var // Useful vars. - track = this; - var drawables = this._get_drawables(); var key = this._gen_tile_cache_key(w_scale, region); var is_tile = o => o && "track" in o; // Check tile cache, if found show existing tile in correct position - var tile = force ? undefined : track.tile_cache.get_elt(key); + var tile = force ? undefined : this.tile_cache.get_elt(key); if (tile) { if (is_tile(tile)) { - track.show_tile(tile, w_scale); + this.show_tile(tile, w_scale); } return tile; } @@ -3277,16 +3281,16 @@ extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, { // Map drawable object to data needed for drawing. var tile_data = _.map(drawables, ( d // Get the track data/promise. - ) => d.data_manager.get_data(region, data_mode, resolution, track.data_url_extra_params)); + ) => d.data_manager.get_data(region, data_mode, resolution, this.data_url_extra_params)); // Get reference data/promise. - if (view.reference_track) { + if (this.view.reference_track) { tile_data.push( - view.reference_track.data_manager.get_data( + this.view.reference_track.data_manager.get_data( region, mode, resolution, - view.reference_track.data_url_extra_params + this.view.reference_track.data_url_extra_params ) ); } @@ -3298,7 +3302,7 @@ extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, { // When data is available, draw tile. // var tile_drawn = $.Deferred(); - track.tile_cache.set_elt(key, tile_drawn); + this.tile_cache.set_elt(key, tile_drawn); $.when.apply($, get_tile_data()).then(() => { var tile_data = get_tile_data(); var tracks_data = tile_data; @@ -3309,41 +3313,36 @@ extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, { // Deferred, try again from the top. NOTE: this condition could (should?) be handled by the // GenomeDataManager in visualization module. if (_.find(tile_data, d => util.is_deferred(d))) { - track.tile_cache.set_elt(key, undefined); - $.when(track.draw_helper(region, w_scale, options)).then(tile => { + this.tile_cache.set_elt(key, undefined); + $.when(this.draw_helper(region, w_scale, options)).then(tile => { tile_drawn.resolve(tile); }); return; } // If sequence data is available, subset to get only data in region. - if (view.reference_track) { - seq_data = view.reference_track.data_manager.subset_entry(tile_data.pop(), region); + if (this.view.reference_track) { + seq_data = this.view.reference_track.data_manager.subset_entry(tile_data.pop(), region); } // Get drawing modes, heights for all tracks. var drawing_modes = []; - var drawing_heights = []; _.each(drawables, (d, i) => { - var mode = d.mode; var data = tracks_data[i]; - if (mode === "Auto") { - mode = d.get_mode(data); - d.update_auto_mode(mode); + if (d.mode === "Auto") { + d.mode = d.get_mode(data); + d.update_auto_mode(d.mode); } - drawing_modes.push(mode); - drawing_heights.push(d.get_canvas_height(data, mode, w_scale, width)); + drawing_modes.push(d.mode); + drawing_heights.push(d.get_canvas_height(data, d.mode, w_scale, width)); }); - var canvas = track.view.canvas_manager.new_canvas(); + var canvas = this.view.canvas_manager.new_canvas(); var tile_low = region.get("start"); var tile_high = region.get("end"); - var all_data_index = 0; - - var width = Math.ceil((tile_high - tile_low) * w_scale) + track.left_offset; - + var width = Math.ceil((tile_high - tile_low) * w_scale) + this.left_offset; var height = _.max(drawing_heights); var tile; @@ -3354,7 +3353,7 @@ extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, { // Height is specified in options or is the height found above. canvas.height = options.height || height; var ctx = canvas.getContext("2d"); - ctx.translate(track.left_offset, 0); + ctx.translate(this.left_offset, 0); if (drawables.length > 1) { ctx.globalAlpha = 0.5; ctx.globalCompositeOperation = "source-over"; @@ -3365,8 +3364,8 @@ extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, { // Don't cache, show if no tile. if (tile !== undefined) { - track.tile_cache.set_elt(key, tile); - track.show_tile(tile, w_scale); + this.tile_cache.set_elt(key, tile); + this.show_tile(tile, w_scale); } tile_drawn.resolve(tile); @@ -3428,7 +3427,6 @@ extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, { * an existing tile rather than reshowing it. */ show_tile: function(tile, w_scale) { - var track = this; var tile_element = tile.html_elt; // -- Show/move tile element. -- @@ -3785,7 +3783,7 @@ extend(CompositeTrack.prototype, TiledTrack.prototype, { } // Replace track with group. - var index = this.container.replace_drawable(this, group, true); + this.container.replace_drawable(this, group, true); group.request_draw({ clear_tile_cache: true }); }, @@ -3819,7 +3817,6 @@ extend(CompositeTrack.prototype, TiledTrack.prototype, { * Update minimum, maximum for component tracks. */ update_all_min_max: function() { - var track = this; var min_value = this.config.get_value("min_value"); var max_value = this.config.get_value("max_value"); _.each(this.drawables, d => { @@ -4127,7 +4124,8 @@ extend(DiagonalHeatmapTrack.prototype, Drawable.prototype, TiledTrack.prototype, hda_ldda: track.dataset.get("hda_ldda") }, result => { - var data = result.data; + // What does this do? Is it meant to be attached to some higher scope state object? + // var data = result.data; } ); }, @@ -4163,10 +4161,9 @@ var FeatureTrack = function(view, container, obj_dict) { this.slotters = {}; this.start_end_dct = {}; this.left_offset = 200; - - // this.painter = painters.LinkedFeaturePainter; this.set_painter_from_config(); }; + extend(FeatureTrack.prototype, Drawable.prototype, TiledTrack.prototype, { display_modes: ["Auto", "Coverage", "Dense", "Squish", "Pack"], @@ -4258,9 +4255,6 @@ extend(FeatureTrack.prototype, Drawable.prototype, TiledTrack.prototype, { postdraw_actions: function(tiles, width, w_scale, clear_after) { TiledTrack.prototype.postdraw_actions.call(this, tiles, width, w_scale, clear_after); - var track = this; - var i; - var line_track_tiles = _.filter(tiles, t => t instanceof LineTrackTile); // @@ -4277,7 +4271,6 @@ extend(FeatureTrack.prototype, Drawable.prototype, TiledTrack.prototype, { }); // Draw incomplete features on each tile. - var self = this; _.each(tiles, tile => { // Remove features already drawn on tile originally. var tile_incomplete_features = _.omit( @@ -4296,16 +4289,16 @@ extend(FeatureTrack.prototype, Drawable.prototype, TiledTrack.prototype, { data: _.values(tile_incomplete_features) }; - var new_canvas = self.view.canvas_manager.new_canvas(); + var new_canvas = this.view.canvas_manager.new_canvas(); var new_canvas_ctx = new_canvas.getContext("2d"); new_canvas.height = Math.max( tile.canvas.height, - self.get_canvas_height(features, tile.mode, tile.w_scale, 100) + this.get_canvas_height(features, tile.mode, tile.w_scale, 100) ); new_canvas.width = tile.canvas.width; new_canvas_ctx.drawImage(tile.canvas, 0, 0); - new_canvas_ctx.translate(track.left_offset, 0); - var new_tile = self.draw_tile( + new_canvas_ctx.translate(this.left_offset, 0); + var new_tile = this.draw_tile( features, new_canvas_ctx, tile.mode, @@ -4348,8 +4341,8 @@ extend(FeatureTrack.prototype, Drawable.prototype, TiledTrack.prototype, { // // Update filtering UI. - if (track.filters_manager) { - var filters = track.filters_manager.filters; + if (this.filters_manager) { + var filters = this.filters_manager.filters; var f; for (f = 0; f < filters.length; f++) { filters[f].update_ui_elt(); @@ -4361,7 +4354,7 @@ extend(FeatureTrack.prototype, Drawable.prototype, TiledTrack.prototype, { var example_feature; var filter; - for (i = 0; i < tiles.length; i++) { + for (let i = 0; i < tiles.length; i++) { if (tiles[i].data.length) { example_feature = tiles[i].data[0]; for (f = 0; f < filters.length; f++) { @@ -4375,12 +4368,12 @@ extend(FeatureTrack.prototype, Drawable.prototype, TiledTrack.prototype, { } // If filter availability changed, hide filter div if necessary and update menu. - if (track.filters_available !== filters_available) { - track.filters_available = filters_available; - if (!track.filters_available) { - track.filters_manager.hide(); + if (this.filters_available !== filters_available) { + this.filters_available = filters_available; + if (!this.filters_available) { + this.filters_manager.hide(); } - track.update_icons(); + this.update_icons(); } } @@ -4389,7 +4382,7 @@ extend(FeatureTrack.prototype, Drawable.prototype, TiledTrack.prototype, { // if (tiles[0] instanceof FeatureTrackTile) { var all_slotted = true; - for (i = 0; i < tiles.length; i++) { + for (let i = 0; i < tiles.length; i++) { if (!tiles[i].all_slotted) { all_slotted = false; break; @@ -4557,6 +4550,7 @@ extend(FeatureTrack.prototype, Drawable.prototype, TiledTrack.prototype, { ); var feature_mapper = null; + var incomplete_features = null; ctx.fillStyle = this.config.get_value("block_color"); ctx.font = ctx.canvas.manager.default_font; diff --git a/client/galaxy/scripts/viz/visualization.js b/client/galaxy/scripts/viz/visualization.js index 7ba8c775ad3..b3140462fe8 100644 --- a/client/galaxy/scripts/viz/visualization.js +++ b/client/galaxy/scripts/viz/visualization.js @@ -5,7 +5,6 @@ import util_mod from "viz/trackster/util"; import config_mod from "utils/config"; import GridView from "mvc/grid/grid-view"; import Tabs from "mvc/ui/ui-tabs"; -import Ui from "mvc/ui/ui-misc"; /** * Mixin for returning custom JSON representation from toJSON. Class attribute to_json_keys defines a set of attributes * to include in the representation; to_json_mappers defines mappers for returned objects. @@ -1109,12 +1108,11 @@ var TrackBrowserRouter = Backbone.Router.extend({ // Can't put regular expression in routes dictionary. // NOTE: parentheses are used to denote parameters returned to callback. this.route(/([\w]+)$/, "change_location"); - this.route(/([\w\+]+\:[\d,]+-[\d,]+)$/, "change_location"); + this.route(/([\w+]+:[\d,]+-[\d,]+)$/, "change_location"); // Handle navigate events from view. - var self = this; - self.view.on("navigate", new_loc => { - self.navigate(new_loc); + this.view.on("navigate", new_loc => { + this.navigate(new_loc); }); }, diff --git a/config/datatypes_conf.xml.sample b/config/datatypes_conf.xml.sample index a6b87e2c82c..4da482becf8 100644 --- a/config/datatypes_conf.xml.sample +++ b/config/datatypes_conf.xml.sample @@ -21,7 +21,7 @@ - + @@ -299,7 +299,7 @@ - + diff --git a/doc/source/releases/18.01.rst b/doc/source/releases/18.01.rst new file mode 100644 index 00000000000..cd507ddc8d2 --- /dev/null +++ b/doc/source/releases/18.01.rst @@ -0,0 +1,1184 @@ + +.. to_doc + +18.01 +=============================== + +.. announce_start + +Enhancements +------------------------------- + +.. major_feature + +.. _list of related performance pull requests: + +* Performance and User Experience Improvements + `Pull Request 5514`_, `Pull Request 5515`_, `Pull Request 5542`_, + `Pull Request 5574`_, `Pull Request 5576`_, `Pull Request 5582`_, + `Pull Request 5533`_, `Pull Request 5615`_, `Pull Request 5616`_ + +.. _list of related client pull requests: + +* Client Architecture + `Pull Request 4435`_, `Pull Request 4978`_, `Pull Request 4436`_, `Pull Request 5173`_ + `Pull Request 5293`_, `Pull Request 5191`_, `Pull Request 5190`_, + `Pull Request 4827`_, `Pull Request 4964`_, `Pull Request 5371`_, + `Pull Request 5128`_, `Pull Request 5262`_, `Pull Request 5081`_, `Pull Request 5054`_ + `Pull Request 5093`_, `Pull Request 5001`_, `Pull Request 5261`_, `Pull Request 5278`_, + `Pull Request 5294`_ + +.. feature + +* Add option to clone tool steps in the workflow editor + (thanks to `@anatskiy `__). + `Pull Request 5087`_, `Pull Request 5124`_, `Pull Request 5185`_ +* Implement a generic Cloud ObjectStore using multi-cloud support from + `cloudbridge `__ + (thanks to `@VJalili `__). + `Pull Request 4487`_ +* Reload tools immediately if a macro changes + (thanks to `@mvdbeek `__). + `Pull Request 4635`_ +* Add an interactive environment for `AskOmics `__ + a visual SPARQL query builder for RDF databases + (thanks to `@xgaia `__). + `Pull Request 4737`_ +* Implement a Github error report backend for + (thanks to `@erasche `__). + `Pull Request 4765`_ +* Add maintenance script to simplify setting up a cleanup cron job + (thanks to `@scholtalbers `__). + `Pull Request 4916`_ +* Create the ``$GALAXY_MEMORY_MB`` job environment variable for tools. + `Pull Request 4958`_ +* Improved home and temp directory handling for tools and jobs. + `Pull Request 5193`_ +* Tool-based annotation of out of memory errors. + `Pull Request 5196`_ +* Added support for recursively discovering output datasets + (thanks to `@nuwang `__). + `Pull Request 5240`_ +* Add an API endpoint that allows admins to decode galaxy object IDs. + `Pull Request 5018`_ +* Add sorting options for data library folders. + `Pull Request 4877`_ +* Add option to auto create ``user_library_import_dir`` directories upon user + login. + (thanks to `@scholtalbers `__). + `Pull Request 5138`_ +* Add option to check file permissions for the user library imports + (thanks to `@scholtalbers `__). + `Pull Request 5154`_ +* Add an admin form to pre-populate an LDAP user + (thanks to `@scholtalbers `__). + `Pull Request 5238`_ +* Add a CRAM to BAM datatype converter + (thanks to `@mvdbeek `__). + `Pull Request 4939`_ +* Add infernal-cm datatype + (thanks to `@mmiladi `__). + `Pull Request 4977`_ +* Add ICM datatype for glimmer + (thanks to `@abretaud `__). + `Pull Request 5042`_ +* Add Analyze75 datatype + (thanks to `@bgruening `__). + `Pull Request 4841`_ +* Add Classical linkage and haplotype datatypes + (thanks to `@mtekman `__). + `Pull Request 4894`_ +* Add ideaspre datatype + (thanks to `@gregvonkuster `__). + `Pull Request 5445`_ +* Add compressed fasta support. + `Pull Request 5561`_ +* Add ``cool`` datatype + (thanks to `@bgruening `__). + `Pull Request 5023`_ +* Add neostore zip datatype + (thanks to `@zipho `__). + `Pull Request 4178`_ +* Add fast5_archive datatype + (thanks to `@jvolkening `__). + `Pull Request 4569`_ +* Add postgresql datatype + (thanks to `@bgruening `__). + `Pull Request 4730`_ +* Add IQtree datatypes + (thanks to `@mtekman `__). + `Pull Request 4849`_ +* Add Phylip datatype + (thanks to `@khillion `__). + `Pull Request 5301`_ +.. enhancement + +* Option to group Galaxy Tours for viewing clarity + (thanks to `@selten `__). + `Pull Request 4829`_ +* Allow users to upload multiple FTP files within a single request + `Pull Request 4513`_ +* Replaces the admin form builder grid and forms + `Pull Request 4480`_ +* Update pysam dependency to 0.14 and eliminate the need to have + samtools on Galaxy's ``PATH`` (with huge help from `@mvdbeek + `__) + `Pull Request 4497`_, `Pull Request 5512`_, `Pull Request 5037`_ +* Expand and improve Selenium testing of the web UI (with help from + `@anatskiy `__). + `Pull Request 4543`_, `Pull Request 4655`_, `Pull Request 4676`_, + `Pull Request 4753`_, `Pull Request 4732`_, `Pull Request 4909`_, + `Pull Request 4935`_, `Pull Request 4925`_, + `Pull Request 4687`_, `Pull Request 4660`_, `Pull Request 5333`_, + `Pull Request 5068`_, `Pull Request 4757`_, `Pull Request 4971`_, + `Pull Request 4653`_ +* Allow multiple simultaneous uploads via single POST. + `Pull Request 4563`_ +* Various bits of proactive security-related hardening + (thanks to `@erasche `__). + `Pull Request 4604`_ +* Move test helper ``wait_for_dataset_collection`` for reuse + (thanks to `@mvdbeek `__). + `Pull Request 4658`_ +* Extend job search for hdcas + (thanks to `@mvdbeek `__). + `Pull Request 4665`_ +* Add a custom ``TRACE`` log level for even more verbosity. + `Pull Request 4672`_ +* Migrate various mako templates to modern JavaScript driven views. + `Pull Request 4681`_, `Pull Request 4682`_, `Pull Request 4711`_, + `Pull Request 4755`_, `Pull Request 4661`_, `Pull Request 4993`_, + `Pull Request 4664`_, `Pull Request 4996`_, `Pull Request 5014`_, + `Pull Request 4833`_, `Pull Request 5212`_, `Pull Request 5114`_ +* More HDCA copying tests, add option to copy HDAs into new history. + `Pull Request 5004`_ +* Use only latest publication in ``CITATION`` + (thanks to `@nsoranzo `__). + `Pull Request 4688`_ +* Nicer logging message for sentry + (thanks to `@erasche `__). + `Pull Request 4693`_ +* Use enumeration to provide history input index names. + `Pull Request 4700`_ +* Cleanup delayed action in ``history-view.js``. + `Pull Request 4704`_ +* Add logging during for script integrity exceptions + (thanks to `@erasche `__). + `Pull Request 4720`_ +* Fix to respect ``galaxy.json`` supplied metadata for empty outputs. + `Pull Request 4722`_ +* Update ``reports.md`` with a link to the community hub + (thanks to `@scholtalbers `__). + `Pull Request 4723`_ +* Typo fixes and small cleanups + (thanks to `@nsoranzo `__). + `Pull Request 4725`_ +* Fix that implements stricter checks for SDF datatype sniffing + (thanks to `@nsoranzo `__). + `Pull Request 4729`_ +* When reloading the toolbox, use the existing dependency manager if possible + (thanks to `@mvdbeek `__). + `Pull Request 4739`_ +* Many more upload tests - big improvements to uploads will be coming to Galaxy 18.05. + `Pull Request 4746`_, `Pull Request 4762`_, `Pull Request 4790`_, + `Pull Request 4863`_, `Pull Request 5266`_, `Pull Request 5209`_ +* Kubernetes resources requests/limits support + (thanks to `@pcm32 `__ and the `@phnmnl `__ project). + `Pull Request 4751`_ +* Send all influxdb stats to a single bucket + (thanks to `@erasche `__). + `Pull Request 4758`_ +* PEP-8 fixes in random doctests. + `Pull Request 4764`_ +* Avoid circular import when determining max metadata value size. + `Pull Request 4770`_ +* Remove unused concept of dataset children. + `Pull Request 4771`_ +* Allow dataset attribute changes without refreshing the page. + `Pull Request 4779`_ +* Include check for updates to dependencies in tox, Makefile, Travis. + `Pull Request 4788`_ +* Add labels to selection options of the collection flattening tool. + `Pull Request 4791`_ +* Expose ``state``, ``stdout``, ``stderr``, ``uuid`` in the library API + `Pull Request 4839`_ +* Significant improvements to client QUnit tests including new + `Karma `__ based test driver. + `Pull Request 4855`_, `Pull Request 5066`_, `Pull Request 5063`_, + `Pull Request 5074`_ +* Remove tool reloading buttons and packaging endpoint, revise admin labels + `Pull Request 4866`_ +* Add various elements to the Tool XML doc page + (thanks to `@nsoranzo `__). + `Pull Request 4871`_ +* Absolute pins on linting dependencies. + `Pull Request 4876`_ +* Update various Galaxy requirements. + `Pull Request 4884`_ +* Updates and enhancements for the testing ``Dockerfile``. + `Pull Request 4885`_, `Pull Request 4879`_, `Pull Request 4900`_ +* Add nicer composite dataset names by default + (thanks to `@bgruening `__). + `Pull Request 4886`_ +* Improved initialization and isolation of Postgres databases used in integration testing. + `Pull Request 4887`_, `Pull Request 4914`_ +* Rework dev dependencies to be Pipfile generated, locked, and hashed. + `Pull Request 4891`_ +* Install dev and regular dependencies at the same time. + `Pull Request 4903`_ +* More structured app shutdown. + `Pull Request 4910`_ +* Touch up issue labels in repository procedures document. + `Pull Request 4912`_ +* Improve error handling for incorrect datatype upload. + `Pull Request 4922`_ +* Activate mulled dependencies once per job + (thanks to `@nsoranzo `__). + `Pull Request 4945`_ +* Remove invalid user preferences beta (no longer a beta, always enabled) + `Pull Request 4957`_ +* Add ``DELETE /api/jobs/`` as a job cancellation API endpoint. + `Pull Request 4961`_ +* Kill off processes when stopping the local job runner. + `Pull Request 4962`_ +* Test both endpoints for collection creation in history contents API. + `Pull Request 4965`_ +* Add @flakey test annotation and "skip" them if the fail on Jenkins. + `Pull Request 4972`_ +* Include path in job script integrity errors + (thanks to `@nsoranzo `__). + `Pull Request 4991`_ +* Fix tox envlist to contain all envs that should pass + (thanks to `@nsoranzo `__). + `Pull Request 4992`_ +* Changes made while working on uWSGI mules that don't belong in the mules PR + `Pull Request 4994`_ +* Add warning for sort-of-defunct workflow options in galaxy.ini. + `Pull Request 5002`_ +* Fix Python import order everywhere + (thanks to `@nsoranzo `__). + `Pull Request 4697`_, `Pull Request 5005`_ +* dataset info: present decoded IDs for admins and add peek + `Pull Request 5006`_ +* Removed unneeded skip_install tags in tox.ini. + `Pull Request 5011`_ +* Add metric to the core plugin to collect $GALAXY_MEMORY_MB + `Pull Request 5016`_ +* Test renaming multiple different outputs in workflows. + `Pull Request 5017`_ +* Render arbitrarily nested lists in the UI + `Pull Request 5038`_ +* Expose proper element_identifier in tool action template expansions + `Pull Request 5049`_ +* Document fastest way to iterate on client & client tests together. + `Pull Request 5051`_ +* Support separate DSN for job sentry error reports + (thanks to `@erasche `__). + `Pull Request 5056`_ +* Build endpoint separation + `Pull Request 5058`_ +* Remove ``wchartype`` dependency and ``is_multi_byte`` attribute + (thanks to `@nsoranzo `__). + `Pull Request 5062`_, `Pull Request 5088`_ +* Implement multilingualization support on workflow page + (thanks to `@manabuishii `__). + `Pull Request 5077`_ +* Update Jupyter IE default image + (thanks to `@galaxyproject `__). + `Pull Request 5095`_ +* Determine dynamically if an extension corresponds to an unsniffable binary + datatype + (thanks to `@nsoranzo `__). + `Pull Request 5109`_ +* Update to flake8-import-order 0.16 + (thanks to `@nsoranzo `__). + `Pull Request 4869`_, `Pull Request 5110`_ +* Change the default to not add tags based on filename + `Pull Request 5115`_ +* Improve tool validation and metadata generation + (thanks to `@mvdbeek `__). + `Pull Request 5119`_ +* Download button fixes. + `Pull Request 5125`_ +* Datatype conversion check optimization + (thanks to `@nsoranzo `__). + `Pull Request 5137`_ +* Test resubmit for dynamic JobDestination structures. + `Pull Request 5139`_ +* Various dataset hashtag display improvements. + `Pull Request 5155`_ +* i18n improvements for French localization + (thanks to `@ValentinChCloud `__). + `Pull Request 5089`_, `Pull Request 5157`_ +* Change hicexplorer image name + (thanks to `@bgruening `__). + `Pull Request 5177`_ +* Fix `#3002 `__ with update to + newer version of virtualenv. + (thanks to `@selten `__). + `Pull Request 5202`_ +* Huge steps toward Python 3 compatiblity + (thanks to `@nsoranzo `__). + `Pull Request 5215`_, `Pull Request 5221`_, `Pull Request 5225`_, `Pull Request 5228`_, + `Pull Request 5200`_, `Pull Request 5199`_, `Pull Request 4799`_, `Pull Request 4811`_ +* Add chinese support + (thanks to `@istevenshen `__). + `Pull Request 5232`_ +* Make ``pam`` a conditional dependency + (thanks to `@nsoranzo `__). + `Pull Request 5251`_ +* Update api quickstart doc to use default port, with a little bit of extra + guidance. + `Pull Request 5260`_ +* Allow sorting collection elements based on file + (thanks to `@mvdbeek `__). + `Pull Request 5273`_ +* Add Biostar configuration options to the configuration sample file. + `Pull Request 5276`_ +* Update Japanese translation + (thanks to `@istevenshen `__). + `Pull Request 5288`_ +* Improve the migration message when having to downgrade the database + (thanks to `@mvdbeek `__). + `Pull Request 5299`_ +* Allow ``message`` attribute to be modified on a library dataset. + `Pull Request 5312`_ +* Enforce a size constraint on the tag editor. + `Pull Request 5337`_ +* Various webhooks improvements. + `Pull Request 5342`_ +* Make ``TabularToolDataTable._deduplicate_data()`` faster + (thanks to `@nsoranzo `__). + `Pull Request 5383`_ +* Add ``--skip_flakey_fails`` flag to CI script for API tests + `Pull Request 5455`_ +* Fix for toolbox filters + (thanks to `@bgruening `__). + `Pull Request 5526`_ +* Fix missing job stdout/stderr on Pulsar transfer failures. + `Pull Request 5535`_ +* Optimization to fix repeated fetching dataset permissions in dynamic output collection. + `Pull Request 5578`_ +* Backport toolbox cache + `Pull Request 5583`_ +* Replace distutils.version with packaging.version (fixing lineage handling for + freebayes among other things). + `Pull Request 5588`_ +* Move the cache from toolbox level to the tool level. + `Pull Request 5600`_ + +.. small_enhancement + +* Removes Sample request and External services makos/controllers + `Pull Request 4526`_, `Pull Request 4872`_, `Pull Request 5103`_, + `Pull Request 5204`_ +* Remove unused abstraction layers from Visualizations Registry. + `Pull Request 4620`_ +* Visible keys standardization in model classes. + `Pull Request 4744`_ +* Remove legacy library interface + `Pull Request 4908`_ +* ES6 client/galaxy/scripts/utils/ajax-queue.js + `Pull Request 4933`_ +* Remove unused galaxy-side set_tool_version code + (thanks to `@mvdbeek `__). + `Pull Request 4986`_ +* Fix ``allow-register`` option in ``auth`` module + (thanks to `@nsoranzo `__). + `Pull Request 4989`_ +* Tried to fix issue with Conda environment building failing jobs that + had to be rolled back. + (thanks to `@mvdbeek `__). + `Pull Request 5036`_, `Pull Request 5470`_ +* Add packed symlink back pending a deprecation cycle. + `Pull Request 5094`_ +* Onload webhook toggles. + `Pull Request 5116`_ +* Re-organize edge case upload options for greater readability. + `Pull Request 5206`_ +* Refactor ``upload.py`` toward reuse. + `Pull Request 5229`_ +* JavaScript router cleanup. + `Pull Request 5235`_ +* Comment PlantTribes datatypes + (thanks to `@gregvonkuster `__). + `Pull Request 5254`_ +* Dataset error interface cleanup. + `Pull Request 5279`_ +* Mention how to specify the config file location + (thanks to `@mvdbeek `__). + `Pull Request 5297`_ +* Uninstall a tool by default (vs. deactivating it). + `Pull Request 5300`_ + + + +Fixes +------------------------------- + +.. major_bug + +.. bug + +* Allow mapping over collections when discovering dataset collections in tools + (thanks to `@mvdbeek `__). + `Pull Request 5413`_ +* Make liftover tool use data tables + (thanks to `@mvdbeek `__). + `Pull Request 4645`_ +* Pass job output file unqualified names to Pulsar so that it can create them + before running the job. + `Pull Request 4662`_ +* Fix transiently failing saved histories due to success message disappearing. + `Pull Request 4669`_ +* Update CITATION file with 2016 paper + (thanks to `@mvdbeek `__). + `Pull Request 4686`_ +* Stop running common_startup.sh twice when starting from run.sh + `Pull Request 4759`_ +* Fix docstring linting. + `Pull Request 4766`_ +* Mothur.freq sniffer more stringent + (thanks to `@yhoogstrate `__). + `Pull Request 4781`_ +* MacOS X fix for a test tool. + `Pull Request 4806`_ +* Minor architecture slides fixes for typos/grammar. + `Pull Request 4822`_ +* Fix two invalid targets in dataset list item. + `Pull Request 4823`_ +* Fix double return in form-parameters. + `Pull Request 4826`_ +* Fix the case where 'Labels' in a docker node inspect exists but is null. + `Pull Request 4838`_ +* Fix all E722 errors and ignore E741 + (thanks to `@nsoranzo `__). + `Pull Request 4847`_ +* Fix jsutils time - fixes charts visualize. + `Pull Request 4852`_ +* Bugfix during error handling with linked files during upload + (thanks to `@ieguinoa `__). + `Pull Request 4858`_ +* Add a gulp plumber. + `Pull Request 4867`_ +* Minor admin panel fixes. + `Pull Request 4895`_ +* Fix list collection creator dragdrop event bindings. + `Pull Request 4901`_ +* Fix status handling for grids. + `Pull Request 4913`_ +* Fix revision selection during (beta) repository installation + (thanks to `@mvdbeek `__). + `Pull Request 4944`_ +* Fix Trackster styles bleeding into the app (the slightly off-center upload + .icon buttons). + `Pull Request 4948`_ +* Fix multiple selections for grid operations redirecting to center panel. + `Pull Request 4951`_ +* Fix visualization link in import success message. + `Pull Request 4952`_ +* Fix up reports JavaScript. + `Pull Request 4967`_ +* Run ``hg clone`` in a subprocess instead of using the Mercurial API + (thanks to `@nsoranzo `__). + `Pull Request 4979`_ +* Tolerate ``IOError`` in tool and data table watcher + (thanks to `@mvdbeek `__). + `Pull Request 4981`_ +* Install numpy before bx-python in case you are installing from sdists + `Pull Request 4982`_ +* Specify ``TagAssociation`` class when copying a tag + (thanks to `@mvdbeek `__). + `Pull Request 4984`_ +* Fix initialization of named ajax queue. + `Pull Request 4985`_ +* Encode file content with utf-8 + (thanks to `@mvdbeek `__). + `Pull Request 4987`_ +* Revert export to file. + `Pull Request 4988`_ +* Remove extraneous subclass for DMND datatype + (thanks to `@nsoranzo `__). + `Pull Request 4990`_ +* Fix to allow ``get_history`` calls with ``create=False`` when evaluating workflows. + `Pull Request 4997`_ +* Add missing ``ipaddress`` requirement + (thanks to `@nsoranzo `__). + `Pull Request 5000`_ +* Use github instead of NCBI for problematic data manager test FASTA. + `Pull Request 5007`_ +* Fix for history contents API to remove the default flag override. + `Pull Request 5008`_ +* Fix to avoid visiting child inputs of invalid conditionals. + `Pull Request 5010`_ +* Fix for ``parse_interpreter`` - log a warning only if interpreter is set + (thanks to `@nsoranzo `__). + `Pull Request 5015`_ +* Fix a few stray wiki links. + `Pull Request 5020`_ +* Workflow editor outputs fixes. + `Pull Request 5021`_ +* Fix workflow editor output attributes. + `Pull Request 5022`_ +* Metadata parameters rely on their own optional setting not on the field + attribute. + `Pull Request 5027`_ +* A Python 3 fix for the gsummary tool + (thanks to `@bernt-matthias `__). + `Pull Request 5043`_ +* Cleanup SA objects between workflow invocation scheduling attempts. + `Pull Request 5045`_ +* Safely handle possible ``None`` value encountered in processing and execution of + post-job action arguments + (thanks to `@erasche `__). + `Pull Request 5050`_ +* Restore admin form routes. + `Pull Request 5065`_ +* Fixes galaxy startup when ``LC_TYPE=UTF-8`` on OS X + (thanks to `@mvdbeek `__). + `Pull Request 5070`_ +* Ignore ``OSError`` when chmod'ing integrated_tool_panel_conf.xml + (thanks to `@mvdbeek `__). + `Pull Request 5071`_ +* Fix metadata setting for ``otu`` datatypes + (thanks to `@mvdbeek `__). + `Pull Request 5072`_ +* Fix exception in admin panel + (thanks to `@mvdbeek `__). + `Pull Request 5079`_ +* Always fill ``message`` to avoid ``KeyError`` for sentry ``ERROR_TEMPLATE`` + (thanks to `@mvdbeek `__). + `Pull Request 5086`_ +* Attempt to make data manager integration test more robust. + `Pull Request 5098`_ +* Toolshed install stability improvements + (thanks to `@mvdbeek `__). + `Pull Request 5099`_ +* Fix Trackster link to custom builds view. + `Pull Request 5104`_ +* Improve resilience of filter detection, add error messages, fix identifiers. + `Pull Request 5106`_ +* Fix ICM datatype sniffer config + (thanks to `@mvdbeek `__). + `Pull Request 5121`_ +* Fix attribute error that was missed during refactor of sentry + (thanks to `@erasche `__). + `Pull Request 5122`_ +* Fix connecting non-input modules to subworkflow inputs. + `Pull Request 5140`_ +* Fix for history copy. + `Pull Request 5144`_ +* Fixes for handling delayed steps within subworkflows. + `Pull Request 5145`_ +* Fix localization and build client. + `Pull Request 5156`_ +* Resolve broken link for "all workflows" + (thanks to `@mmiladi `__). + `Pull Request 5161`_ +* Fix workflow collection attachments. + `Pull Request 5166`_ +* Provide UI collection output information for subworkflows. + `Pull Request 5172`_ +* Remove legacy request controller from reports app. + `Pull Request 5182`_ +* Fixes genome decode handling. + `Pull Request 5198`_ +* Remove broken Yahoo OpenID support + (thanks to `@VJalili `__). + `Pull Request 5208`_ +* Force window jQuery access for charts. + `Pull Request 5210`_ +* Mark transiently failing ``test_run_data`` as flakey. + `Pull Request 5211`_ +* Fail job if tools that use ``galaxy.json`` write to stderr + (thanks to `@mvdbeek `__). + `Pull Request 5217`_ +* Allow shell plugins with different parameters to co-exist + (thanks to `@mvdbeek `__). + `Pull Request 5223`_ +* paster.pid/log to galaxy.pid/log reference update + (thanks to `@nsoranzo `__). + `Pull Request 5226`_ +* Refine Conda version numbers allowed for using ``--offline`` flag again + (thanks to `@NCEichner `__). + `Pull Request 5233`_ +* Workflow list show-in-tool-panel callback bugfix. + `Pull Request 5234`_ +* Fix image proxy prefix in tool form. + `Pull Request 5237`_ +* Fix wrong tool id after switching versions + (thanks to `@mvdbeek `__). + `Pull Request 5249`_ +* Catch and display error when displaying broken BAM file + (thanks to `@mvdbeek `__). + `Pull Request 5253`_ +* Fix for getmicrobedata tool + (thanks to `@bernt-matthias `__). + `Pull Request 5258`_ +* Adjust note about nginx enabled sites configuration + (thanks to `@scholtalbers `__). + `Pull Request 5259`_ +* Mark the test ``rerun_with_use_cached_job`` as flakey + (thanks to `@mvdbeek `__). + `Pull Request 5286`_ +* Fix dataset edit link. + `Pull Request 5289`_ +* Fix link to getgalaxy.org + (thanks to `@selten `__). + `Pull Request 5295`_ +* Fix tool report submission with sentry + (thanks to `@mvdbeek `__). + `Pull Request 5303`_ +* Fix ``common_startup.sh`` bash-isms + (thanks to `@nsoranzo `__). + `Pull Request 5304`_ +* Fix Galaxy instance startup error + (thanks to `@bgruening `__). + `Pull Request 5306`_ +* Fix link to library from history structure view. + `Pull Request 5327`_ +* Prevent reloading when data table is being modified + (thanks to `@mvdbeek `__). + `Pull Request 5331`_ +* Work around (temporarily) wrong ``getsize()`` output + (thanks to `@mvdbeek `__). + `Pull Request 5335`_ +* Disable galaxy tour 'path' navigation. + `Pull Request 5340`_ +* Fix ``tool-shed-config-validate`` ``Makefile`` target. + (thanks to `@ValentinChCloud `__). + `Pull Request 5343`_ +* History import fixes + (thanks to `@mvdbeek `__). + `Pull Request 5344`_ +* Fix dataset purging, dataset cleanup script and db_shell script + (thanks to `@mvdbeek `__). + `Pull Request 5346`_ +* Fix BAM conversion test tool + (thanks to `@mvdbeek `__). + `Pull Request 5351`_ +* Remove charlimit for fetching URLs. + `Pull Request 5353`_ +* Use ``print()`` function in common_startup.sh + (thanks to `@mvdbeek `__). + `Pull Request 5357`_ +* Handle ``None`` in job owner in API + (thanks to `@erasche `__). + `Pull Request 5358`_ +* Fix form logic in deactivate or uninstall. + `Pull Request 5363`_ +* History multipanel fixes. + `Pull Request 5364`_ +* Remove additional checkbox workarounds. + `Pull Request 5367`_ +* Workflow tool menu fix for deleted workflows. + `Pull Request 5368`_ +* Bump conditional ``Pygments`` version to 2.2.0 so it matches the dev. + `Pull Request 5376`_ +* Fix ``make docs`` when the virtualenv is not ``.venv`` . + `Pull Request 5377`_ +* Force a fixed node image version when building client for Jenkins. + `Pull Request 5382`_ +* Install latest Conda and don't use ``shell=True`` + (thanks to `@nsoranzo `__). + `Pull Request 5397`_ +* Fix for subworkflow creation + (thanks to `@mvdbeek `__). + `Pull Request 5398`_ +* Follow IUC and drop ``r`` channel from the default Conda channels + (thanks to `@mvdbeek `__). + `Pull Request 5406`_ +* Implement workaround for extra metadata revision creation. + `Pull Request 5433`_ +* Don't silently fail rest of multi-action queue when attempting to purge a + collection. + `Pull Request 5443`_ +* Ensure ``jobStateSummariesCollection`` exists. + `Pull Request 5444`_ +* Fix ``server_name`` when config is a ``dict``. + `Pull Request 5447`_ +* Fixes for workflow sharing links. + `Pull Request 5467`_ +* Fix workflow execution post action - rename + (thanks to `@scholtalbers `__). + `Pull Request 5485`_ +* Fix ``common_startup.sh`` for galaxy tarballs + (thanks to `@nsoranzo `__). + `Pull Request 5491`_ +* Close ``tempfile`` handles. + `Pull Request 5506`_, `Pull Request 5552`_ +* Do not allow ``codefiles`` during tool shed tool loading. + `Pull Request 5510`_ +* Fix for GenomeSpace importer/exporter + (thanks to `@nuwang `__). + `Pull Request 5528`_ +* Fix search overlay JS errors + (thanks to `@bgruening `__). + `Pull Request 5531`_ +* Allow LDAP options not starting with ``OPT_`` + (thanks to `@nsoranzo `__). + `Pull Request 5556`_ +* Fix broken admin ``create new user`` when ``registration =='challenge'`` + (thanks to `@scholtalbers `__). + `Pull Request 5569`_ +* Do not remove external path files during library uploads + (thanks to `@nsoranzo `__). + `Pull Request 5573`_ +* Bump sqlite3 dependency for web proxy. + `Pull Request 5575`_ +* Fix small bam (header-only) infinite fetching. + `Pull Request 5579`_ +* Fix migration 0137's downgrade. + `Pull Request 5605`_ +* Conda fix for commands using stdout redirection. + `Pull Request 5620`_ +* Move `Extract genomic DNA 1` to list of versioned galaxy tools requiring + galaxy to be importable + (thanks to `@mvdbeek `__). + `Pull Request 5626`_ +* Changed GenomeSpace token handling to use manual OpenID association only. + `Pull Request 5631`_ +* Use sample file path when adding missing indexes + (thanks to `@mvdbeek `__). + `Pull Request 5650`_ +* Fix exception if user preference value undefined + (thanks to `@mvdbeek `__). + `Pull Request 5662`_ +* Fix exception if email is not specified or email is wrong + (thanks to `@mvdbeek `__). + `Pull Request 5663`_ +* Show error message if user tries purging datasets + (thanks to `@mvdbeek `__). + `Pull Request 5664`_ +* Show error message if history structure can't be shown + (thanks to `@mvdbeek `__). + `Pull Request 5665`_ +* Consistent sniffing regardless of in_place. + `Pull Request 5643`_ + +.. github_links +.. _Pull Request 4178: https://github.com/galaxyproject/galaxy/pull/4178 +.. _Pull Request 4435: https://github.com/galaxyproject/galaxy/pull/4435 +.. _Pull Request 4436: https://github.com/galaxyproject/galaxy/pull/4436 +.. _Pull Request 4475: https://github.com/galaxyproject/galaxy/pull/4475 +.. _Pull Request 4480: https://github.com/galaxyproject/galaxy/pull/4480 +.. _Pull Request 4487: https://github.com/galaxyproject/galaxy/pull/4487 +.. _Pull Request 4497: https://github.com/galaxyproject/galaxy/pull/4497 +.. _Pull Request 4513: https://github.com/galaxyproject/galaxy/pull/4513 +.. _Pull Request 4526: https://github.com/galaxyproject/galaxy/pull/4526 +.. _Pull Request 4543: https://github.com/galaxyproject/galaxy/pull/4543 +.. _Pull Request 4563: https://github.com/galaxyproject/galaxy/pull/4563 +.. _Pull Request 4569: https://github.com/galaxyproject/galaxy/pull/4569 +.. _Pull Request 4604: https://github.com/galaxyproject/galaxy/pull/4604 +.. _Pull Request 4620: https://github.com/galaxyproject/galaxy/pull/4620 +.. _Pull Request 4635: https://github.com/galaxyproject/galaxy/pull/4635 +.. _Pull Request 4645: https://github.com/galaxyproject/galaxy/pull/4645 +.. _Pull Request 4649: https://github.com/galaxyproject/galaxy/pull/4649 +.. _Pull Request 4653: https://github.com/galaxyproject/galaxy/pull/4653 +.. _Pull Request 4655: https://github.com/galaxyproject/galaxy/pull/4655 +.. _Pull Request 4658: https://github.com/galaxyproject/galaxy/pull/4658 +.. _Pull Request 4660: https://github.com/galaxyproject/galaxy/pull/4660 +.. _Pull Request 4661: https://github.com/galaxyproject/galaxy/pull/4661 +.. _Pull Request 4662: https://github.com/galaxyproject/galaxy/pull/4662 +.. _Pull Request 4664: https://github.com/galaxyproject/galaxy/pull/4664 +.. _Pull Request 4665: https://github.com/galaxyproject/galaxy/pull/4665 +.. _Pull Request 4669: https://github.com/galaxyproject/galaxy/pull/4669 +.. _Pull Request 4672: https://github.com/galaxyproject/galaxy/pull/4672 +.. _Pull Request 4673: https://github.com/galaxyproject/galaxy/pull/4673 +.. _Pull Request 4676: https://github.com/galaxyproject/galaxy/pull/4676 +.. _Pull Request 4679: https://github.com/galaxyproject/galaxy/pull/4679 +.. _Pull Request 4681: https://github.com/galaxyproject/galaxy/pull/4681 +.. _Pull Request 4682: https://github.com/galaxyproject/galaxy/pull/4682 +.. _Pull Request 4686: https://github.com/galaxyproject/galaxy/pull/4686 +.. _Pull Request 4687: https://github.com/galaxyproject/galaxy/pull/4687 +.. _Pull Request 4688: https://github.com/galaxyproject/galaxy/pull/4688 +.. _Pull Request 4689: https://github.com/galaxyproject/galaxy/pull/4689 +.. _Pull Request 4690: https://github.com/galaxyproject/galaxy/pull/4690 +.. _Pull Request 4693: https://github.com/galaxyproject/galaxy/pull/4693 +.. _Pull Request 4697: https://github.com/galaxyproject/galaxy/pull/4697 +.. _Pull Request 4699: https://github.com/galaxyproject/galaxy/pull/4699 +.. _Pull Request 4700: https://github.com/galaxyproject/galaxy/pull/4700 +.. _Pull Request 4704: https://github.com/galaxyproject/galaxy/pull/4704 +.. _Pull Request 4711: https://github.com/galaxyproject/galaxy/pull/4711 +.. _Pull Request 4720: https://github.com/galaxyproject/galaxy/pull/4720 +.. _Pull Request 4722: https://github.com/galaxyproject/galaxy/pull/4722 +.. _Pull Request 4723: https://github.com/galaxyproject/galaxy/pull/4723 +.. _Pull Request 4725: https://github.com/galaxyproject/galaxy/pull/4725 +.. _Pull Request 4729: https://github.com/galaxyproject/galaxy/pull/4729 +.. _Pull Request 4730: https://github.com/galaxyproject/galaxy/pull/4730 +.. _Pull Request 4732: https://github.com/galaxyproject/galaxy/pull/4732 +.. _Pull Request 4737: https://github.com/galaxyproject/galaxy/pull/4737 +.. _Pull Request 4739: https://github.com/galaxyproject/galaxy/pull/4739 +.. _Pull Request 4744: https://github.com/galaxyproject/galaxy/pull/4744 +.. _Pull Request 4746: https://github.com/galaxyproject/galaxy/pull/4746 +.. _Pull Request 4751: https://github.com/galaxyproject/galaxy/pull/4751 +.. _Pull Request 4753: https://github.com/galaxyproject/galaxy/pull/4753 +.. _Pull Request 4755: https://github.com/galaxyproject/galaxy/pull/4755 +.. _Pull Request 4757: https://github.com/galaxyproject/galaxy/pull/4757 +.. _Pull Request 4758: https://github.com/galaxyproject/galaxy/pull/4758 +.. _Pull Request 4759: https://github.com/galaxyproject/galaxy/pull/4759 +.. _Pull Request 4762: https://github.com/galaxyproject/galaxy/pull/4762 +.. _Pull Request 4764: https://github.com/galaxyproject/galaxy/pull/4764 +.. _Pull Request 4765: https://github.com/galaxyproject/galaxy/pull/4765 +.. _Pull Request 4766: https://github.com/galaxyproject/galaxy/pull/4766 +.. _Pull Request 4770: https://github.com/galaxyproject/galaxy/pull/4770 +.. _Pull Request 4771: https://github.com/galaxyproject/galaxy/pull/4771 +.. _Pull Request 4778: https://github.com/galaxyproject/galaxy/pull/4778 +.. _Pull Request 4779: https://github.com/galaxyproject/galaxy/pull/4779 +.. _Pull Request 4781: https://github.com/galaxyproject/galaxy/pull/4781 +.. _Pull Request 4787: https://github.com/galaxyproject/galaxy/pull/4787 +.. _Pull Request 4788: https://github.com/galaxyproject/galaxy/pull/4788 +.. _Pull Request 4789: https://github.com/galaxyproject/galaxy/pull/4789 +.. _Pull Request 4790: https://github.com/galaxyproject/galaxy/pull/4790 +.. _Pull Request 4791: https://github.com/galaxyproject/galaxy/pull/4791 +.. _Pull Request 4792: https://github.com/galaxyproject/galaxy/pull/4792 +.. _Pull Request 4796: https://github.com/galaxyproject/galaxy/pull/4796 +.. _Pull Request 4799: https://github.com/galaxyproject/galaxy/pull/4799 +.. _Pull Request 4806: https://github.com/galaxyproject/galaxy/pull/4806 +.. _Pull Request 4811: https://github.com/galaxyproject/galaxy/pull/4811 +.. _Pull Request 4814: https://github.com/galaxyproject/galaxy/pull/4814 +.. _Pull Request 4822: https://github.com/galaxyproject/galaxy/pull/4822 +.. _Pull Request 4823: https://github.com/galaxyproject/galaxy/pull/4823 +.. _Pull Request 4826: https://github.com/galaxyproject/galaxy/pull/4826 +.. _Pull Request 4827: https://github.com/galaxyproject/galaxy/pull/4827 +.. _Pull Request 4829: https://github.com/galaxyproject/galaxy/pull/4829 +.. _Pull Request 4833: https://github.com/galaxyproject/galaxy/pull/4833 +.. _Pull Request 4838: https://github.com/galaxyproject/galaxy/pull/4838 +.. _Pull Request 4839: https://github.com/galaxyproject/galaxy/pull/4839 +.. _Pull Request 4841: https://github.com/galaxyproject/galaxy/pull/4841 +.. _Pull Request 4847: https://github.com/galaxyproject/galaxy/pull/4847 +.. _Pull Request 4849: https://github.com/galaxyproject/galaxy/pull/4849 +.. _Pull Request 4850: https://github.com/galaxyproject/galaxy/pull/4850 +.. _Pull Request 4852: https://github.com/galaxyproject/galaxy/pull/4852 +.. _Pull Request 4855: https://github.com/galaxyproject/galaxy/pull/4855 +.. _Pull Request 4858: https://github.com/galaxyproject/galaxy/pull/4858 +.. _Pull Request 4863: https://github.com/galaxyproject/galaxy/pull/4863 +.. _Pull Request 4866: https://github.com/galaxyproject/galaxy/pull/4866 +.. _Pull Request 4867: https://github.com/galaxyproject/galaxy/pull/4867 +.. _Pull Request 4869: https://github.com/galaxyproject/galaxy/pull/4869 +.. _Pull Request 4871: https://github.com/galaxyproject/galaxy/pull/4871 +.. _Pull Request 4872: https://github.com/galaxyproject/galaxy/pull/4872 +.. _Pull Request 4876: https://github.com/galaxyproject/galaxy/pull/4876 +.. _Pull Request 4877: https://github.com/galaxyproject/galaxy/pull/4877 +.. _Pull Request 4879: https://github.com/galaxyproject/galaxy/pull/4879 +.. _Pull Request 4884: https://github.com/galaxyproject/galaxy/pull/4884 +.. _Pull Request 4885: https://github.com/galaxyproject/galaxy/pull/4885 +.. _Pull Request 4886: https://github.com/galaxyproject/galaxy/pull/4886 +.. _Pull Request 4887: https://github.com/galaxyproject/galaxy/pull/4887 +.. _Pull Request 4891: https://github.com/galaxyproject/galaxy/pull/4891 +.. _Pull Request 4894: https://github.com/galaxyproject/galaxy/pull/4894 +.. _Pull Request 4895: https://github.com/galaxyproject/galaxy/pull/4895 +.. _Pull Request 4900: https://github.com/galaxyproject/galaxy/pull/4900 +.. _Pull Request 4901: https://github.com/galaxyproject/galaxy/pull/4901 +.. _Pull Request 4903: https://github.com/galaxyproject/galaxy/pull/4903 +.. _Pull Request 4908: https://github.com/galaxyproject/galaxy/pull/4908 +.. _Pull Request 4909: https://github.com/galaxyproject/galaxy/pull/4909 +.. _Pull Request 4910: https://github.com/galaxyproject/galaxy/pull/4910 +.. _Pull Request 4912: https://github.com/galaxyproject/galaxy/pull/4912 +.. _Pull Request 4913: https://github.com/galaxyproject/galaxy/pull/4913 +.. _Pull Request 4914: https://github.com/galaxyproject/galaxy/pull/4914 +.. _Pull Request 4916: https://github.com/galaxyproject/galaxy/pull/4916 +.. _Pull Request 4917: https://github.com/galaxyproject/galaxy/pull/4917 +.. _Pull Request 4922: https://github.com/galaxyproject/galaxy/pull/4922 +.. _Pull Request 4925: https://github.com/galaxyproject/galaxy/pull/4925 +.. _Pull Request 4933: https://github.com/galaxyproject/galaxy/pull/4933 +.. _Pull Request 4934: https://github.com/galaxyproject/galaxy/pull/4934 +.. _Pull Request 4935: https://github.com/galaxyproject/galaxy/pull/4935 +.. _Pull Request 4939: https://github.com/galaxyproject/galaxy/pull/4939 +.. _Pull Request 4942: https://github.com/galaxyproject/galaxy/pull/4942 +.. _Pull Request 4944: https://github.com/galaxyproject/galaxy/pull/4944 +.. _Pull Request 4945: https://github.com/galaxyproject/galaxy/pull/4945 +.. _Pull Request 4948: https://github.com/galaxyproject/galaxy/pull/4948 +.. _Pull Request 4951: https://github.com/galaxyproject/galaxy/pull/4951 +.. _Pull Request 4952: https://github.com/galaxyproject/galaxy/pull/4952 +.. _Pull Request 4957: https://github.com/galaxyproject/galaxy/pull/4957 +.. _Pull Request 4958: https://github.com/galaxyproject/galaxy/pull/4958 +.. _Pull Request 4961: https://github.com/galaxyproject/galaxy/pull/4961 +.. _Pull Request 4962: https://github.com/galaxyproject/galaxy/pull/4962 +.. _Pull Request 4964: https://github.com/galaxyproject/galaxy/pull/4964 +.. _Pull Request 4965: https://github.com/galaxyproject/galaxy/pull/4965 +.. _Pull Request 4967: https://github.com/galaxyproject/galaxy/pull/4967 +.. _Pull Request 4968: https://github.com/galaxyproject/galaxy/pull/4968 +.. _Pull Request 4971: https://github.com/galaxyproject/galaxy/pull/4971 +.. _Pull Request 4972: https://github.com/galaxyproject/galaxy/pull/4972 +.. _Pull Request 4977: https://github.com/galaxyproject/galaxy/pull/4977 +.. _Pull Request 4978: https://github.com/galaxyproject/galaxy/pull/4978 +.. _Pull Request 4979: https://github.com/galaxyproject/galaxy/pull/4979 +.. _Pull Request 4981: https://github.com/galaxyproject/galaxy/pull/4981 +.. _Pull Request 4982: https://github.com/galaxyproject/galaxy/pull/4982 +.. _Pull Request 4984: https://github.com/galaxyproject/galaxy/pull/4984 +.. _Pull Request 4985: https://github.com/galaxyproject/galaxy/pull/4985 +.. _Pull Request 4986: https://github.com/galaxyproject/galaxy/pull/4986 +.. _Pull Request 4987: https://github.com/galaxyproject/galaxy/pull/4987 +.. _Pull Request 4988: https://github.com/galaxyproject/galaxy/pull/4988 +.. _Pull Request 4989: https://github.com/galaxyproject/galaxy/pull/4989 +.. _Pull Request 4990: https://github.com/galaxyproject/galaxy/pull/4990 +.. _Pull Request 4991: https://github.com/galaxyproject/galaxy/pull/4991 +.. _Pull Request 4992: https://github.com/galaxyproject/galaxy/pull/4992 +.. _Pull Request 4993: https://github.com/galaxyproject/galaxy/pull/4993 +.. _Pull Request 4994: https://github.com/galaxyproject/galaxy/pull/4994 +.. _Pull Request 4996: https://github.com/galaxyproject/galaxy/pull/4996 +.. _Pull Request 4997: https://github.com/galaxyproject/galaxy/pull/4997 +.. _Pull Request 4998: https://github.com/galaxyproject/galaxy/pull/4998 +.. _Pull Request 5000: https://github.com/galaxyproject/galaxy/pull/5000 +.. _Pull Request 5001: https://github.com/galaxyproject/galaxy/pull/5001 +.. _Pull Request 5002: https://github.com/galaxyproject/galaxy/pull/5002 +.. _Pull Request 5004: https://github.com/galaxyproject/galaxy/pull/5004 +.. _Pull Request 5005: https://github.com/galaxyproject/galaxy/pull/5005 +.. _Pull Request 5006: https://github.com/galaxyproject/galaxy/pull/5006 +.. _Pull Request 5007: https://github.com/galaxyproject/galaxy/pull/5007 +.. _Pull Request 5008: https://github.com/galaxyproject/galaxy/pull/5008 +.. _Pull Request 5010: https://github.com/galaxyproject/galaxy/pull/5010 +.. _Pull Request 5011: https://github.com/galaxyproject/galaxy/pull/5011 +.. _Pull Request 5013: https://github.com/galaxyproject/galaxy/pull/5013 +.. _Pull Request 5014: https://github.com/galaxyproject/galaxy/pull/5014 +.. _Pull Request 5015: https://github.com/galaxyproject/galaxy/pull/5015 +.. _Pull Request 5016: https://github.com/galaxyproject/galaxy/pull/5016 +.. _Pull Request 5017: https://github.com/galaxyproject/galaxy/pull/5017 +.. _Pull Request 5018: https://github.com/galaxyproject/galaxy/pull/5018 +.. _Pull Request 5020: https://github.com/galaxyproject/galaxy/pull/5020 +.. _Pull Request 5021: https://github.com/galaxyproject/galaxy/pull/5021 +.. _Pull Request 5022: https://github.com/galaxyproject/galaxy/pull/5022 +.. _Pull Request 5023: https://github.com/galaxyproject/galaxy/pull/5023 +.. _Pull Request 5027: https://github.com/galaxyproject/galaxy/pull/5027 +.. _Pull Request 5036: https://github.com/galaxyproject/galaxy/pull/5036 +.. _Pull Request 5037: https://github.com/galaxyproject/galaxy/pull/5037 +.. _Pull Request 5038: https://github.com/galaxyproject/galaxy/pull/5038 +.. _Pull Request 5042: https://github.com/galaxyproject/galaxy/pull/5042 +.. _Pull Request 5043: https://github.com/galaxyproject/galaxy/pull/5043 +.. _Pull Request 5045: https://github.com/galaxyproject/galaxy/pull/5045 +.. _Pull Request 5049: https://github.com/galaxyproject/galaxy/pull/5049 +.. _Pull Request 5050: https://github.com/galaxyproject/galaxy/pull/5050 +.. _Pull Request 5051: https://github.com/galaxyproject/galaxy/pull/5051 +.. _Pull Request 5054: https://github.com/galaxyproject/galaxy/pull/5054 +.. _Pull Request 5056: https://github.com/galaxyproject/galaxy/pull/5056 +.. _Pull Request 5058: https://github.com/galaxyproject/galaxy/pull/5058 +.. _Pull Request 5062: https://github.com/galaxyproject/galaxy/pull/5062 +.. _Pull Request 5063: https://github.com/galaxyproject/galaxy/pull/5063 +.. _Pull Request 5065: https://github.com/galaxyproject/galaxy/pull/5065 +.. _Pull Request 5066: https://github.com/galaxyproject/galaxy/pull/5066 +.. _Pull Request 5068: https://github.com/galaxyproject/galaxy/pull/5068 +.. _Pull Request 5070: https://github.com/galaxyproject/galaxy/pull/5070 +.. _Pull Request 5071: https://github.com/galaxyproject/galaxy/pull/5071 +.. _Pull Request 5072: https://github.com/galaxyproject/galaxy/pull/5072 +.. _Pull Request 5073: https://github.com/galaxyproject/galaxy/pull/5073 +.. _Pull Request 5074: https://github.com/galaxyproject/galaxy/pull/5074 +.. _Pull Request 5077: https://github.com/galaxyproject/galaxy/pull/5077 +.. _Pull Request 5078: https://github.com/galaxyproject/galaxy/pull/5078 +.. _Pull Request 5079: https://github.com/galaxyproject/galaxy/pull/5079 +.. _Pull Request 5080: https://github.com/galaxyproject/galaxy/pull/5080 +.. _Pull Request 5081: https://github.com/galaxyproject/galaxy/pull/5081 +.. _Pull Request 5086: https://github.com/galaxyproject/galaxy/pull/5086 +.. _Pull Request 5087: https://github.com/galaxyproject/galaxy/pull/5087 +.. _Pull Request 5088: https://github.com/galaxyproject/galaxy/pull/5088 +.. _Pull Request 5089: https://github.com/galaxyproject/galaxy/pull/5089 +.. _Pull Request 5091: https://github.com/galaxyproject/galaxy/pull/5091 +.. _Pull Request 5092: https://github.com/galaxyproject/galaxy/pull/5092 +.. _Pull Request 5093: https://github.com/galaxyproject/galaxy/pull/5093 +.. _Pull Request 5094: https://github.com/galaxyproject/galaxy/pull/5094 +.. _Pull Request 5095: https://github.com/galaxyproject/galaxy/pull/5095 +.. _Pull Request 5098: https://github.com/galaxyproject/galaxy/pull/5098 +.. _Pull Request 5099: https://github.com/galaxyproject/galaxy/pull/5099 +.. _Pull Request 5103: https://github.com/galaxyproject/galaxy/pull/5103 +.. _Pull Request 5104: https://github.com/galaxyproject/galaxy/pull/5104 +.. _Pull Request 5105: https://github.com/galaxyproject/galaxy/pull/5105 +.. _Pull Request 5106: https://github.com/galaxyproject/galaxy/pull/5106 +.. _Pull Request 5108: https://github.com/galaxyproject/galaxy/pull/5108 +.. _Pull Request 5109: https://github.com/galaxyproject/galaxy/pull/5109 +.. _Pull Request 5110: https://github.com/galaxyproject/galaxy/pull/5110 +.. _Pull Request 5114: https://github.com/galaxyproject/galaxy/pull/5114 +.. _Pull Request 5115: https://github.com/galaxyproject/galaxy/pull/5115 +.. _Pull Request 5116: https://github.com/galaxyproject/galaxy/pull/5116 +.. _Pull Request 5119: https://github.com/galaxyproject/galaxy/pull/5119 +.. _Pull Request 5121: https://github.com/galaxyproject/galaxy/pull/5121 +.. _Pull Request 5122: https://github.com/galaxyproject/galaxy/pull/5122 +.. _Pull Request 5124: https://github.com/galaxyproject/galaxy/pull/5124 +.. _Pull Request 5125: https://github.com/galaxyproject/galaxy/pull/5125 +.. _Pull Request 5128: https://github.com/galaxyproject/galaxy/pull/5128 +.. _Pull Request 5135: https://github.com/galaxyproject/galaxy/pull/5135 +.. _Pull Request 5137: https://github.com/galaxyproject/galaxy/pull/5137 +.. _Pull Request 5138: https://github.com/galaxyproject/galaxy/pull/5138 +.. _Pull Request 5139: https://github.com/galaxyproject/galaxy/pull/5139 +.. _Pull Request 5140: https://github.com/galaxyproject/galaxy/pull/5140 +.. _Pull Request 5143: https://github.com/galaxyproject/galaxy/pull/5143 +.. _Pull Request 5144: https://github.com/galaxyproject/galaxy/pull/5144 +.. _Pull Request 5145: https://github.com/galaxyproject/galaxy/pull/5145 +.. _Pull Request 5147: https://github.com/galaxyproject/galaxy/pull/5147 +.. _Pull Request 5154: https://github.com/galaxyproject/galaxy/pull/5154 +.. _Pull Request 5155: https://github.com/galaxyproject/galaxy/pull/5155 +.. _Pull Request 5156: https://github.com/galaxyproject/galaxy/pull/5156 +.. _Pull Request 5157: https://github.com/galaxyproject/galaxy/pull/5157 +.. _Pull Request 5161: https://github.com/galaxyproject/galaxy/pull/5161 +.. _Pull Request 5166: https://github.com/galaxyproject/galaxy/pull/5166 +.. _Pull Request 5170: https://github.com/galaxyproject/galaxy/pull/5170 +.. _Pull Request 5172: https://github.com/galaxyproject/galaxy/pull/5172 +.. _Pull Request 5173: https://github.com/galaxyproject/galaxy/pull/5173 +.. _Pull Request 5177: https://github.com/galaxyproject/galaxy/pull/5177 +.. _Pull Request 5180: https://github.com/galaxyproject/galaxy/pull/5180 +.. _Pull Request 5182: https://github.com/galaxyproject/galaxy/pull/5182 +.. _Pull Request 5185: https://github.com/galaxyproject/galaxy/pull/5185 +.. _Pull Request 5190: https://github.com/galaxyproject/galaxy/pull/5190 +.. _Pull Request 5191: https://github.com/galaxyproject/galaxy/pull/5191 +.. _Pull Request 5193: https://github.com/galaxyproject/galaxy/pull/5193 +.. _Pull Request 5196: https://github.com/galaxyproject/galaxy/pull/5196 +.. _Pull Request 5197: https://github.com/galaxyproject/galaxy/pull/5197 +.. _Pull Request 5198: https://github.com/galaxyproject/galaxy/pull/5198 +.. _Pull Request 5199: https://github.com/galaxyproject/galaxy/pull/5199 +.. _Pull Request 5200: https://github.com/galaxyproject/galaxy/pull/5200 +.. _Pull Request 5202: https://github.com/galaxyproject/galaxy/pull/5202 +.. _Pull Request 5204: https://github.com/galaxyproject/galaxy/pull/5204 +.. _Pull Request 5206: https://github.com/galaxyproject/galaxy/pull/5206 +.. _Pull Request 5208: https://github.com/galaxyproject/galaxy/pull/5208 +.. _Pull Request 5209: https://github.com/galaxyproject/galaxy/pull/5209 +.. _Pull Request 5210: https://github.com/galaxyproject/galaxy/pull/5210 +.. _Pull Request 5211: https://github.com/galaxyproject/galaxy/pull/5211 +.. _Pull Request 5212: https://github.com/galaxyproject/galaxy/pull/5212 +.. _Pull Request 5215: https://github.com/galaxyproject/galaxy/pull/5215 +.. _Pull Request 5217: https://github.com/galaxyproject/galaxy/pull/5217 +.. _Pull Request 5221: https://github.com/galaxyproject/galaxy/pull/5221 +.. _Pull Request 5223: https://github.com/galaxyproject/galaxy/pull/5223 +.. _Pull Request 5225: https://github.com/galaxyproject/galaxy/pull/5225 +.. _Pull Request 5226: https://github.com/galaxyproject/galaxy/pull/5226 +.. _Pull Request 5228: https://github.com/galaxyproject/galaxy/pull/5228 +.. _Pull Request 5229: https://github.com/galaxyproject/galaxy/pull/5229 +.. _Pull Request 5230: https://github.com/galaxyproject/galaxy/pull/5230 +.. _Pull Request 5232: https://github.com/galaxyproject/galaxy/pull/5232 +.. _Pull Request 5233: https://github.com/galaxyproject/galaxy/pull/5233 +.. _Pull Request 5234: https://github.com/galaxyproject/galaxy/pull/5234 +.. _Pull Request 5235: https://github.com/galaxyproject/galaxy/pull/5235 +.. _Pull Request 5237: https://github.com/galaxyproject/galaxy/pull/5237 +.. _Pull Request 5238: https://github.com/galaxyproject/galaxy/pull/5238 +.. _Pull Request 5240: https://github.com/galaxyproject/galaxy/pull/5240 +.. _Pull Request 5247: https://github.com/galaxyproject/galaxy/pull/5247 +.. _Pull Request 5249: https://github.com/galaxyproject/galaxy/pull/5249 +.. _Pull Request 5251: https://github.com/galaxyproject/galaxy/pull/5251 +.. _Pull Request 5253: https://github.com/galaxyproject/galaxy/pull/5253 +.. _Pull Request 5254: https://github.com/galaxyproject/galaxy/pull/5254 +.. _Pull Request 5258: https://github.com/galaxyproject/galaxy/pull/5258 +.. _Pull Request 5259: https://github.com/galaxyproject/galaxy/pull/5259 +.. _Pull Request 5260: https://github.com/galaxyproject/galaxy/pull/5260 +.. _Pull Request 5261: https://github.com/galaxyproject/galaxy/pull/5261 +.. _Pull Request 5262: https://github.com/galaxyproject/galaxy/pull/5262 +.. _Pull Request 5264: https://github.com/galaxyproject/galaxy/pull/5264 +.. _Pull Request 5266: https://github.com/galaxyproject/galaxy/pull/5266 +.. _Pull Request 5270: https://github.com/galaxyproject/galaxy/pull/5270 +.. _Pull Request 5272: https://github.com/galaxyproject/galaxy/pull/5272 +.. _Pull Request 5273: https://github.com/galaxyproject/galaxy/pull/5273 +.. _Pull Request 5276: https://github.com/galaxyproject/galaxy/pull/5276 +.. _Pull Request 5278: https://github.com/galaxyproject/galaxy/pull/5278 +.. _Pull Request 5279: https://github.com/galaxyproject/galaxy/pull/5279 +.. _Pull Request 5286: https://github.com/galaxyproject/galaxy/pull/5286 +.. _Pull Request 5288: https://github.com/galaxyproject/galaxy/pull/5288 +.. _Pull Request 5289: https://github.com/galaxyproject/galaxy/pull/5289 +.. _Pull Request 5293: https://github.com/galaxyproject/galaxy/pull/5293 +.. _Pull Request 5294: https://github.com/galaxyproject/galaxy/pull/5294 +.. _Pull Request 5295: https://github.com/galaxyproject/galaxy/pull/5295 +.. _Pull Request 5297: https://github.com/galaxyproject/galaxy/pull/5297 +.. _Pull Request 5299: https://github.com/galaxyproject/galaxy/pull/5299 +.. _Pull Request 5300: https://github.com/galaxyproject/galaxy/pull/5300 +.. _Pull Request 5301: https://github.com/galaxyproject/galaxy/pull/5301 +.. _Pull Request 5303: https://github.com/galaxyproject/galaxy/pull/5303 +.. _Pull Request 5304: https://github.com/galaxyproject/galaxy/pull/5304 +.. _Pull Request 5306: https://github.com/galaxyproject/galaxy/pull/5306 +.. _Pull Request 5311: https://github.com/galaxyproject/galaxy/pull/5311 +.. _Pull Request 5312: https://github.com/galaxyproject/galaxy/pull/5312 +.. _Pull Request 5321: https://github.com/galaxyproject/galaxy/pull/5321 +.. _Pull Request 5327: https://github.com/galaxyproject/galaxy/pull/5327 +.. _Pull Request 5331: https://github.com/galaxyproject/galaxy/pull/5331 +.. _Pull Request 5333: https://github.com/galaxyproject/galaxy/pull/5333 +.. _Pull Request 5335: https://github.com/galaxyproject/galaxy/pull/5335 +.. _Pull Request 5337: https://github.com/galaxyproject/galaxy/pull/5337 +.. _Pull Request 5340: https://github.com/galaxyproject/galaxy/pull/5340 +.. _Pull Request 5342: https://github.com/galaxyproject/galaxy/pull/5342 +.. _Pull Request 5343: https://github.com/galaxyproject/galaxy/pull/5343 +.. _Pull Request 5344: https://github.com/galaxyproject/galaxy/pull/5344 +.. _Pull Request 5346: https://github.com/galaxyproject/galaxy/pull/5346 +.. _Pull Request 5351: https://github.com/galaxyproject/galaxy/pull/5351 +.. _Pull Request 5353: https://github.com/galaxyproject/galaxy/pull/5353 +.. _Pull Request 5357: https://github.com/galaxyproject/galaxy/pull/5357 +.. _Pull Request 5358: https://github.com/galaxyproject/galaxy/pull/5358 +.. _Pull Request 5363: https://github.com/galaxyproject/galaxy/pull/5363 +.. _Pull Request 5364: https://github.com/galaxyproject/galaxy/pull/5364 +.. _Pull Request 5367: https://github.com/galaxyproject/galaxy/pull/5367 +.. _Pull Request 5368: https://github.com/galaxyproject/galaxy/pull/5368 +.. _Pull Request 5371: https://github.com/galaxyproject/galaxy/pull/5371 +.. _Pull Request 5373: https://github.com/galaxyproject/galaxy/pull/5373 +.. _Pull Request 5376: https://github.com/galaxyproject/galaxy/pull/5376 +.. _Pull Request 5377: https://github.com/galaxyproject/galaxy/pull/5377 +.. _Pull Request 5382: https://github.com/galaxyproject/galaxy/pull/5382 +.. _Pull Request 5383: https://github.com/galaxyproject/galaxy/pull/5383 +.. _Pull Request 5387: https://github.com/galaxyproject/galaxy/pull/5387 +.. _Pull Request 5390: https://github.com/galaxyproject/galaxy/pull/5390 +.. _Pull Request 5395: https://github.com/galaxyproject/galaxy/pull/5395 +.. _Pull Request 5397: https://github.com/galaxyproject/galaxy/pull/5397 +.. _Pull Request 5398: https://github.com/galaxyproject/galaxy/pull/5398 +.. _Pull Request 5403: https://github.com/galaxyproject/galaxy/pull/5403 +.. _Pull Request 5406: https://github.com/galaxyproject/galaxy/pull/5406 +.. _Pull Request 5413: https://github.com/galaxyproject/galaxy/pull/5413 +.. _Pull Request 5414: https://github.com/galaxyproject/galaxy/pull/5414 +.. _Pull Request 5416: https://github.com/galaxyproject/galaxy/pull/5416 +.. _Pull Request 5418: https://github.com/galaxyproject/galaxy/pull/5418 +.. _Pull Request 5426: https://github.com/galaxyproject/galaxy/pull/5426 +.. _Pull Request 5433: https://github.com/galaxyproject/galaxy/pull/5433 +.. _Pull Request 5440: https://github.com/galaxyproject/galaxy/pull/5440 +.. _Pull Request 5441: https://github.com/galaxyproject/galaxy/pull/5441 +.. _Pull Request 5442: https://github.com/galaxyproject/galaxy/pull/5442 +.. _Pull Request 5443: https://github.com/galaxyproject/galaxy/pull/5443 +.. _Pull Request 5444: https://github.com/galaxyproject/galaxy/pull/5444 +.. _Pull Request 5445: https://github.com/galaxyproject/galaxy/pull/5445 +.. _Pull Request 5447: https://github.com/galaxyproject/galaxy/pull/5447 +.. _Pull Request 5449: https://github.com/galaxyproject/galaxy/pull/5449 +.. _Pull Request 5455: https://github.com/galaxyproject/galaxy/pull/5455 +.. _Pull Request 5456: https://github.com/galaxyproject/galaxy/pull/5456 +.. _Pull Request 5460: https://github.com/galaxyproject/galaxy/pull/5460 +.. _Pull Request 5467: https://github.com/galaxyproject/galaxy/pull/5467 +.. _Pull Request 5470: https://github.com/galaxyproject/galaxy/pull/5470 +.. _Pull Request 5482: https://github.com/galaxyproject/galaxy/pull/5482 +.. _Pull Request 5485: https://github.com/galaxyproject/galaxy/pull/5485 +.. _Pull Request 5491: https://github.com/galaxyproject/galaxy/pull/5491 +.. _Pull Request 5506: https://github.com/galaxyproject/galaxy/pull/5506 +.. _Pull Request 5510: https://github.com/galaxyproject/galaxy/pull/5510 +.. _Pull Request 5512: https://github.com/galaxyproject/galaxy/pull/5512 +.. _Pull Request 5514: https://github.com/galaxyproject/galaxy/pull/5514 +.. _Pull Request 5515: https://github.com/galaxyproject/galaxy/pull/5515 +.. _Pull Request 5521: https://github.com/galaxyproject/galaxy/pull/5521 +.. _Pull Request 5526: https://github.com/galaxyproject/galaxy/pull/5526 +.. _Pull Request 5528: https://github.com/galaxyproject/galaxy/pull/5528 +.. _Pull Request 5531: https://github.com/galaxyproject/galaxy/pull/5531 +.. _Pull Request 5532: https://github.com/galaxyproject/galaxy/pull/5532 +.. _Pull Request 5533: https://github.com/galaxyproject/galaxy/pull/5533 +.. _Pull Request 5535: https://github.com/galaxyproject/galaxy/pull/5535 +.. _Pull Request 5542: https://github.com/galaxyproject/galaxy/pull/5542 +.. _Pull Request 5552: https://github.com/galaxyproject/galaxy/pull/5552 +.. _Pull Request 5556: https://github.com/galaxyproject/galaxy/pull/5556 +.. _Pull Request 5558: https://github.com/galaxyproject/galaxy/pull/5558 +.. _Pull Request 5561: https://github.com/galaxyproject/galaxy/pull/5561 +.. _Pull Request 5566: https://github.com/galaxyproject/galaxy/pull/5566 +.. _Pull Request 5569: https://github.com/galaxyproject/galaxy/pull/5569 +.. _Pull Request 5573: https://github.com/galaxyproject/galaxy/pull/5573 +.. _Pull Request 5574: https://github.com/galaxyproject/galaxy/pull/5574 +.. _Pull Request 5575: https://github.com/galaxyproject/galaxy/pull/5575 +.. _Pull Request 5576: https://github.com/galaxyproject/galaxy/pull/5576 +.. _Pull Request 5578: https://github.com/galaxyproject/galaxy/pull/5578 +.. _Pull Request 5579: https://github.com/galaxyproject/galaxy/pull/5579 +.. _Pull Request 5582: https://github.com/galaxyproject/galaxy/pull/5582 +.. _Pull Request 5583: https://github.com/galaxyproject/galaxy/pull/5583 +.. _Pull Request 5588: https://github.com/galaxyproject/galaxy/pull/5588 +.. _Pull Request 5589: https://github.com/galaxyproject/galaxy/pull/5589 +.. _Pull Request 5600: https://github.com/galaxyproject/galaxy/pull/5600 +.. _Pull Request 5605: https://github.com/galaxyproject/galaxy/pull/5605 +.. _Pull Request 5615: https://github.com/galaxyproject/galaxy/pull/5615 +.. _Pull Request 5616: https://github.com/galaxyproject/galaxy/pull/5616 +.. _Pull Request 5620: https://github.com/galaxyproject/galaxy/pull/5620 +.. _Pull Request 5626: https://github.com/galaxyproject/galaxy/pull/5626 +.. _Pull Request 5631: https://github.com/galaxyproject/galaxy/pull/5631 +.. _Pull Request 5634: https://github.com/galaxyproject/galaxy/pull/5634 +.. _Pull Request 5635: https://github.com/galaxyproject/galaxy/pull/5635 +.. _Pull Request 5643: https://github.com/galaxyproject/galaxy/pull/5643 +.. _Pull Request 5644: https://github.com/galaxyproject/galaxy/pull/5644 +.. _Pull Request 5650: https://github.com/galaxyproject/galaxy/pull/5650 +.. _Pull Request 5662: https://github.com/galaxyproject/galaxy/pull/5662 +.. _Pull Request 5663: https://github.com/galaxyproject/galaxy/pull/5663 +.. _Pull Request 5664: https://github.com/galaxyproject/galaxy/pull/5664 +.. _Pull Request 5665: https://github.com/galaxyproject/galaxy/pull/5665 +.. _Pull Request 5674: https://github.com/galaxyproject/galaxy/pull/5674 diff --git a/doc/source/releases/18.01_announce.rst b/doc/source/releases/18.01_announce.rst index b62092b1e06..5cd42a4125d 100644 --- a/doc/source/releases/18.01_announce.rst +++ b/doc/source/releases/18.01_announce.rst @@ -3,8 +3,145 @@ January 2018 Galaxy Release (v 18.01) =========================================================== +.. include:: _header.rst -Schedule +Highlights =========================================================== - * Planned Freeze Date: 2018-01-08 - * Planned Release Date: 2018-01-29 + +**Performance and User Experience Improvements** + We made Galaxy more lively and responsive. Homepage, published workflows, published/saved histories, and data libraries should all load much faster now. Importing data from FTP will also take less of your time. + We achieved this by optimizing database queries, implementing cache, rethinking presentation, and adding progress bars and loading indicators where needed. See the `list of related performance pull requests`_. + +**Web Server and Configuration** + The default web server used by Galaxy has changed from Paste to `uWSGI `__ and the default configuration file for Galaxy is now ``config/galaxy.yml`` instead of ``config/galaxy.ini``. + uWSGI is more production ready and allows Galaxy to scale better in its default + configuration. In the future uWSGI will allow Galaxy to setup GIE proxies without additional + configuration and use modern web technologies such as web sockets. + Read more about the server, configuration, and documentation changes in the `uWSGI details`_ section of this document. + +**Dataset Collection Usability** + This release has significantly improved the usability of Galaxy dataset collections. Dozens of improvements + to collections have been made, some of the key highlights include: + + - Data library folders can now be sent to histories as a dataset collection. `Pull Request 4998`_, `Pull Request 5080`_ + - Failed dataset collection elements can now be fixed using job re-running (thanks to `@mvdbeek `__). `Pull Request 5321`_, `Pull Request 5247`_, `Pull Request 5270`_ + - Collections now appear with state and progress bars in the history panel and contained datasets + are hidden by default (with help from `@mvdbeek `__). + `Pull Request 5013`_, `Pull Request 5078`_ + - We added intuitive workflow post job actions for dataset collections. `Pull Request 5416`_, `Pull Request 5418`_, `Pull Request 5414`_ + - The web interface now supports collections with arbitrary nesting and size (with help + from `@mvdbeek `__). `Pull Request 4942`_, `Pull Request 4934`_, `Pull Request 5091`_ + - More robust nametag discovery and propagation when using collections. `Pull Request 5403`_ + +**Client Architecture** + The architecture for the client code that powers the Galaxy user interface has been significantly + overhauled. The code base has been converted to `ES6 `__, + `Yarn `__ now powers the build and dependency management of the code, + `Prettier `__ is now used to ensure consistent code formatting, + and the `VueJS `__ framework has been integrated. Taken together, these changes are + enabling Galaxy developers to write usable, responsive client code more quickly and concisely than + previously possible. A big thanks goes out to community contributions from + `@anuprulez `__ and `@anatskiy `__ that are + already converting existing Galaxy components to reactive VueJS ones. See the `list of related client pull requests`_. + +**New BAM datatypes** + Previously Galaxy only supported coordinate sorted BAM files by default (the ``bam`` datatype). In addition, this + release of Galaxy now supports three new types of BAM: + + - ``qname_sorted.bam``, that ensures that the file is queryname sorted (e.g. ``SO:queryname``); + - ``qname_input_sorted.bam``, that can be used to describe the output of aligners which generally keep mate pairs adjacent + - ``unsorted.bam``, that makes no assumptions about the sort order of the file. + + A huge thanks goes out to `@bgruening `__ and `@mvdbeek `__ who + implemented these datatypes. + + `Pull Request 5180`_, `Pull Request 5589`_, `Pull Request 5532`_, `Pull Request 5644`_, `Pull Request 5674`_ + +**Experimental Job Caching** + Galaxy can now be configured to allow users the option of skipping duplicated jobs if one with + identical parameters has been previously executed and simply reuse the previously generated outputs. + This contribution is thanks to `@mvdbeek `__. + + `Pull Request 4690`_ + + +Get Galaxy +========== + +The code lives at `Github `__ and you should have `Git `__ to obtain it. + +To get a new Galaxy repository run: + .. code-block:: shell + + $ git clone -b release_18.01 https://github.com/galaxyproject/galaxy.git + +To update an existing Galaxy repository run: + .. code-block:: shell + + $ git checkout release_18.01 && git pull --ff-only origin release_18.01 + +See the `community hub `__ for additional details regarding the source code locations. + + +Security +======== + +Breaking Changes +================ + +We have reworked the **Galaxy Webhook** interface so if you have custom webhooks at your instance +you need to take the following steps in order to make them work: + +1. Rename the main config file: .yml -> config.yml +2. In the config file, rename the name attribute: name -> id +3. Put all files into the plugin's root folder, which should contain only four files: ``config.yml`` (mandatory), ``__init__.py`` (optional), ``script.js`` (optional), ``styles.css`` (optional) + +Deprecation Notices +=================== + +* This is the last release we are shipping JavaScript source maps for Galaxy client. + +Removal Notices +=============== +The following features that have been deprecated in the past releases are being removed in 18.01: + +* Sample tracking +* Sample request and external services management +* Legacy library interface for Administrators + +In addition to that, the PlantTribes datatypes have been commented out in the source code. Uncomment them if you want to re-enable it. + +uWSGI details +============= + +To minimize the impact of this change on existing Galaxy instances, if a Galaxy has a ``galaxy.ini`` +file configured, it will continue to use Paste by default unless additional steps are +taken by the administrator (Galaxy can be forced to start under uWSGI even with an older configuration file +by setting ``APP_WEBSERVER=uwsgi`` in the environment). As part of the transition to YAML-based +configuration files, we have implemented a schema to validate Galaxy configuration files. Run +``make config-validate`` from Galaxy's root directory to validate a schema and ``make config-lint`` to +check for best practices. While there is no need to convert your configuration file (``galaxy.ini`` hasn't +been deprecated), you can run ``make config-convert-dry-run`` and ``make config-convert`` +to respectively test and perform the conversion of an ``ini`` configuration file to a YAML one. + +These are big changes that affect many parts of Galaxy's administration documentation and makes +this documentation very dependent on which Galaxy version they are targeting. To address this, we have +moved a significant amount of administration documentation into Galaxy's code +base and made it available on a per-release basis. The latest administration documentation for +the previous release of Galaxy (17.09) which reference ``galaxy.ini`` files and Paste servers can +be found `here `__, while documentation for this release can be found `here `__. + +`Pull Request 4475`_, `Pull Request 5135`_, `Pull Request 5390`_, `Pull Request 5373`_, +`Pull Request 5105`_, `Pull Request 5441`_ + +Release Notes +============= + +.. include:: 18.01.rst + :start-after: announce_start + +Security patch details +====================== + +.. include:: _thanks.rst + diff --git a/doc/source/releases/18.05_announce.rst b/doc/source/releases/18.05_announce.rst new file mode 100644 index 00000000000..15f289f613b --- /dev/null +++ b/doc/source/releases/18.05_announce.rst @@ -0,0 +1,10 @@ + +=========================================================== +May 2018 Galaxy Release (v 18.05) +=========================================================== + + +Schedule +=========================================================== + * Planned Freeze Date: 2018-05-07 + * Planned Release Date: 2018-05-28 diff --git a/doc/source/releases/index.rst b/doc/source/releases/index.rst index 448ab9bfbd0..c3a0f71450c 100644 --- a/doc/source/releases/index.rst +++ b/doc/source/releases/index.rst @@ -4,6 +4,7 @@ Releases .. toctree:: :maxdepth: 1 + 18.01_announce 17.09_announce 17.05_announce 17.01_announce diff --git a/lib/galaxy/containers/docker_model.py b/lib/galaxy/containers/docker_model.py index 302708d48df..9342d7cadd7 100644 --- a/lib/galaxy/containers/docker_model.py +++ b/lib/galaxy/containers/docker_model.py @@ -85,7 +85,12 @@ class DockerContainer(Container): # } # ] rval = [] - port_mappings = self.inspect[0]['NetworkSettings']['Ports'] + try: + port_mappings = self.inspect[0]['NetworkSettings']['Ports'] + except (IndexError, KeyError) as exc: + log.warning("Failed to get ports for container %s from `docker inspect` output at " + "[0]['NetworkSettings']['Ports']: %s: %s", self.id, exc.__class__.__name__, str(exc)) + return None for port_name in port_mappings: for binding in port_mappings[port_name]: rval.append(ContainerPort( @@ -165,7 +170,12 @@ class DockerService(Container): # } # ] rval = [] - port_mappings = self.inspect[0]['Endpoint']['Ports'] + try: + port_mappings = self.inspect[0]['Endpoint']['Ports'] + except (IndexError, KeyError) as exc: + log.warning("Failed to get ports for container %s from `docker service inspect` output at " + "[0]['Endpoint']['Ports']: %s: %s", self.id, exc.__class__.__name__, str(exc)) + return None for binding in port_mappings: rval.append(ContainerPort( binding['TargetPort'], diff --git a/lib/galaxy/datatypes/binary.py b/lib/galaxy/datatypes/binary.py index 783f030177f..9d75f1232fb 100644 --- a/lib/galaxy/datatypes/binary.py +++ b/lib/galaxy/datatypes/binary.py @@ -192,7 +192,7 @@ class BamNative(Binary): """Class describing a BAM binary file that is not necessarily sorted""" edam_format = "format_2572" edam_data = "data_0863" - file_ext = "bam_native" + file_ext = "unsorted.bam" sort_flag = None MetadataElement(name="bam_index", desc="BAM Index File", param=metadata.FileParameter, file_ext="bai", readonly=True, no_value=None, visible=False, optional=True) diff --git a/lib/galaxy/datatypes/converters/bam_to_bigwig_converter.xml b/lib/galaxy/datatypes/converters/bam_to_bigwig_converter.xml index 50b8c1ca14c..43787ccc152 100644 --- a/lib/galaxy/datatypes/converters/bam_to_bigwig_converter.xml +++ b/lib/galaxy/datatypes/converters/bam_to_bigwig_converter.xml @@ -17,7 +17,7 @@ > temp.bg && bedGraphToBigWig temp.bg '$chromInfo' '$output']]> - + diff --git a/lib/galaxy/datatypes/converters/sam_to_bam_native.xml b/lib/galaxy/datatypes/converters/sam_to_unsorted_bam.xml similarity index 72% rename from lib/galaxy/datatypes/converters/sam_to_bam_native.xml rename to lib/galaxy/datatypes/converters/sam_to_unsorted_bam.xml index 1b0dfabe18b..2a99a793d27 100644 --- a/lib/galaxy/datatypes/converters/sam_to_bam_native.xml +++ b/lib/galaxy/datatypes/converters/sam_to_unsorted_bam.xml @@ -1,4 +1,4 @@ - + samtools @@ -15,7 +15,7 @@ - + diff --git a/lib/galaxy/datatypes/converters/to_coordinate_sorted_bam.xml b/lib/galaxy/datatypes/converters/to_coordinate_sorted_bam.xml index 30847c6437b..1e2889a921c 100644 --- a/lib/galaxy/datatypes/converters/to_coordinate_sorted_bam.xml +++ b/lib/galaxy/datatypes/converters/to_coordinate_sorted_bam.xml @@ -12,7 +12,7 @@ ]]> - + diff --git a/lib/galaxy/datatypes/converters/to_qname_sorted_bam.xml b/lib/galaxy/datatypes/converters/to_qname_sorted_bam.xml index ce606c5bf01..ced46c0cc31 100644 --- a/lib/galaxy/datatypes/converters/to_qname_sorted_bam.xml +++ b/lib/galaxy/datatypes/converters/to_qname_sorted_bam.xml @@ -13,7 +13,7 @@ ]]> - + diff --git a/lib/galaxy/datatypes/sniff.py b/lib/galaxy/datatypes/sniff.py index c69373b0669..221887ec82c 100644 --- a/lib/galaxy/datatypes/sniff.py +++ b/lib/galaxy/datatypes/sniff.py @@ -344,7 +344,7 @@ def guess_ext(fname, sniff_order): 'bam' >>> fname = get_test_fname('3unsorted.bam') >>> guess_ext(fname, sniff_order) - 'bam_native' + 'unsorted.bam' >>> fname = get_test_fname('test.idpDB') >>> guess_ext(fname, sniff_order) 'idpdb' diff --git a/lib/galaxy/tools/toolbox/filters/__init__.py b/lib/galaxy/tools/toolbox/filters/__init__.py index 8e9a1677f11..2184e37e846 100644 --- a/lib/galaxy/tools/toolbox/filters/__init__.py +++ b/lib/galaxy/tools/toolbox/filters/__init__.py @@ -34,7 +34,7 @@ class FilterFactory(object): filters = deepcopy(self.default_filters) if trans.user: for name, value in trans.user.preferences.items(): - if value.strip(): + if value and value.strip(): user_filters = listify(value, do_strip=True) category = '' if name == 'toolbox_tool_filters': diff --git a/lib/galaxy/tools/verify/interactor.py b/lib/galaxy/tools/verify/interactor.py index b1a28e27a3a..5623a7faa44 100644 --- a/lib/galaxy/tools/verify/interactor.py +++ b/lib/galaxy/tools/verify/interactor.py @@ -622,7 +622,7 @@ def _verify_extra_files_content(extra_files, hda_id, dataset_fetcher, test_data_ _verify_composite_datatype_file_content(filepath, hda_id, base_name=filename, attributes=attributes, dataset_fetcher=dataset_fetcher, test_data_path_builder=test_data_path_builder, keep_outputs_dir=keep_outputs_dir) -def verify_tool(tool_id, galaxy_interactor, resource_parameters={}, register_job_data=None, test_index=0, tool_version=None): +def verify_tool(tool_id, galaxy_interactor, resource_parameters={}, register_job_data=None, test_index=0, tool_version=None, quiet=False): tool_test_dicts = galaxy_interactor.get_tool_tests(tool_id, tool_version=tool_version) tool_test_dict = tool_test_dicts[test_index] testdef = ToolTestDescription(tool_test_dict) @@ -642,6 +642,7 @@ def verify_tool(tool_id, galaxy_interactor, resource_parameters={}, register_job job_output_exceptions = None tool_execution_exception = None expected_failure_occurred = False + begin_time = time.time() try: try: tool_response = galaxy_interactor.run_tool(testdef, test_history, resource_parameters=resource_parameters) @@ -662,7 +663,7 @@ def verify_tool(tool_id, galaxy_interactor, resource_parameters={}, register_job assert data_list or data_collection_list try: - job_stdio = _verify_outputs(testdef, test_history, jobs, tool_id, data_list, data_collection_list, galaxy_interactor) + job_stdio = _verify_outputs(testdef, test_history, jobs, tool_id, data_list, data_collection_list, galaxy_interactor, quiet=quiet) except JobOutputsError as e: job_stdio = e.job_stdio job_output_exceptions = e.output_exceptions @@ -671,16 +672,26 @@ def verify_tool(tool_id, galaxy_interactor, resource_parameters={}, register_job job_output_exceptions = [e] raise e finally: - job_data = {} - if tool_inputs is not None: - job_data["inputs"] = tool_inputs - if job_stdio is not None: - job_data["job"] = job_stdio - if job_output_exceptions: - job_data["output_problems"] = [str(_) for _ in job_output_exceptions] - if tool_execution_exception: - job_data["execution_problem"] = str(tool_execution_exception) if register_job_data is not None: + end_time = time.time() + job_data = { + "tool_id": tool_id, + "tool_version": tool_version, + "test_index": test_index, + "time_seconds": end_time - begin_time, + } + if tool_inputs is not None: + job_data["inputs"] = tool_inputs + if job_stdio is not None: + job_data["job"] = job_stdio + status = "success" + if job_output_exceptions: + job_data["output_problems"] = [str(_) for _ in job_output_exceptions] + status = "failure" + if tool_execution_exception: + job_data["execution_problem"] = str(tool_execution_exception) + status = "error" + job_data["status"] = status register_job_data(job_data) galaxy_interactor.delete_history(test_history) @@ -698,7 +709,7 @@ def _handle_def_errors(testdef): raise Exception("Test parse failure") -def _verify_outputs(testdef, history, jobs, tool_id, data_list, data_collection_list, galaxy_interactor): +def _verify_outputs(testdef, history, jobs, tool_id, data_list, data_collection_list, galaxy_interactor, quiet=False): assert len(jobs) == 1, "Test framework logic error, somehow tool test resulted in more than one job." job = jobs[0] @@ -713,7 +724,7 @@ def _verify_outputs(testdef, history, jobs, tool_id, data_list, data_collection_ found_exceptions = [] def register_exception(e): - if not found_exceptions: + if not found_exceptions and not quiet: # Only print this stuff out once. for stream in ['stdout', 'stderr']: if stream in job_stdio: diff --git a/lib/galaxy/tools/verify/script.py b/lib/galaxy/tools/verify/script.py index b9ca7b58c64..64873a368f4 100644 --- a/lib/galaxy/tools/verify/script.py +++ b/lib/galaxy/tools/verify/script.py @@ -1,11 +1,14 @@ #!/usr/bin/env python +from __future__ import print_function + import argparse import json import sys from galaxy.tools.verify.interactor import GalaxyInteractorApi, verify_tool -DESCRIPTION = "Script to quickly run a tool test against a running Galaxy instance." +DESCRIPTION = """Script to quickly run a tool test against a running Galaxy instance.""" +ALL_TESTS = "*all_tests*" def main(argv=None): @@ -20,35 +23,70 @@ def main(argv=None): "keep_outputs_dir": args.output, } tool_id = args.tool_id - test_index = int(args.test_index) tool_version = args.tool_version galaxy_interactor = GalaxyInteractorApi(**galaxy_interactor_kwds) + raw_test_index = args.test_index + if raw_test_index == ALL_TESTS: + tool_test_dicts = galaxy_interactor.get_tool_tests(tool_id, tool_version=tool_version) + test_indices = list(range(len(tool_test_dicts))) + else: + test_indices = [int(raw_test_index)] test_results = [] - def _register_job_data(job_data): - test_results.append({ - 'id': tool_id + "-" + str(test_index), - 'has_data': True, - 'data': job_data, - }) + if args.append: + with open(args.output_json, "r") as f: + previous_results = json.load(f) + test_results = previous_results["tests"] - try: - verify_tool( - tool_id, galaxy_interactor, test_index=test_index, tool_version=tool_version, register_job_data=_register_job_data - ) - finally: - report_obj = { - 'version': '0.1', - 'tests': test_results, - } - output_json = args.output_json - if output_json: + exceptions = [] + verbose = args.verbose + for test_index in test_indices: + if tool_version: + tool_id_and_version = "%s/%s" % (tool_id, tool_version) + else: + tool_id_and_version = tool_id + + test_identifier = "tool %s test # %d" % (tool_id_and_version, test_index) + + def register(job_data): + test_results.append({ + 'id': tool_id + "-" + str(test_index), + 'has_data': True, + 'data': job_data, + }) + + try: + verify_tool( + tool_id, galaxy_interactor, test_index=test_index, tool_version=tool_version, + register_job_data=register, quiet=not verbose + ) + + if verbose: + print("%s passed" % test_identifier) + + except Exception as e: + if verbose: + print("%s failed, %s" % (test_identifier, e)) + exceptions.append(e) + + report_obj = { + 'version': '0.1', + 'tests': test_results, + } + output_json = args.output_json + if output_json: + if args.output_json == "-": + assert not args.append + print(json.dumps(report_obj)) + else: with open(args.output_json, "w") as f: - print(report_obj) json.dump(report_obj, f) + if exceptions: + raise exceptions[0] + def _arg_parser(): parser = argparse.ArgumentParser(description=DESCRIPTION) @@ -57,9 +95,11 @@ def _arg_parser(): parser.add_argument('-a', '--admin-key', default=None, help='Galaxy Admin API Key') parser.add_argument('-t', '--tool-id', default=None, help='Tool ID') parser.add_argument('--tool-version', default=None, help='Tool Version') - parser.add_argument('-i', '--test-index', default=0, help='Tool Test Index (starting at 0)') + parser.add_argument('-i', '--test-index', default=ALL_TESTS, help='Tool Test Index (starting at 0) - by default all tests will run.') parser.add_argument('-o', '--output', default=None, help='directory to dump outputs to') - parser.add_argument('-j', '--output_json', default=None, help='output metadata json') + parser.add_argument('--append', default=False, action="store_true", help="Extend a test record json (created with --output-json) with additional tests.") + parser.add_argument('-j', '--output-json', default=None, help='output metadata json') + parser.add_argument('--verbose', default=False, action="store_true", help="Verbose logging.") return parser diff --git a/lib/galaxy/visualization/plugins/interactive_environments.py b/lib/galaxy/visualization/plugins/interactive_environments.py index edb108eb864..10cb067282d 100644 --- a/lib/galaxy/visualization/plugins/interactive_environments.py +++ b/lib/galaxy/visualization/plugins/interactive_environments.py @@ -6,6 +6,7 @@ import shlex import stat import string import tempfile +import time import uuid from itertools import product from subprocess import PIPE, Popen @@ -442,7 +443,20 @@ class InteractiveEnvironmentRequest(object): """ run_args = self.container_run_args(image, env_override, volumes) container = self.attr.container_interface.run_in_container(None, **run_args) - container_port = self._find_port_mapping(container.ports) + attempt = 0 + container_ports = container.ports + while container_ports is None and attempt < 30: + # TODO: it would be better to do this in /interactive_environments/ready so the client doesn't block here, + # but _find_port_mapping needs certain non-persisted data (the port configured to be published) and the + # proxy manager doesn't have an update method, so that'd require bigger changes than I have the time for + # right now + attempt += 1 + log.warning("Sleeping for 2 seconds while waiting for container %s ports", container.id) + time.sleep(2) + container_ports = container.ports + if container_ports is None: + raise Exception("Failed to determine ports for container '%s' after 30 attempts" % container.id) + container_port = self._find_port_mapping(container_ports) log.debug("Container '%s' accessible at: %s:%s", container.id, container_port.hostaddr, container_port.hostport) self.attr.proxy_request = self.trans.app.proxy_manager.setup_proxy( self.trans, diff --git a/lib/galaxy/visualization/plugins/plugin.py b/lib/galaxy/visualization/plugins/plugin.py index b8508aebeef..5cae1668913 100644 --- a/lib/galaxy/visualization/plugins/plugin.py +++ b/lib/galaxy/visualization/plugins/plugin.py @@ -270,6 +270,14 @@ class InteractiveEnvironmentPlugin(VisualizationPlugin): context['base_url'] = 'interactive_environments' super(InteractiveEnvironmentPlugin, self).__init__(app, path, name, config, context=context, **kwargs) + def _error_template(self, trans): + return trans.fill_template('message.mako', + message='Loading the interactive environment failed, please contact the {admin_tag} for assistance'.format( + admin_tag='
Galaxy administrator'.format( + admin_mail=trans.app.config.error_email_to) + if trans.app.config.error_email_to else 'Galaxy administrator'), + status='error') + def _render(self, render_vars, trans=None, embedded=None, **kwargs): """ Override to add interactive environment specific template vars. @@ -295,16 +303,15 @@ class InteractiveEnvironmentPlugin(VisualizationPlugin): request = self.INTENV_REQUEST_FACTORY(trans, self) except Exception: log.exception("IE plugin request handling failed") - return trans.fill_template('message.mako', - message='Loading the interactive environment failed, please contact the {admin_tag} for assistance'.format( - admin_tag='Galaxy administrator'.format( - admin_mail=trans.app.config.error_email_to) - if trans.app.config.error_email_to else 'Galaxy administrator'), - status='error') + return self._error_template(trans) render_vars["ie_request"] = request template_filename = self.config['entry_point']['file'] - return trans.fill_template(template_filename, template_lookup=self.template_lookup, **render_vars) + try: + return trans.fill_template(template_filename, template_lookup=self.template_lookup, **render_vars) + except Exception: + log.exception("IE plugin template fill failed") + return self._error_template(trans) def _get_url(self): return url_for('interactive_environment_plugin', visualization_name=self.name) diff --git a/lib/galaxy/webapps/galaxy/controllers/history.py b/lib/galaxy/webapps/galaxy/controllers/history.py index 2e2d1909af5..9d51b8a7618 100644 --- a/lib/galaxy/webapps/galaxy/controllers/history.py +++ b/lib/galaxy/webapps/galaxy/controllers/history.py @@ -494,11 +494,10 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt history = trans.sa_session.query(model.History).options( eagerload_all('active_datasets.creating_job_associations.job.workflow_invocation_step.workflow_invocation.workflow'), ).get(id) - assert history - # TODO: formalize to trans.show_error - assert (history.user and (history.user.id == trans.user.id) or - (history.id == trans.history.id) or - (trans.user_is_admin())) + if not (history and ((history.user and trans.user and history.user.id == trans.user.id) or + (trans.history and history.id == trans.history.id) or + trans.user_is_admin())): + return trans.show_error_message("Cannot display history structure.") # Resolve jobs and workflow invocations for the datasets in the history # items is filled with items (hdas, jobs, or workflows) that go at the # top level @@ -1127,7 +1126,7 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt @web.expose def purge_deleted_datasets(self, trans): count = 0 - if trans.app.config.allow_user_dataset_purge: + if trans.app.config.allow_user_dataset_purge and trans.history: for hda in trans.history.datasets: if not hda.deleted or hda.purged: continue @@ -1145,7 +1144,8 @@ class HistoryController(BaseUIController, SharableMixin, UsesAnnotations, UsesIt except Exception: log.exception('Unable to purge dataset (%s) on purge of hda (%s):' % (hda.dataset.id, hda.id)) count += 1 - return trans.show_ok_message("%d datasets have been deleted permanently" % count, refresh_frames=['history']) + return trans.show_ok_message("%d datasets have been deleted permanently" % count, refresh_frames=['history']) + return trans.show_error_message("Cannot purge deleted datasets from this session.") @web.expose def delete(self, trans, id, purge=False): diff --git a/lib/galaxy/webapps/galaxy/controllers/user.py b/lib/galaxy/webapps/galaxy/controllers/user.py index 638659cf031..96ba8b0a786 100644 --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -925,7 +925,9 @@ class User(BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Create Check whether token fits the user and then activate the user's account. """ params = util.Params(kwd, sanitize=False) - email = unquote(params.get('email', None)) + email = params.get('email', None) + if email is not None: + email = unquote(email) activation_token = params.get('activation_token', None) if email is None or activation_token is None: @@ -934,6 +936,9 @@ class User(BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Create else: # Find the user user = trans.sa_session.query(trans.app.model.User).filter(trans.app.model.User.table.c.email == email).first() + if not user: + # Probably wrong email address + return trans.show_error_message("You are using an invalid activation link. Try to log in and we will send you a new activation email.
Go to login page.") % web.url_for(controller="root", action="index") # If the user is active already don't try to activate if user.active is True: return trans.show_ok_message("Your account is already active. Nothing has changed.
Go to login page.") % web.url_for(controller='root', action='index') diff --git a/lib/tool_shed/util/tool_util.py b/lib/tool_shed/util/tool_util.py index 42dc7132d44..3a6ac2069cb 100644 --- a/lib/tool_shed/util/tool_util.py +++ b/lib/tool_shed/util/tool_util.py @@ -43,6 +43,7 @@ def copy_sample_file(app, filename, dest_path=None): """ Copies a sample file at `filename` to `the dest_path` directory and strips the '.sample' extensions from `filename`. + Returns the path to the copied file (with the .sample extension). """ if dest_path is None: dest_path = os.path.abspath(app.config.tool_data_path) @@ -56,8 +57,10 @@ def copy_sample_file(app, filename, dest_path=None): shutil.copy(full_source_path, full_destination_path) # Only create the .loc file if it does not yet exist. We don't overwrite it in case it # contains stuff proprietary to the local instance. - if not os.path.lexists(os.path.join(dest_path, copied_file)): + non_sample_path = os.path.join(dest_path, copied_file) + if not os.path.lexists(non_sample_path): shutil.copy(full_source_path, os.path.join(dest_path, copied_file)) + return non_sample_path def copy_sample_files(app, sample_files, tool_path=None, sample_files_copied=None, dest_path=None): @@ -159,10 +162,10 @@ def handle_missing_index_file(app, tool_path, sample_files, repository_tools_tup for sample_file in sample_files: sample_file_name = basic_util.strip_path(sample_file) if sample_file_name == '%s.sample' % missing_file_name: - copy_sample_file(app, os.path.join(tool_path, sample_file)) + target_path = copy_sample_file(app, os.path.join(tool_path, sample_file)) if options.tool_data_table and options.tool_data_table.missing_index_file: - options.tool_data_table.handle_found_index_file(options.missing_index_file) - sample_files_copied.append(options.missing_index_file) + options.tool_data_table.handle_found_index_file(target_path) + sample_files_copied.append(target_path) break return repository_tools_tups, sample_files_copied diff --git a/test/functional/test_toolbox.py b/test/functional/test_toolbox.py index b503e1dc5b2..46b2cc941bf 100644 --- a/test/functional/test_toolbox.py +++ b/test/functional/test_toolbox.py @@ -10,6 +10,7 @@ except ImportError: return x from base.driver_util import setup_keep_outdir, target_url_parts +from base.instrument import register_job_data from galaxy.tools import DataManagerTool # noqa: I201 from galaxy.tools.verify.interactor import GalaxyInteractorApi, verify_tool # noqa: I201 from .twilltestcase import TwillTestCase @@ -37,7 +38,7 @@ class ToolTestCase(TwillTestCase): tool_id = self.tool_id assert tool_id - verify_tool(tool_id, self.galaxy_interactor, resource_parameters=resource_parameters, test_index=test_index, tool_version=tool_version) + verify_tool(tool_id, self.galaxy_interactor, resource_parameters=resource_parameters, test_index=test_index, tool_version=tool_version, register_job_data=register_job_data) @nottest diff --git a/test/functional/tools/sam_to_bam_native.xml b/test/functional/tools/sam_to_unsorted_bam.xml similarity index 92% rename from test/functional/tools/sam_to_bam_native.xml rename to test/functional/tools/sam_to_unsorted_bam.xml index b15fd0cbdde..3a0830e8838 100644 --- a/test/functional/tools/sam_to_bam_native.xml +++ b/test/functional/tools/sam_to_unsorted_bam.xml @@ -23,13 +23,13 @@ - + - + input1 or input2 @@ -46,12 +46,12 @@ - + - + diff --git a/test/functional/tools/sample_datatypes_conf.xml b/test/functional/tools/sample_datatypes_conf.xml index 29917074a99..3b8b0dc0d58 100644 --- a/test/functional/tools/sample_datatypes_conf.xml +++ b/test/functional/tools/sample_datatypes_conf.xml @@ -22,7 +22,7 @@ - + @@ -30,7 +30,7 @@ - + diff --git a/test/functional/tools/samples_tool_conf.xml b/test/functional/tools/samples_tool_conf.xml index 788bab2d293..b1cf03ed24d 100644 --- a/test/functional/tools/samples_tool_conf.xml +++ b/test/functional/tools/samples_tool_conf.xml @@ -86,7 +86,7 @@ - +