Merge branch 'dev' of https://github.com/galaxyproject/galaxy into realtimetools

This commit is contained in:
Daniel Blankenberg
2019-06-06 17:39:45 -04:00
90 changed files with 2739 additions and 995 deletions
+4
View File
@@ -2,6 +2,10 @@
.tox
.venv
.venv3
packages/*/.venv
packages/*/build
packages/*/dist
packages/venv
node_modules
database
doc/build
+1 -1
View File
@@ -1,5 +1,5 @@
FROM toolshed/requirements
MAINTAINER John Chilton, jmchilton@gmail.com
LABEL maintainer="John Chilton <jmchilton@gmail.com>"
RUN apt-get -qq update && \
apt-get install --no-install-recommends -y postgresql-client python-pip libffi-dev python-cffi && \
-27
View File
@@ -9,19 +9,6 @@ import mod_repo_status_view from "mvc/toolshed/repo-status-view";
import mod_workflows_view from "mvc/toolshed/workflows-view";
var AdminToolshedRouter = Backbone.Router.extend({
initialize: function() {
this.routesHit = 0;
// keep count of number of routes handled by the application
Backbone.history.on(
"route",
function() {
this.routesHit++;
},
this
);
this.bind("route", this.trackPageview);
},
routes: {
"": "toolsheds",
sheds: "toolsheds",
@@ -32,20 +19,6 @@ var AdminToolshedRouter = Backbone.Router.extend({
"categories/s/:tool_shed": "categories",
"category/s/:tool_shed/c/:category_id/k/:sort_key/p/:page/t/:sort_order": "repositories",
"repository/s/:tool_shed/r/:repository_id": "repository"
},
/**
* If more than one route has been hit the user did not land on current
* page directly so we can go back safely. Otherwise go to the home page.
* Use replaceState if available so the navigation doesn't create an
* extra history entry
*/
back: function() {
if (this.routesHit > 1) {
window.history.back();
} else {
this.navigate("#", { trigger: true, replace: true });
}
}
});
@@ -16,8 +16,8 @@
</template>
<script>
import { getAppRoot } from "onload/loadConfig";
import axios from "axios";
import { mapCacheActions } from "vuex-cache";
import { mapGetters } from "vuex";
export default {
props: {
@@ -37,44 +37,42 @@ export default {
}
},
data() {
return {
metricsByPlugins: {}
};
return {};
},
created: function() {
let url;
if (this.jobId) {
url = `${getAppRoot()}api/jobs/${this.jobId}/metrics`;
this.fetchJobMetricsForJobId(this.jobId);
} else {
url = `${getAppRoot()}api/datasets/${this.datasetId}/metrics?hda_ldda=${this.datasetType}`;
this.fetchJobMetricsForDatasetId({ datasetId: this.datasetId, datasetType: this.datasetType });
}
this.ajaxCall(url);
},
computed: {
...mapGetters(["getJobMetricsByDatasetId", "getJobMetricsByJobId"]),
jobMetrics: function() {
if (this.jobId) {
return this.getJobMetricsByJobId(this.jobId);
} else {
return this.getJobMetricsByDatasetId(this.datasetId, this.datasetType);
}
},
metricsByPlugins: function() {
const metricsByPlugins = {};
const metrics = this.jobMetrics;
metrics.forEach(metric => {
if (!(metric.plugin in metricsByPlugins)) {
metricsByPlugins[metric.plugin] = {};
}
const metricsForPlugin = metricsByPlugins[metric.plugin];
metricsForPlugin[metric.title] = metric.value;
});
return metricsByPlugins;
},
orderedPlugins: function() {
return Object.keys(this.metricsByPlugins).sort();
}
},
methods: {
ajaxCall: function(url) {
axios
.get(url)
.then(response => {
const metricsByPlugins = {};
const metrics = response.data;
metrics.forEach(metric => {
if (!(metric.plugin in metricsByPlugins)) {
metricsByPlugins[metric.plugin] = {};
}
const metricsForPlugin = metricsByPlugins[metric.plugin];
metricsForPlugin[metric.title] = metric.value;
});
this.metricsByPlugins = metricsByPlugins;
})
.catch(e => {
console.error(e);
});
}
...mapCacheActions(["fetchJobMetricsForDatasetId", "fetchJobMetricsForJobId"])
}
};
</script>
@@ -2,18 +2,17 @@
* Endpoint for mounting job metrics from non-Vue environment.
*/
import $ from "jquery";
import Vue from "vue";
import JobMetrics from "./JobMetrics.vue";
import { mountVueComponent } from "utils/mountVueComponent";
export const mountJobMetrics = (propsData = {}) => {
$(".job-metrics").each((index, el) => {
const jobId = $(el).attr("job_id");
const datasetId = $(el).attr("dataset_id");
const datasetType = $(el).attr("dataset_type") || "hda";
const component = Vue.extend(JobMetrics);
propsData.jobId = jobId;
propsData.datasetId = datasetId;
propsData.datasetType = datasetType;
return new component({ propsData: propsData }).$mount(el);
mountVueComponent(JobMetrics)(propsData, el);
});
};
@@ -756,7 +756,6 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
"click .order .set-order": "_chooseOrder",
"click #toggle-deleted": "_clickToggleDeletedDatasets",
"click #toggle-hidden": "_clickToggleHiddenDatasets"
//'dragstart .list-item .title-bar' : function( e ){ console.debug( 'ok' ); }
},
close: function(ev) {
@@ -768,6 +767,7 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
this.toggleDeletedHistories($(ev.currentTarget).is(":checked"));
this.toggleOptionsPopover();
},
/** Include deleted histories in the collection */
toggleDeletedHistories: function(show) {
if (show) {
@@ -835,7 +835,19 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** Set up any view plugins */
setUpBehaviors: function() {
this._moreOptionsPopover();
const searchHistories = searchFor => {
const multipanel = this;
this.historySearch = searchFor;
this.filters = [
function() {
// This is intentionally a function where 'this' gets
// bound, applying the filter to the model of the
// caller.
return this.model.matchesAll(multipanel.historySearch);
}
];
this.renderColumns(0);
};
// input to search histories
this.$("#search-histories").searchInput({
name: "search-histories",
@@ -847,17 +859,11 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
this.collection.fetchAll().done(() => {
this.$("#search-histories").searchInput("toggle-loading");
this.renderInfo("");
searchHistories(searchFor);
});
},
onsearch: searchFor => {
this.historySearch = searchFor;
this.filters = [
() => {
return this.model.matchesAll(this.historySearch);
}
];
this.renderColumns(0);
},
onsearch: searchHistories,
onclear: searchFor => {
this.historySearch = null;
//TODO: remove specifically not just reset
+66 -71
View File
@@ -14,23 +14,22 @@ import Webhooks from "mvc/webhooks";
import Vue from "vue";
import ToolEntryPoints from "components/ToolEntryPoints/ToolEntryPoints";
var View = Backbone.View.extend({
const View = Backbone.View.extend({
initialize: function(options) {
const Galaxy = getGalaxyInstance();
const self = this;
this.modal = Galaxy.modal || new Modal.View();
this.form = new ToolFormBase(
Utils.merge(
{
listen_to_history: true,
always_refresh: false,
buildmodel: function(process, form) {
var options = form.model.attributes;
buildmodel: (process, form) => {
const options = form.model.attributes;
// build request url
var build_url = "";
var build_data = {};
var job_id = options.job_id;
let build_url = "";
let build_data = {};
const job_id = options.job_id;
if (job_id) {
build_url = `${getAppRoot()}api/jobs/${job_id}/build_for_rerun`;
} else {
@@ -44,18 +43,18 @@ var View = Backbone.View.extend({
Utils.get({
url: build_url,
data: build_data,
success: function(data) {
success: data => {
if (!data.display) {
window.location = getAppRoot();
return;
}
form.model.set(data);
self._customize(form);
this._customize(form);
Galaxy.emit.debug("tool-form-base::_buildModel()", "Initial tool model ready.", data);
process.resolve();
},
error: function(response, status) {
var error_message = (response && response.err_msg) || "Uncaught error.";
error: (response, status) => {
const error_message = (response && response.err_msg) || "Uncaught error.";
if (status == 401) {
window.location = `${getAppRoot()}user/login?${$.param({
redirect: `${getAppRoot()}?tool_id=${options.id}`
@@ -74,7 +73,7 @@ var View = Backbone.View.extend({
title: _l("Tool request failed"),
body: error_message,
buttons: {
Close: function() {
Close: () => {
Galaxy.modal.hide();
}
}
@@ -89,8 +88,8 @@ var View = Backbone.View.extend({
}
});
},
postchange: function(process, form) {
var current_state = {
postchange: (process, form) => {
const current_state = {
tool_id: form.model.get("id"),
tool_version: form.model.get("version"),
inputs: $.extend(true, {}, form.data.create())
@@ -101,13 +100,13 @@ var View = Backbone.View.extend({
type: "POST",
url: `${getAppRoot()}api/tools/${form.model.get("id")}/build`,
data: current_state,
success: function(data) {
success: data => {
form.update(data);
form.wait(false);
Galaxy.emit.debug("tool-form::postchange()", "Received new model.", data);
process.resolve();
},
error: function(response) {
error: response => {
Galaxy.emit.debug("tool-form::postchange()", "Refresh request failed.", response);
process.reject();
}
@@ -123,19 +122,18 @@ var View = Backbone.View.extend({
},
_customize: function(form) {
var self = this;
var options = form.model.attributes;
const options = form.model.attributes;
// build execute button
var execute_button = new Ui.Button({
const execute_button = new Ui.Button({
icon: "fa-check",
tooltip: `Execute: ${options.name} (${options.version})`,
title: _l("Execute"),
cls: "btn btn-primary",
wait_cls: "btn btn-info",
onclick: function() {
onclick: () => {
execute_button.wait();
form.portlet.disable();
self.submit(options, () => {
this.submit(options, () => {
execute_button.unwait();
form.portlet.enable();
});
@@ -145,7 +143,7 @@ var View = Backbone.View.extend({
// remap feature
if (options.job_id && options.job_remap) {
var label, help;
let label, help;
if (options.job_remap === "job_produced_collection_elements") {
label = "Replace elements in collection ?";
help =
@@ -169,11 +167,11 @@ var View = Backbone.View.extend({
// Job Re-use Options
const Galaxy = getGalaxyInstance();
var extra_user_preferences = {};
let extra_user_preferences = {};
if (Galaxy.user.attributes.preferences && "extra_user_preferences" in Galaxy.user.attributes.preferences) {
extra_user_preferences = JSON.parse(Galaxy.user.attributes.preferences.extra_user_preferences);
}
var use_cached_job =
const use_cached_job =
"use_cached_job|use_cached_job_checkbox" in extra_user_preferences
? extra_user_preferences["use_cached_job|use_cached_job_checkbox"]
: false;
@@ -198,7 +196,6 @@ var View = Backbone.View.extend({
submit: function(options, callback) {
const Galaxy = getGalaxyInstance();
const history_id = Galaxy.currHistoryPanel && Galaxy.currHistoryPanel.model.id;
const self = this;
const job_def = {
history_id: history_id,
tool_id: options.id,
@@ -206,7 +203,7 @@ var View = Backbone.View.extend({
inputs: this.form.data.create()
};
this.form.trigger("reset");
if (!self.validate(job_def)) {
if (!this.validate(job_def)) {
Galaxy.emit.debug("tool-form::submit()", "Submission canceled. Validation failed.");
callback && callback();
return;
@@ -232,14 +229,14 @@ var View = Backbone.View.extend({
type: "POST",
url: `${getAppRoot()}api/tools`,
data: job_def,
success: function(response) {
success: response => {
callback && callback();
self.$el.children().hide();
this.$el.children().hide();
if (response.produces_entry_points) {
for (const job of response.jobs) {
const toolEntryPointsInstance = Vue.extend(ToolEntryPoints);
const vm = document.createElement("div");
self.$el.append(vm);
this.$el.append(vm);
const instance = new toolEntryPointsInstance({
propsData: {
jobId: job.id
@@ -248,39 +245,40 @@ var View = Backbone.View.extend({
instance.$mount(vm);
}
}
self.$el.append(self._templateSuccess(response, job_def));
this.$el.append(this._templateSuccess(response, job_def));
this.$el.parent().scrollTop(0);
// Show Webhook if job is running
if (response.jobs && response.jobs.length > 0) {
self.$el.append($("<div/>", { id: "webhook-view" }));
this.$el.append($("<div/>", { id: "webhook-view" }));
new Webhooks.WebhookView({
type: "tool",
toolId: job_def.tool_id
});
}
if (Galaxy.currHistoryPanel) {
self.form.stopListening(Galaxy.currHistoryPanel.collection);
this.form.stopListening(Galaxy.currHistoryPanel.collection);
Galaxy.currHistoryPanel.refreshContents();
}
},
error: function(response) {
error: response => {
callback && callback();
Galaxy.emit.debug("tool-form::submit", "Submission failed.", response);
let input_found = false;
if (response && response.err_data) {
const error_messages = self.form.data.matchResponse(response.err_data);
const error_messages = this.form.data.matchResponse(response.err_data);
for (const input_id in error_messages) {
self.form.highlight(input_id, error_messages[input_id]);
this.form.highlight(input_id, error_messages[input_id]);
input_found = true;
break;
}
}
if (!input_found) {
self.modal.show({
this.modal.show({
title: _l("Job submission failed"),
body: self._templateError(job_def, response && response.err_msg),
body: this._templateError(job_def, response && response.err_msg),
buttons: {
Close: function() {
self.modal.hide();
Close: () => {
this.modal.hide();
}
}
});
@@ -294,14 +292,14 @@ var View = Backbone.View.extend({
*/
validate: function(job_def) {
const Galaxy = getGalaxyInstance();
var job_inputs = job_def.inputs;
var batch_n = -1;
var batch_src = null;
for (var job_input_id in job_inputs) {
var input_value = job_inputs[job_input_id];
var input_id = this.form.data.match(job_input_id);
var input_field = this.form.field_list[input_id];
var input_def = this.form.input_list[input_id];
const job_inputs = job_def.inputs;
let batch_n = -1;
let batch_src = null;
for (const job_input_id in job_inputs) {
const input_value = job_inputs[job_input_id];
const input_id = this.form.data.match(job_input_id);
const input_field = this.form.field_list[input_id];
const input_def = this.form.input_list[input_id];
if (!input_id || !input_def || !input_field) {
Galaxy.emit.debug("tool-form::validate()", "Retrieving input objects failed.");
continue;
@@ -318,8 +316,8 @@ var View = Backbone.View.extend({
}
}
if (input_value && input_value.batch) {
var n = input_value.values.length;
var src = n > 0 && input_value.values[0] && input_value.values[0].src;
const n = input_value.values.length;
const src = n > 0 && input_value.values[0] && input_value.values[0].src;
if (src) {
if (batch_src === null) {
batch_src = src;
@@ -346,8 +344,8 @@ var View = Backbone.View.extend({
},
_getInputs: function(job_def) {
var inputs = [];
var index = {};
const inputs = [];
const index = {};
for (const i in job_def.inputs) {
const input = job_def.inputs[i];
if (input && $.isArray(input.values)) {
@@ -362,36 +360,33 @@ var View = Backbone.View.extend({
return inputs;
},
_templateRow: function(list, title, max = 3) {
var blurb = "";
list.sort(function(a, b) {
return b.hid - a.hid;
});
_templateRow: function(list, title) {
let blurb = "";
if (list.length > 0) {
blurb += `<p>${title}:</p>`;
list.sort((a, b) => {
b.hid - a.hid;
});
blurb += `<ul>`;
for (const item of list) {
const rowString = max > 0 ? `${item.hid}: ${_.escape(item.name)}` : "...";
blurb += `<p class="messagerow">
<b>${rowString}</b>
</p>`;
if (max-- <= 0) {
break;
}
const rowString = `${item.hid}: ${_.escape(item.name)}`;
blurb += `<li><b>${rowString}</b></li>`;
}
blurb += `</ul>`;
}
return blurb;
},
_templateSuccess: function(response, job_def) {
var njobs = response && response.jobs ? response.jobs.length : 0;
const njobs = response && response.jobs ? response.jobs.length : 0;
if (njobs > 0) {
var inputs = this._getInputs(job_def);
var ninputs = inputs.length;
var noutputs = response.outputs.length;
var njobsText = njobs > 1 ? `${njobs} jobs` : `1 job`;
var ninputsText = ninputs > 1 ? `${ninputs} inputs` : `this input`;
var noutputsText = noutputs > 1 ? `${noutputs} outputs` : `this output`;
var tool_name = this.form.model.get("name");
const inputs = this._getInputs(job_def);
const ninputs = inputs.length;
const noutputs = response.outputs.length;
const njobsText = njobs > 1 ? `${njobs} jobs` : `1 job`;
const ninputsText = ninputs > 1 ? `${ninputs} inputs` : `this input`;
const noutputsText = noutputs > 1 ? `${noutputs} outputs` : `this output`;
const tool_name = this.form.model.get("name");
return `<div class="donemessagelarge">
<p>
Executed <b>${tool_name}</b> and successfully added ${njobsText} to the queue.
@@ -9,28 +9,23 @@ import "libs/jquery/jquery-ui";
var ToolShedCategories = Backbone.View.extend({
el: "#center",
defaults: {
tool_shed: "https://toolshed.g2.bx.psu.edu/"
},
initialize: function(options) {
var shed = options.tool_shed.replace(/\//g, "%2f");
this.options = _.defaults(this.options || options, this.defaults);
this.model = new toolshed_model.Categories();
this.listenTo(this.model, "sync", this.render);
this.model.url = `${this.model.url}?tool_shed_url=${this.options.tool_shed}`;
this.model.tool_shed = shed;
this.model.tool_shed = options.tool_shed.replace(/\//g, "%2f");
this.model.fetch();
this.listenTo(this.model, "sync", this.render);
},
render: function(options) {
const category_list_template = this.templateCategoryList();
this.options = _.extend(this.options, options);
this.options.categories = this.model.models;
this.options.queue = toolshed_util.queueLength();
var category_list_template = this.templateCategoryList;
this.$el.html(category_list_template(this.options));
$("#center").css("overflow", "auto");
this.bindEvents();
$("#center").css("overflow", "auto");
},
bindEvents: function() {
@@ -60,44 +55,42 @@ var ToolShedCategories = Backbone.View.extend({
});
},
templateCategoryList: _.template(
[
'<style type="text/css">',
".ui-autocomplete { background-color: #fff; }",
"li.ui-menu-item { list-style-type: none; }",
"</style>",
'<div class="unified-panel-header" id="panel_header" unselectable="on">',
'<div class="unified-panel-header-inner" style="layout: inline;">Categories in <%= tool_shed.replace(/%2f/g, "/") %><a class="ml-auto" href="#/queue">Repository Queue (<%= queue %>)</a></div>',
"</div>",
'<div class="unified-panel-body" id="list_categories">',
'<div id="standard-search" style="height: 2em; margin: 1em;">',
'<span class="ui-widget" >',
'<input class="search-box-input" id="search_box" data-shedurl="<%= tool_shed.replace(/%2f/g, "/") %>" name="search" placeholder="Search repositories by name or id" size="60" type="text" />',
"</span>",
"</div>",
'<div style="clear: both; margin-top: 1em;">',
'<table class="grid">',
'<thead id="grid-table-header">',
"<tr>",
"<th>Name</th>",
"<th>Description</th>",
"<th>Repositories</th>",
"</tr>",
"</thead>",
"<% _.each(categories, function(category) { %>",
"<tr>",
"<td>",
'<a href="#/category/s/<%= tool_shed %>/c/<%= category.get("id") %>/k/name/p/1/t/asc"><%= category.get("name") %></a>',
"</td>",
'<td><%= category.get("description") %></td>',
'<td><%= category.get("repositories") %></td>',
"</tr>",
"<% }); %>",
"</table>",
"</div>",
"</div>"
].join("")
)
templateCategoryList: function() {
return _.template(
`<div class='shed-style-container'>
<div class='header'>
<h2>Categories in <%= tool_shed.replace(/%2f/g, '/') %></h2>
<span><a href='#/queue'>Repository Queue (<%= queue %>)</a></span>
<span style='clear:both; '></span>
</div>
<div id='standard-search' style='height: 2em; margin: 1em;'>
<span class='ui-widget' >
<input class='search-box-input' id='search_box' data-shedurl='<%= tool_shed.replace(/%2f/g, '/') %>' name='search' placeholder='Search repositories' size='30' type='text' />
</span>
</div>
<div style='clear: both; margin-top: 1em;'>
<table class='grid'>
<thead id='grid-table-header'>
<tr>
<th>Name</th>
<th>Description</th>
<th>Repositories</th>
</tr>
</thead>
<% _.each(categories, function(category) { %>
<tr>
<td>
<a href='#/category/s/<%= tool_shed %>/c/<%= category.get('id') %>/k/name/p/1/t/asc'><%= category.get('name') %></a>
</td>
<td><%= category.get('description') %></td>
<td><%= category.get('repositories') %></td>
</tr>
<% }); %>
</table>
</div>
</div>`
);
}
});
export default {
@@ -38,7 +38,7 @@ var ToolShedRepoStatusView = Backbone.View.extend({
render: function(options) {
this.options = _.extend(this.options, options);
var repo_status_template = this.templateRepoStatus;
var repo_status_template = this.templateRepoStatus();
this.$el.html(
repo_status_template({
title: _l("Repository Status"),
@@ -49,80 +49,82 @@ var ToolShedRepoStatusView = Backbone.View.extend({
$("#center").css("overflow", "auto");
},
templateRepoStatus: _.template(
[
'<div class="unified-panel-header" id="panel_header" unselectable="on">',
'<div class="unified-panel-header-inner"><%= title %><a class="ml-auto" href="#/queue">Repository Queue (<%= queue %>)</a></div>',
"</div>",
'<style type="text/css">',
".state-color-new,",
".state-color-deactivated,",
".state-color-uninstalled { border-color:#bfbfbf; background:#eee }",
".state-color-cloning,",
".state-color-setting-tool-versions,",
".state-color-installing-repository-dependencies,",
".state-color-installing-tool-dependencies,",
".state-color-loading-proprietary-datatypes { border-color:#AAAA66; background:#FFFFCC }",
".state-color-installed { border-color:#20b520; background:#b0f1b0 }",
".state-color-error { border-color:#dd1b15; background:#f9c7c5 }",
"</style>",
'<table id="grid-table" class="grid">',
'<thead id="grid-table-header">',
"<tr>",
'<th id="null-header">Name<span class="sort-arrow"></span></th>',
'<th id="null-header">Description<span class="sort-arrow"></span></th>',
'<th id="null-header">Owner<span class="sort-arrow"></span></th>',
'<th id="null-header">Revision<span class="sort-arrow"></span></th>',
'<th id="null-header">Installation Status<span class="sort-arrow"></span></th>',
"</tr>",
"</thead>",
'<tbody id="grid-table-body">',
"<% _.each(repositories, function(repository) { %>",
"<tr>",
"<td>",
'<div id="" class="">',
'<label id="repo-name-<%= repository.get("id") %>" for="<%= repository.get("id") %>">',
'<%= repository.get("name") %>',
"</label>",
"</div>",
"</td>",
"<td>",
'<div id="" class="">',
'<label id="repo-desc-<%= repository.get("id") %>" for="<%= repository.get("id") %>">',
'<%= repository.get("description") %>',
"</label>",
"</div>",
"</td>",
"<td>",
'<div id="" class="">',
'<label id="repo-user-<%= repository.get("id") %>" for="<%= repository.get("id") %>">',
'<%= repository.get("owner") %>',
"</label>",
"</div>",
"</td>",
"<td>",
'<div id="" class="">',
'<label id="repo-changeset-<%= repository.get("id") %>" for="<%= repository.get("id") %>">',
'<%= repository.get("changeset_revision") %>',
"</label>",
"</div>",
"</td>",
"<td>",
'<div id="" class="">',
'<label id="RepositoryStatus-<%= repository.get("id") %>" for="<%= repository.get("id") %>">',
'<div class="repo-status count-box state-color-<%= repository.get("status").toLowerCase().replace(/ /g, "-") %>" id="RepositoryStatus-<%= repository.get("id") %>">',
'<%= repository.get("status") %>',
"</div>",
"</label>",
"</div>",
"</td>",
"</tr>",
"<% }); %>",
"</tbody>",
'<tfoot id="grid-table-footer"></tfoot>',
"</table>"
].join("")
)
templateRepoStatus: function() {
return _.template(
`<div class="unified-panel-header" id="panel_header" unselectable="on">
<div class="unified-panel-header-inner"><%= title %>
<a class="ml-auto" href="#/queue">Repository Queue (<%= queue %>)</a>
</div>
</div>
<style type="text/css">
.state-color-new,
.state-color-deactivated,
.state-color-uninstalled { border-color:#bfbfbf; background:#eee }
.state-color-cloning,
.state-color-setting-tool-versions,
.state-color-installing-repository-dependencies,
.state-color-installing-tool-dependencies,
.state-color-loading-proprietary-datatypes { border-color:#AAAA66; background:#FFFFCC }
.state-color-installed { border-color:#20b520; background:#b0f1b0 }
.state-color-error { border-color:#dd1b15; background:#f9c7c5 }
</style>
<table id="grid-table" class="grid">
<thead id="grid-table-header">
<tr>
<th id="null-header">Name<span class="sort-arrow"></span></th>
<th id="null-header">Description<span class="sort-arrow"></span></th>
<th id="null-header">Owner<span class="sort-arrow"></span></th>
<th id="null-header">Revision<span class="sort-arrow"></span></th>
<th id="null-header">Installation Status<span class="sort-arrow"></span></th>
</tr>
</thead>
<tbody id="grid-table-body">
<% _.each(repositories, function(repository) { %>
<tr>
<td>
<div id="" class="">
<label id="repo-name-<%= repository.get("id") %>" for="<%= repository.get("id") %>">
<%= repository.get("name") %>
</label>
</div>
</td>
<td>
<div id="" class="">
<label id="repo-desc-<%= repository.get("id") %>" for="<%= repository.get("id") %>">
<%= repository.get("description") %>
</label>
</div>
</td>
<td>
<div id="" class="">
<label id="repo-user-<%= repository.get("id") %>" for="<%= repository.get("id") %>">
<%= repository.get("owner") %>
</label>
</div>
</td>
<td>
<div id="" class="">
<label id="repo-changeset-<%= repository.get("id") %>" for="<%= repository.get("id") %>">
<%= repository.get("changeset_revision") %>
</label>
</div>
</td>
<td>
<div id="" class="">
<label id="RepositoryStatus-<%= repository.get("id") %>" for="<%= repository.get("id") %>">
<div class="repo-status count-box state-color-<%= repository.get("status").toLowerCase().replace(/ /g, "-") %>" id="RepositoryStatus-<%= repository.get("id") %>">
<%= repository.get("status") %>
</div>
</label>
</div>
</td>
</tr>
<% }); %>
</tbody>
<tfoot id="grid-table-footer"></tfoot>
</table>`
);
}
});
export default {
@@ -14,9 +14,11 @@ var ToolShedCategoryContentsView = Backbone.View.extend({
this.model = new toolshed_model.CategoryCollection();
this.listenTo(this.model, "sync", this.render);
var shed = params.tool_shed.replace(/\//g, "%2f");
this.model.url += `?tool_shed_url=${shed}&category_id=${params.category_id}&sort_key=${
params.sort_key
}&sort_order=${params.sort_order}&page=${params.page}`;
this.model.url += `?tool_shed_url=${shed}`;
this.model.url += `&category_id=${params.category_id}`;
this.model.url += `&sort_key=${params.sort_key}`;
this.model.url += `&sort_order=${params.sort_order}`;
this.model.url += `&page=${params.page}`;
this.model.tool_shed = shed;
this.model.category = params.category_id;
this.model.fetch();
@@ -24,8 +26,8 @@ var ToolShedCategoryContentsView = Backbone.View.extend({
render: function(options) {
this.options = _.defaults(this.options || {}, options);
var category_contents_template = this.templateCategoryContents;
var page_navigation_template = this.templatePageNavigation;
var category_contents_template = this.templateCategoryContents();
var page_navigation_template = this.templatePageNavigation();
var sorting = {
class: { owner: "fa-sort", description: "fa-sort", name: "fa-sort" },
direction: { owner: "asc", description: "asc", name: "asc" }
@@ -81,7 +83,7 @@ var ToolShedCategoryContentsView = Backbone.View.extend({
});
},
minLength: 3,
select: function(event, ui) {
select: (event, ui) => {
var tsr_id = ui.item.value;
var new_route = `repository/s/${this.model.tool_shed}/r/${tsr_id}`;
Backbone.history.navigate(new_route, {
@@ -114,105 +116,105 @@ var ToolShedCategoryContentsView = Backbone.View.extend({
});
},
templatePageNavigation: _.template(
[
'<div class="navigation">',
"<% if (page != 1) { %>",
'<a data-page="1" class="pagenav fa fa-fast-backward" />',
'<a data-page="<%= previous %>" class="pagenav fa fa-step-backward" />',
"<% } else { %>",
'<a data-page="1" class="pagenav-inactive fa fa-fast-backward" />',
'<a data-page="<%= previous %>" class="pagenav-inactive fa fa-step-backward" />',
"<% } %>",
"<% if (pages > 5) { %>",
"<% if (page != 1) { %>",
'<a data-page="1" class="pagenav fa"><a>1</a>',
"<% if (page != 2) { %>",
'<a class="fa">&hellip;</a>',
"<% } %>",
"<% } else { %>",
'<a data-page="1" class="pagenav-inactive fa"><a>1</a>',
"<% } %>",
"<% _.each(page_slice, function(i) { %>",
"<% if (i == page) { %>",
'<a data-page="<%= i %>" class="fa"><strong><%= i %></strong></a>',
"<% } else { %>",
'<a data-page="<%= i %>" class="pagenav fa"><%= i %></a>',
"<% } %>",
"<% }); %>",
"<% var last_pages = [pages - 2, pages - 1, pages]; %>",
"<% if (last_pages.indexOf(parseInt(page)) == -1) { %>",
'<a class="fa">&hellip;</a>',
'<a data-page="<%= pages %>" class="pagenav fa"><%= pages %></a>',
"<% } %>",
"<% } else { %>",
"<% for (i = 1; i <= pages; i++) { %>",
"<% if (i == page) { %>",
'<a data-page="<%= i %>" class="fa"><strong><%= i %></strong></a>',
"<% } else { %>",
'<a data-page="<%= i %>" class="pagenav fa"><%= i %></a>',
"<% } %>",
"<% } %>",
"<% } %>",
"<% if (page < pages) { %>",
'<a data-page="<%= next %>" class="pagenav fa fa-step-forward" />',
'<a data-page="<%= pages %>" class="pagenav fa fa-fast-forward" />',
"<% } else { %>",
'<a data-page="<%= next %>" class="pagenav-inactive fa fa-step-forward" />',
'<a data-page="<%= pages %>" class="pagenav-inactive fa fa-fast-forward" />',
"<% } %>",
"</div>"
].join("")
),
templatePageNavigation: function() {
return _.template(
`<div class="navigation">
<% if (page != 1) { %>
<a data-page="1" class="pagenav fa fa-fast-backward" />
<a data-page="<%= previous %>" class="pagenav fa fa-step-backward" />
<% } else { %>
<a data-page="1" class="pagenav-inactive fa fa-fast-backward" />
<a data-page="<%= previous %>" class="pagenav-inactive fa fa-step-backward" />
<% } %>
<% if (pages > 5) { %>
<% if (page != 1) { %>
<a data-page="1" class="pagenav fa"><a>1</a>
<% if (page != 2) { %>
<a class="fa">&hellip;</a>
<% } %>
<% } else { %>
<a data-page="1" class="pagenav-inactive fa"><a>1</a>
<% } %>
<% _.each(page_slice, function(i) { %>
<% if (i == page) { %>
<a data-page="<%= i %>" class="fa"><strong><%= i %></strong></a>
<% } else { %>
<a data-page="<%= i %>" class="pagenav fa"><%= i %></a>
<% } %>
<% }); %>
<% var last_pages = [pages - 2, pages - 1, pages]; %>
<% if (last_pages.indexOf(parseInt(page)) == -1) { %>
<a class="fa">&hellip;</a>
<a data-page="<%= pages %>" class="pagenav fa"><%= pages %></a>
<% } %>
<% } else { %>
<% for (i = 1; i <= pages; i++) { %>
<% if (i == page) { %>
<a data-page="<%= i %>" class="fa"><strong><%= i %></strong></a>
<% } else { %>
<a data-page="<%= i %>" class="pagenav fa"><%= i %></a>
<% } %>
<% } %>
<% } %>
<% if (page < pages) { %>
<a data-page="<%= next %>" class="pagenav fa fa-step-forward" />
<a data-page="<%= pages %>" class="pagenav fa fa-fast-forward" />
<% } else { %>
<a data-page="<%= next %>" class="pagenav-inactive fa fa-step-forward" />
<a data-page="<%= pages %>" class="pagenav-inactive fa fa-fast-forward" />
<% } %>
</div>`
);
},
templateCategoryContents: _.template(
[
'<style type="text/css">',
".ui-autocomplete { background-color: #fff; }",
"li.ui-menu-item { list-style-type: none; }",
"div.navigation { width: 100%; text-align: center; }",
"div.navigation a { margin-left: 0.5em; margin-right: 0.5em; display: inline; text-decoration: underline; }",
"a.pagenav-inactive { opacity: 0.5; }",
"</style>",
'<div class="unified-panel-header" id="panel_header" unselectable="on">',
'<div class="unified-panel-header-inner">Repositories in <%= category.get("name") %><a class="ml-auto" href="#/queue">Repository Queue (<%= queue %>)</a></div>',
"</div>",
'<div class="unified-panel-body" id="list_repositories">',
'<div id="standard-search" style="height: 2em; margin: 1em;">',
'<span class="ui-widget" >',
'<input class="search-box-input" id="search_box" name="search" data-shedurl="<%= tool_shed.replace(/%2f/g, "/") %>" placeholder="Search repositories by name or id" size="60" type="text" />',
"</span>",
"</div>",
"<% if (category.get('repository_count') > 25) { %>",
"<%= page_navigation %>",
"<% } %>",
'<div style="clear: both; margin-top: 1em;">',
'<table class="grid table-striped">',
'<thead id="grid-table-header">',
"<tr>",
'<th style="width: 10%;"><a class="fa fa-fw <%= sorting.class.owner %>" data-direction="<%= sorting.direction.owner %>" data-field="owner">Owner</a></th>',
'<th style="width: 15%;"><a class="fa fa-fw <%= sorting.class.name %>" data-direction="<%= sorting.direction.name %>" data-field="name">Name</a></th>',
'<th><a class="fa fa-fw <%= sorting.class.description %>" data-direction="<%= sorting.direction.description %>" data-field="description">Synopsis</a></th>',
'<th style="width: 10%;">Type</th>',
"</tr>",
"</thead>",
'<% _.each(category.get("repositories"), function(repository) { %>',
"<tr>",
"<td><%= repository.owner %></td>",
"<td>",
'<div style="float: left; margin-left: 1px;" class="menubutton split">',
'<a href="#/repository/s/<%= tool_shed %>/r/<%= repository.id %>"><%= repository.name %></a>',
"</div>",
"</td>",
"<td><%= repository.description %></td>",
"<td><%= repository.type %></td>",
"</tr>",
"<% }); %>",
"</table>",
"</div>",
"</div>"
].join("")
)
templateCategoryContents: function() {
return _.template(
`<style type="text/css">
.ui-autocomplete { background-color: #fff; }
li.ui-menu-item { list-style-type: none; }
div.navigation { width: 100%; text-align: center; }
div.navigation a { margin-left: 0.5em; margin-right: 0.5em; display: inline; text-decoration: underline; }
a.pagenav-inactive { opacity: 0.5; }
</style>
<div class="unified-panel-header" id="panel_header" unselectable="on">
<div class="unified-panel-header-inner">Repositories in <%= category.get("name") %><a class="ml-auto" href="#/queue">Repository Queue (<%= queue %>)</a></div>
</div>
<div class="unified-panel-body" id="list_repositories">
<div id="standard-search" style="height: 2em; margin: 1em;">
<span class="ui-widget" >
<input class="search-box-input" id="search_box" name="search" data-shedurl="<%= tool_shed.replace(/%2f/g, "/") %>" placeholder="Search repositories by name or id" size="60" type="text" />
</span>
</div>
<% if (category.get('repository_count') > 25) { %>
<%= page_navigation %>
<% } %>
<div style="clear: both; margin-top: 1em;">
<table class="grid table-striped">
<thead id="grid-table-header">
<tr>
<th style="width: 10%;"><a class="fa fa-fw <%= sorting.class.owner %>" data-direction="<%= sorting.direction.owner %>" data-field="owner">Owner</a></th>
<th style="width: 15%;"><a class="fa fa-fw <%= sorting.class.name %>" data-direction="<%= sorting.direction.name %>" data-field="name">Name</a></th>
<th><a class="fa fa-fw <%= sorting.class.description %>" data-direction="<%= sorting.direction.description %>" data-field="description">Synopsis</a></th>
<th style="width: 10%;">Type</th>
</tr>
</thead>
<% _.each(category.get("repositories"), function(repository) { %>
<tr>
<td><%= repository.owner %></td>
<td>
<div style="float: left; margin-left: 1px;" class="menubutton split">
<a href="#/repository/s/<%= tool_shed %>/r/<%= repository.id %>"><%= repository.name %></a>
</div>
</td>
<td><%= repository.description %></td>
<td><%= repository.type %></td>
</tr>
<% }); %>
</table>
</div>
</div>`
);
}
});
export default {
@@ -19,13 +19,11 @@ var View = Backbone.View.extend({
},
render: function(options) {
var repo_queue_template = this.templateRepoQueue;
var repo_queue_template = this.templateRepoQueue();
var repositories = this.model.models;
this.$el.html(
repo_queue_template({
title: _l("Repository Installation Queue"),
repositories: repositories,
empty: _l("No repositories in queue."),
queue: toolshed_util.queueLength()
})
);
@@ -35,20 +33,23 @@ var View = Backbone.View.extend({
bindEvents: function() {
$(".install_one").on("click", ev => {
var repository_metadata = this.loadFromQueue($(ev.target).attr("data-repokey"));
const repository_metadata = this.loadFromQueue($(ev.target).attr("data-repokey"));
this.installFromQueue(repository_metadata, $(ev.target).attr("data-repokey"));
});
$(".remove_one").on("click", ev => {
var queue_key = $(ev.target).attr("data-repokey");
var repo_queue = JSON.parse(window.localStorage.repositories);
const queue_key = $(ev.target).attr("data-repokey");
const repo_queue = JSON.parse(window.localStorage.repositories);
if (repo_queue.hasOwnProperty(queue_key)) {
var repository_id = repo_queue[queue_key].repository.id;
this.removeRow(repo_queue[queue_key].id);
delete repo_queue[queue_key];
$(`#queued_repository_${repository_id}`).remove();
}
window.localStorage.repositories = JSON.stringify(repo_queue);
});
$("#clear_queue").on("click", () => {
const repo_queue = JSON.parse(window.localStorage.repositories);
for (const key of Object.keys(repo_queue)) {
this.removeRow(repo_queue[key].id);
}
window.localStorage.repositories = "{}";
});
$("#from_workflow").on("click", () => {
@@ -59,6 +60,10 @@ var View = Backbone.View.extend({
});
},
removeRow: function(row_id) {
$(`#queued_repository_${row_id}`).remove();
},
installFromQueue: function(repository_metadata, queue_key) {
var params = {};
params.install_tool_dependencies = repository_metadata.install_tool_dependencies;
@@ -107,48 +112,53 @@ var View = Backbone.View.extend({
return this.defaults;
},
templateRepoQueue: _.template(
[
'<div class="unified-panel-header" id="panel_header" unselectable="on">',
'<div class="unified-panel-header-inner"><%= title %><a class="ml-auto" href="#/queue">Repository Queue (<%= queue %>)</a></div>',
"</div>",
'<div class="tab-pane" id="panel_header" id="repository_queue">',
'<table id="queued_repositories" class="grid" border="0" cellpadding="2" cellspacing="2" width="100%">',
'<thead id="grid-table-header">',
"<tr>",
'<th class="datasetRow">Name</th>',
'<th class="datasetRow">Owner</th>',
'<th class="datasetRow">Revision</th>',
'<th class="datasetRow">ToolShed</th>',
'<th class="datasetRow">Install</th>',
'<th class="datasetRow"><input class="btn btn-primary" type="submit" id="clear_queue" name="clear_queue" value="Clear queue" /></th>',
"</tr>",
"</thead>",
"<tbody>",
"<% if (repositories.length > 0) { %>",
"<% _.each(repositories, function(repository) { %>",
'<tr id="queued_repository_<%= repository.get("id") %>">',
'<td class="datasetRow"><%= repository.get("repository").name %></td>',
'<td class="datasetRow"><%= repository.get("repository").owner %></td>',
'<td class="datasetRow"><%= repository.get("changeset_revision") %></td>',
'<td class="datasetRow"><%= repository.get("tool_shed_url") %></td>',
'<td class="datasetRow">',
'<input class="btn btn-primary install_one" data-repokey="<%= repository.get("queue_key") %>" type="submit" id="install_repository_<%= repository.get("id") %>" name="install_repository" value="Install now" />',
"</td>",
'<td class="datasetRow">',
'<input class="btn btn-primary remove_one" data-repokey="<%= repository.get("queue_key") %>" type="submit" id="unqueue_repository_<%= repository.get("id") %>" name="unqueue_repository" value="Remove from queue" />',
"</td>",
"</tr>",
"<% }); %>",
"<% } else { %>",
'<tr><td colspan="6"><%= empty %></td></tr>',
"<% } %>",
"</tbody>",
"</table>",
'<input type="button" class="btn btn-primary" id="from_workflow" value="Add from workflow" />',
"</div>"
].join("")
)
templateRepoQueue: function() {
return _.template(
`<div class='shed-style-container'>
<h2>
${_l("Repository Queue")}
</h2>
<div class='tab-pane' id='panel_header' id='repository_queue'>
<table id='queued_repositories' class='grid' border='0' cellpadding='2' cellspacing='2' width='100%'>
<thead id='grid-table-header'>
<tr>
<th class='datasetRow'>Name</th>
<th class='datasetRow'>Owner</th>
<th class='datasetRow'>Revision</th>
<th class='datasetRow'>ToolShed</th>
<th class='datasetRow'>Install</th>
<th class='datasetRow'></th>
</tr>
</thead>
<tbody>
<% if (repositories.length > 0) { %>
<% _.each(repositories, function(repository) { %>
<tr id='queued_repository_<%= repository.get('id') %>'>
<td class='datasetRow'><%= repository.get('repository').name %></td>
<td class='datasetRow'><%= repository.get('repository').owner %></td>
<td class='datasetRow'><%= repository.get('changeset_revision') %></td>
<td class='datasetRow'><%= repository.get('tool_shed_url') %></td>
<td class='datasetRow'>
<input class='btn btn-primary install_one' data-repokey='<%= repository.get('queue_key') %>' type='submit' id='install_repository_<%= repository.get('id') %>' name='install_repository' value='Install now' />
</td>
<td class='datasetRow'>
<input class='btn btn-primary remove_one' data-repokey='<%= repository.get('queue_key') %>' type='submit' id='unqueue_repository_<%= repository.get('id') %>' name='unqueue_repository' value='Remove from queue' />
</td>
</tr>
<% }); %>
<% } else { %>
<tr><td colspan='6'>
${_l("No repositories in queue.")}
</td></tr>
<% } %>
</tbody>
</table>
<input type='button' class='btn btn-primary' id='from_workflow' value='Add from workflow' />
<input class='btn btn-primary' type='submit' id='clear_queue' name='clear_queue' value='Clear queue' />
</div>
</div>`
);
}
});
export default {
@@ -25,7 +25,7 @@ var ToolShedRepositoryView = Backbone.View.extend({
},
render: function(options) {
var repo_details_template = this.templateRepoDetails;
var repo_details_template = this.templateRepoDetails();
var models = this.model.models[0];
this.options = {
repository: models.get("repository"),
@@ -45,13 +45,13 @@ var ToolShedRepositoryView = Backbone.View.extend({
this.options.current_metadata = this.options.repository.metadata[this.options.current_changeset];
this.options.current_metadata.tool_shed_url = this.model.tool_shed_url;
this.options.tools = this.options.current_metadata.tools;
this.options.repository_dependencies_template = this.templateRepoDependencies;
this.options.repository_dependency_template = this.templateRepoDependency;
this.options.tps_template_global_select = this.templateGlobalSectionSelect;
this.options.tps_template_global_create = this.templateGlobalSectionCreate;
this.options.tps_template_tool_select = this.templateToolSectionSelect;
this.options.tps_template_tool_create = this.templateToolSectionCreate;
this.options.panel_section_options = this.templatePanelSelectOptions;
this.options.repository_dependencies_template = this.templateRepoDependencies();
this.options.repository_dependency_template = this.templateRepoDependency();
this.options.tps_template_global_select = this.templateGlobalSectionSelect();
this.options.tps_template_global_create = this.templateGlobalSectionCreate();
this.options.tps_template_tool_select = this.templateToolSectionSelect();
this.options.tps_template_tool_create = this.templateToolSectionCreate();
this.options.panel_section_options = this.templatePanelSelectOptions();
this.options.tool_dependencies = models.get("tool_dependencies");
this.options.shed_tool_conf = this.templateShedToolConf({
shed_tool_confs: models.get("shed_conf")
@@ -389,248 +389,248 @@ var ToolShedRepositoryView = Backbone.View.extend({
});
},
templateRepoDetails: _.template(
[
'<div class="unified-panel-header" id="panel_header" unselectable="on">',
'<div class="unified-panel-header-inner">Repository information for&nbsp;<strong><%= repository.name %></strong>&nbsp;from&nbsp;<strong><%= repository.owner %></strong><a class="ml-auto" href="#/queue">Repository Queue (<%= queue %>)</a></div>',
"</div>",
'<div class="unified-panel-body" id="repository_details" data-tsrid="<%= repository.id %>">',
'<form id="repository_installation" name="install_repository" method="post" action="<%= api_url %>">',
'<input type="hidden" id="repositories" name="<%= repository.id %>" value="ID" />',
'<input type="hidden" id="tool_shed_url" name="tool_shed_url" value="<%= tool_shed %>" />',
'<div class="toolForm">',
'<div class="toolFormTitle">Changeset</div>',
'<div class="toolFormBody changeset">',
'<select id="changeset" name="changeset" style="margin: 5px;">',
"<% _.each(Object.keys(repository.metadata), function(changeset) { %>",
'<% if (changeset == current_changeset) { var selected = "selected "; } else { var selected = ""; } %>',
'<option <%= selected %>value="<%= changeset.split(":")[1] %>"><%= changeset %></option>',
"<% }); %>",
"</select>",
'<input class="btn btn-primary preview-button" data-tsrid="<%= current_metadata.repository.id %>" type="submit" id="install_repository" name="install_repository" value="Install this revision now" />',
'<input class="btn btn-primary preview-button" type="button" id="queue_install" name="queue_install" value="Install this revision later" />',
'<div class="toolParamHelp" style="clear: both;">Please select a revision and review the settings below before installing.</div>',
"</div>",
"</div>",
"<%= shed_tool_conf %>",
"<% if (current_metadata.has_repository_dependencies) { %>",
'<div class="toolFormTitle">Repository dependencies for <strong id="current_changeset"><%= current_changeset %></strong></div>',
'<div class="toolFormBody">',
'<p id="install_repository_dependencies_checkbox">',
'<input type="checkbox" checked id="install_repository_dependencies" />',
'<label for="install_repository_dependencies">Install repository dependencies</label>',
"</p>",
"<% current_metadata.repository_dependency_template = repository_dependency_template; %>",
'<div class="tables container-table" id="repository_dependencies">',
'<div class="expandLink">',
'<a class="toggle_folder" data_target="repository_dependencies_table">',
"Repository dependencies &ndash; <em>installation of these additional repositories is required</em>",
"</a>",
"</div>",
"<%= repository_dependencies_template(current_metadata) %>",
"</div>",
"</div>",
"<% } %>",
"<% if (current_metadata.includes_tool_dependencies) { %>",
'<div class="toolFormTitle">Tool dependencies</div>',
'<div class="toolFormBody">',
'<p id="install_resolver_dependencies_checkbox">',
'<input type="checkbox" checked id="install_resolver_dependencies" />',
'<label for="install_resolver_dependencies">Install resolver dependencies</label>',
"</p>",
'<p id="install_tool_dependencies_checkbox">',
'<input type="checkbox" checked id="install_tool_dependencies" />',
'<label for="install_tool_dependencies">Install tool dependencies</label>',
"</p>",
'<div class="tables container-table" id="tool_dependencies">',
'<div class="expandLink">',
'<a class="toggle_folder" data_target="tool_dependencies_table">',
"Tool dependencies &ndash; <em>repository tools require handling of these dependencies</em>",
"</a>",
"</div>",
'<table class="tables container-table" id="tool_dependencies_table" border="0" cellpadding="2" cellspacing="2" width="100%">',
"<thead>",
'<tr style="display: table-row;" class="datasetRow" parent="0" id="libraryItem-rt-f9cad7b01a472135">',
'<th style="padding-left: 40px;">Name</th>',
"<th>Version</th>",
"<th>Type</th>",
"</tr>",
"</thead>",
'<tbody id="tool_deps">',
"<% _.each(tool_dependencies[current_changeset], function(dependency) { %>",
'<tr class="datasetRow tool_dependency_row" style="display: table-row;">',
'<td style="padding-left: 40px;">',
"<%= dependency.name %></td>",
"<td><%= dependency.version %></td>",
"<td><%= dependency.type %></td>",
"</tr>",
"<% }); %>",
"</tbody>",
"</table>",
"</div>",
"</div>",
"<% } %>",
"<% if (current_metadata.includes_tools_for_display_in_tool_panel) { %>",
'<div class="toolFormTitle">Tools &ndash; <em>click the name to preview the tool and use the pop-up menu to inspect all metadata</em></div>',
'<div class="toolFormBody">',
'<div class="tables container-table" id="tools_toggle">',
'<table class="tables container-table" id="valid_tools" border="0" cellpadding="2" cellspacing="2" width="100%">',
"<thead>",
'<tr style="display: table-row;" class="datasetRow" parent="0" id="libraryItem-rt-f9cad7b01a472135">',
'<th style="padding-left: 40px;">Name</th>',
"<th>Description</th>",
"<th>Version</th>",
"<th><%= tps_template_global_select({panel_section_dict: panel_section_dict, panel_section_options: panel_section_options}) %></tr>",
"</thead>",
'<tbody id="tools_in_repo">',
"<% _.each(current_metadata.tools, function(tool) { %>",
'<tr id="libraryItem-<%= tool.clean %>" class="tool_row" style="display: table-row;" style="width: 15%">',
'<td style="padding-left: 40px;">',
'<div id="tool-<%= tool.clean %>" class="menubutton split popup" style="float: left;">',
'<a class="tool_form view-info" data-toggle="modal" data-target="toolform_<%= tool.clean %>" data-clean="<%= tool.clean %>" data-guid="<%= tool.guid %>" data-name="<%= tool.name %>" data-desc="<%= tool.description %>"><%= tool["name"] %></a>',
"</div>",
"</td>",
"<td><%= tool.description %></td>",
'<td style="width: 15%"><%= tool.version %></td>',
'<td style="width: 35%" id="tool_tps_<%= tool.clean %>">',
"<%= tps_template_tool_select({tool: tool, panel_section_dict: panel_section_dict, panel_section_options: panel_section_options}) %>",
"</td>",
"</tr>",
"<% }); %>",
"</tbody>",
"</table>",
"</div>",
"</div>",
"<% } %>",
"</form>",
"</div>"
].join("")
),
templateRepoDetails: function() {
return _.template(
`<div class="unified-panel-header" id="panel_header" unselectable="on">
<div class="unified-panel-header-inner">Repository information for&nbsp;<strong><%= repository.name %></strong>&nbsp;from&nbsp;<strong><%= repository.owner %></strong><a class="ml-auto" href="#/queue">Repository Queue (<%= queue %>)</a></div>
</div>
<div class="unified-panel-body" id="repository_details" data-tsrid="<%= repository.id %>">
<form id="repository_installation" name="install_repository" method="post" action="<%= api_url %>">
<input type="hidden" id="repositories" name="<%= repository.id %>" value="ID" />
<input type="hidden" id="tool_shed_url" name="tool_shed_url" value="<%= tool_shed %>" />
<div class="toolForm">
<div class="toolFormTitle">Changeset</div>
<div class="toolFormBody changeset">
<select id="changeset" name="changeset" style="margin: 5px;">
<% _.each(Object.keys(repository.metadata), function(changeset) { %>
<% if (changeset == current_changeset) { var selected = "selected "; } else { var selected = ""; } %>
<option <%= selected %>value="<%= changeset.split(":")[1] %>"><%= changeset %></option>
<% }); %>
</select>
<input class="btn btn-primary preview-button" data-tsrid="<%= current_metadata.repository.id %>" type="submit" id="install_repository" name="install_repository" value="Install this revision now" />
<input class="btn btn-primary preview-button" type="button" id="queue_install" name="queue_install" value="Install this revision later" />
<div class="toolParamHelp" style="clear: both;">Please select a revision and review the settings below before installing.</div>
</div>
</div>
<%= shed_tool_conf %>
<% if (current_metadata.has_repository_dependencies) { %>
<div class="toolFormTitle">Repository dependencies for <strong id="current_changeset"><%= current_changeset %></strong></div>
<div class="toolFormBody">
<p id="install_repository_dependencies_checkbox">
<input type="checkbox" checked id="install_repository_dependencies" />
<label for="install_repository_dependencies">Install repository dependencies</label>
</p>
<% current_metadata.repository_dependency_template = repository_dependency_template; %>
<div class="tables container-table" id="repository_dependencies">
<div class="expandLink">
<a class="toggle_folder" data_target="repository_dependencies_table">
Repository dependencies &ndash; <em>installation of these additional repositories is required</em>
</a>
</div>
<%= repository_dependencies_template(current_metadata) %>
</div>
</div>
<% } %>
<% if (current_metadata.includes_tool_dependencies) { %>
<div class="toolFormTitle">Tool dependencies</div>
<div class="toolFormBody">
<p id="install_resolver_dependencies_checkbox">
<input type="checkbox" checked id="install_resolver_dependencies" />
<label for="install_resolver_dependencies">Install resolver dependencies</label>
</p>
<p id="install_tool_dependencies_checkbox">
<input type="checkbox" checked id="install_tool_dependencies" />
<label for="install_tool_dependencies">Install tool dependencies</label>
</p>
<div class="tables container-table" id="tool_dependencies">
<div class="expandLink">
<a class="toggle_folder" data_target="tool_dependencies_table">
Tool dependencies &ndash; <em>repository tools require handling of these dependencies</em>
</a>
</div>
<table class="tables container-table" id="tool_dependencies_table" border="0" cellpadding="2" cellspacing="2" width="100%">
<thead>
<tr style="display: table-row;" class="datasetRow" parent="0" id="libraryItem-rt-f9cad7b01a472135">
<th style="padding-left: 40px;">Name</th>
<th>Version</th>
<th>Type</th>
</tr>
</thead>
<tbody id="tool_deps">
<% _.each(tool_dependencies[current_changeset], function(dependency) { %>
<tr class="datasetRow tool_dependency_row" style="display: table-row;">
<td style="padding-left: 40px;">
<%= dependency.name %></td>
<td><%= dependency.version %></td>
<td><%= dependency.type %></td>
</tr>
<% }); %>
</tbody>
</table>
</div>
</div>
<% } %>
<% if (current_metadata.includes_tools_for_display_in_tool_panel) { %>
<div class="toolFormTitle">Tools &ndash; <em>click the name to preview the tool and use the pop-up menu to inspect all metadata</em></div>
<div class="toolFormBody">
<div class="tables container-table" id="tools_toggle">
<table class="tables container-table" id="valid_tools" border="0" cellpadding="2" cellspacing="2" width="100%">
<thead>
<tr style="display: table-row;" class="datasetRow" parent="0" id="libraryItem-rt-f9cad7b01a472135">
<th style="padding-left: 40px;">Name</th>
<th>Description</th>
<th>Version</th>
<th><%= tps_template_global_select({panel_section_dict: panel_section_dict, panel_section_options: panel_section_options}) %></tr>
</thead>
<tbody id="tools_in_repo">
<% _.each(current_metadata.tools, function(tool) { %>
<tr id="libraryItem-<%= tool.clean %>" class="tool_row" style="display: table-row;" style="width: 15%">
<td style="padding-left: 40px;">
<div id="tool-<%= tool.clean %>" class="menubutton split popup" style="float: left;">
<a class="tool_form view-info" data-toggle="modal" data-target="toolform_<%= tool.clean %>" data-clean="<%= tool.clean %>" data-guid="<%= tool.guid %>" data-name="<%= tool.name %>" data-desc="<%= tool.description %>"><%= tool["name"] %></a>
</div>
</td>
<td><%= tool.description %></td>
<td style="width: 15%"><%= tool.version %></td>
<td style="width: 35%" id="tool_tps_<%= tool.clean %>">
<%= tps_template_tool_select({tool: tool, panel_section_dict: panel_section_dict, panel_section_options: panel_section_options}) %>
</td>
</tr>
<% }); %>
</tbody>
</table>
</div>
</div>
<% } %>
</form>
</div>`
);
},
templateRepoDependencies: _.template(
[
'<div class="toolFormTitle">Repository Dependencies</div>',
'<div class="toolFormBody tables container-table" id="repository_dependencies">',
"<ul>",
"<li>Repository installation requires the following",
"<% if (has_repository_dependencies) { %>",
"<% _.each(repository_dependencies, function(dependency) { %>",
"<% dependency.repository_dependency_template = repository_dependency_template; %>",
"<%= repository_dependency_template(dependency) %>",
"<% }); %>",
"<% } %>",
"</li>",
"</ul>",
"</div>"
].join("")
),
templateRepoDependencies: function() {
return _.template(
`<div class="toolFormTitle">Repository Dependencies</div>
<div class="toolFormBody tables container-table" id="repository_dependencies">
<ul>
<li>Repository installation requires the following
<% if (has_repository_dependencies) { %>
<% _.each(repository_dependencies, function(dependency) { %>
<% dependency.repository_dependency_template = repository_dependency_template; %>
<%= repository_dependency_template(dependency) %>
<% }); %>
<% } %>
</li>
</ul>
</div>`
);
},
templateRepoDependency: _.template(
[
'<li id="metadata_<%= id %>" class="datasetRow repository_dependency_row">',
"Repository <b><%= repository.name %></b> revision <b><%= changeset_revision %></b> owned by <b><%= repository.owner %></b>",
"<% if (has_repository_dependencies) { %>",
'<ul class="child_dependencies">',
"<% _.each(repository_dependencies, function(dependency) { %>",
"<% dependency.repository_dependency_template = repository_dependency_template; %>",
"<%= repository_dependency_template(dependency) %>",
"<% }); %>",
"</ul>",
"<% } %>",
"</li>"
].join("")
),
templateRepoDependency: function() {
return _.template(
`<li id="metadata_<%= id %>" class="datasetRow repository_dependency_row">
Repository <b><%= repository.name %></b> revision <b><%= changeset_revision %></b> owned by <b><%= repository.owner %></b>
<% if (has_repository_dependencies) { %>
<ul class="child_dependencies">
<% _.each(repository_dependencies, function(dependency) { %>
<% dependency.repository_dependency_template = repository_dependency_template; %>
<%= repository_dependency_template(dependency) %>
<% }); %>
</ul>
<% } %>
</li>`
);
},
templateShedToolConf: _.template(
[
'<div class="toolFormTitle">Shed tool configuration file:</div>',
'<div class="toolFormBody">',
'<div class="form-row">',
'<select name="shed_tool_conf">',
"<% _.each(shed_tool_confs.options, function(conf) { %>",
'<option value="<%= conf.value %>"><%= conf.label %></option>',
"<% }); %>",
"</select>",
'<div class="toolParamHelp" style="clear: both;">Select the file whose <b>tool_path</b> setting you want used for installing repositories.</div>',
"</div>",
"</div>"
].join("")
),
templateShedToolConf: function() {
return _.template(
`<div class="toolFormTitle">Shed tool configuration file:</div>
<div class="toolFormBody">
<div class="form-row">
<select name="shed_tool_conf">
<% _.each(shed_tool_confs.options, function(conf) { %>
<option value="<%= conf.value %>"><%= conf.label %></option>
<% }); %>
</select>
<div class="toolParamHelp" style="clear: both;">Select the file whose <b>tool_path</b> setting you want used for installing repositories.</div>
</div>
</div>`
);
},
templateToolDependency: _.template(
[
"<% if (has_repository_dependencies) { %>",
"<% _.each(repository_dependencies, function(dependency) { %>",
"<% if (dependency.includes_tool_dependencies) { %>",
"<% dependency.tool_dependency_template = tool_dependency_template %>",
"<%= tool_dependency_template(dependency) %>",
"<% } %>",
"<% }); %>",
"<% } %>"
].join("")
),
// templateToolDependency: function(){
// return _.template(
// `<% if (has_repository_dependencies) { %>
// <% _.each(repository_dependencies, function(dependency) { %>
// <% if (dependency.includes_tool_dependencies) { %>
// <% dependency.tool_dependency_template = tool_dependency_template %>
// <%= tool_dependency_template(dependency) %>
// <% } %>
// <% }); %>
// <% } %>`
// );
// },
templateGlobalSectionCreate: _.template(
[
'<div id="tool_panel_section">',
'<div class="form-row" id="new_tps">',
'<input id="new_tool_panel_section" name="new_tool_panel_section" type="textfield" value="" size="40"/>',
'<input class="btn btn-primary global-select-tps-button" type="button" id="select_existing" value="Select existing" />',
'<div class="toolParamHelp" style="clear: both;">',
"Add a new tool panel section to contain the installed tools (optional).",
"</div>",
"</div>",
"</div>"
].join("")
),
templateGlobalSectionCreate: function() {
return _.template(
`<div id="tool_panel_section">
<div class="form-row" id="new_tps">
<input id="new_tool_panel_section" name="new_tool_panel_section" type="textfield" value="" size="40"/>
<input class="btn btn-primary global-select-tps-button" type="button" id="select_existing" value="Select existing" />
<div class="toolParamHelp" style="clear: both;">
Add a new tool panel section to contain the installed tools (optional).
</div>
</div>
</div>`
);
},
templateGlobalSectionSelect: _.template(
[
'<div id="tool_panel_section">',
'<div class="toolFormTitle">Tool Panel Section</div>',
'<div class="toolFormBody">',
'<div class="tab-pane" id="select_tps">',
'<select name="<%= name %>" id="<%= panel_section_dict.id %>">',
"<%= panel_section_options({sections: panel_section_dict.sections}) %>",
"</select>",
'<input class="btn btn-primary global-create-tps-button" type="button" id="create_new" value="Create new" />',
'<div class="toolParamHelp" style="clear: both;">',
"Select an existing tool panel section to contain the installed tools (optional).",
"</div>",
"</div>",
"</div>",
"</div>"
].join("")
),
templateGlobalSectionSelect: function() {
return _.template(
`<div id="tool_panel_section">
<div class="toolFormTitle">Tool Panel Section</div>
<div class="toolFormBody">
<div class="tab-pane" id="select_tps">
<select name="<%= name %>" id="<%= panel_section_dict.id %>">
<%= panel_section_options({sections: panel_section_dict.sections}) %>
</select>
<input class="btn btn-primary global-create-tps-button" type="button" id="create_new" value="Create new" />
<div class="toolParamHelp" style="clear: both;">
Select an existing tool panel section to contain the installed tools (optional).
</div>
</div>
</div>
</div>`
);
},
templateToolSectionCreate: _.template(
[
'<div id="new_tps_<%= tool.clean %>" data-clean="<%= tool.clean %>" class="form-row">',
'<input data-toolguid="<%= tool.guid %>" class="tool_panel_section_picker" size="40" name="new_tool_panel_section" id="new_tool_panel_section_<%= tool.clean %>" type="text">',
'<input id="per_tool_select_<%= tool.clean %>" class="btn btn-primary select-tps-button" data-toolguid="<%= tool.guid %>" value="Select existing" id="select_existing_<%= tool.clean %>" type="button">',
"</div>"
].join("")
),
templateToolSectionCreate: function() {
return _.template(
`<div id="new_tps_<%= tool.clean %>" data-clean="<%= tool.clean %>" class="form-row">
<input data-toolguid="<%= tool.guid %>" class="tool_panel_section_picker" size="40" name="new_tool_panel_section" id="new_tool_panel_section_<%= tool.clean %>" type="text">
<input id="per_tool_select_<%= tool.clean %>" class="btn btn-primary select-tps-button" data-toolguid="<%= tool.guid %>" value="Select existing" id="select_existing_<%= tool.clean %>" type="button">
</div>`
);
},
templateToolSectionSelect: _.template(
[
'<div id="select_tps_<%= tool.clean %>" data-clean="<%= tool.clean %>" class="tps_creator">',
'<select default="active" style="width: 30em;" data-toolguid="<%= tool.guid %>" class="tool_panel_section_picker" name="tool_panel_section_id" id="tool_panel_section_select_<%= tool.clean %>">',
"<%= panel_section_options({sections: panel_section_dict.sections}) %>",
"</select>",
'<input id="per_tool_create_<%= tool.clean %>" data-clean="<%= tool.clean %>" class="btn btn-primary create-tps-button" data-toolguid="<%= tool.guid %>" value="Create new" id="create_new_<%= tool.clean %>" type="button">',
'<div style="clear: both;" class="toolParamHelp"></div>',
"</div>"
].join("")
),
templateToolSectionSelect: function() {
return _.template(
`<div id="select_tps_<%= tool.clean %>" data-clean="<%= tool.clean %>" class="tps_creator">
<select default="active" style="width: 30em;" data-toolguid="<%= tool.guid %>" class="tool_panel_section_picker" name="tool_panel_section_id" id="tool_panel_section_select_<%= tool.clean %>">
<%= panel_section_options({sections: panel_section_dict.sections}) %>
</select>
<input id="per_tool_create_<%= tool.clean %>" data-clean="<%= tool.clean %>" class="btn btn-primary create-tps-button" data-toolguid="<%= tool.guid %>" value="Create new" id="create_new_<%= tool.clean %>" type="button">
<div style="clear: both;" class="toolParamHelp"></div>
</div>`
);
},
templatePanelSelectOptions: _.template(
[
"<% _.each(sections, function(section) { %>",
'<option value="<%= section.id %>"><%= section.name %></option>',
"<% }); %>"
].join("")
)
templatePanelSelectOptions: function() {
return _.template(
`<% _.each(sections, function(section) { %>
<option value="<%= section.id %>"><%= section.name %></option>
<% }); %>`
);
}
});
export default {
@@ -1,19 +1,11 @@
import Backbone from "backbone";
import $ from "jquery";
import _ from "underscore";
import _l from "utils/localization";
import toolshed_model from "mvc/toolshed/toolshed-model";
import toolshed_util from "mvc/toolshed/util";
var View = Backbone.View.extend({
defaults: {
tool_sheds: [
{
url: "https://toolshed.g2.bx.psu.edu/",
name: "Galaxy Main Tool Shed"
}
]
},
var ShedListView = Backbone.View.extend({
initialize: function(options) {
this.options = _.defaults(this.options || {}, this.defaults);
this.model = new toolshed_model.ShedsCollection();
@@ -25,7 +17,7 @@ var View = Backbone.View.extend({
render: function(options) {
this.options = _.defaults(this.options || {}, options, this.defaults);
var toolshed_list_template = this.templateToolshedList;
var toolshed_list_template = this.templateToolshedList();
this.$el.html(
toolshed_list_template({
title: _l("Configured Galaxy Tool Sheds"),
@@ -33,33 +25,29 @@ var View = Backbone.View.extend({
queue: toolshed_util.queueLength()
})
);
$("#center").css("overflow", "auto");
},
templateToolshedList: _.template(
[
'<div class="unified-panel-header" id="panel_header" unselectable="on">',
'<div class="unified-panel-header-inner"><%= title %><a class="ml-auto" href="#/queue">Repository Queue (<%= queue %>)</a></div>',
"</div>",
'<div class="unified-panel-body" id="list_toolsheds">',
'<div class="form-row">',
'<table class="grid">',
"<% _.each(tool_sheds, function(shed) { %>",
'<tr class="libraryTitle">',
"<td>",
'<div style="float: left; margin-left: 1px;" class="menubutton split">',
'<a class="view-info shed-selector" href="#/categories/s/<%= shed.get("url") %>"><%= shed.get("name") %></a>',
"</div>",
"</td>",
"</tr>",
"<% }); %>",
"</table>",
"</div>",
'<div style="clear: both"></div>',
"</div>"
].join("")
)
templateToolshedList: function() {
return _.template(
`<div class='shed-style-container'>
<div class='header'>
<h2>
${_l("Configured Tool Sheds")}
</h2>
<span><a href='#/queue'>Repository Queue (<%= queue %>)</a></span>
<div style='clear:both;'></div>
</div'>
<% _.each(tool_sheds, function(shed) { %>
<div>
<a href='#/categories/s/<%= shed.get('url') %>'><%= shed.get('name') %></a>
</div>
<% }); %>
</div>`
);
}
});
export default {
ShedListView: View
ShedListView: ShedListView
};
@@ -19,7 +19,7 @@ var View = Backbone.View.extend({
},
render: function(options) {
var workflows_missing_tools = this.templateWorkflows;
var workflows_missing_tools = this.templateWorkflows();
var workflows = this.model.models;
this.$el.html(
workflows_missing_tools({
@@ -75,57 +75,57 @@ var View = Backbone.View.extend({
$("#from_workflow").on("click", this.loadWorkflows);
},
templateWorkflows: _.template(
[
'<div class="unified-panel-header" id="panel_header" unselectable="on">',
'<div class="unified-panel-header-inner"><%= title %><a class="ml-auto" href="#/queue">Repository Queue (<%= queue %>)</a></div>',
"</div>",
'<style type="text/css">',
".workflow_names, .workflow_tools { list-style-type: none; } ul.workflow_tools, ul.workflow_names { padding-left: 0px; }",
"</style>",
'<table id="workflows_missing_tools" class="grid" border="0" cellpadding="2" cellspacing="2" width="100%">',
'<thead id="grid-table-header">',
"<tr>",
'<th class="datasetRow">Workflows</th>',
'<th class="datasetRow">Tool IDs</th>',
'<th class="datasetRow">Shed</th>',
'<th class="datasetRow">Name</th>',
'<th class="datasetRow">Owner</th>',
'<th class="datasetRow">Actions</th>',
"</tr>",
"</thead>",
"<tbody>",
"<% _.each(workflows, function(workflow) { %>",
"<tr>",
'<td class="datasetRow">',
'<ul class="workflow_names">',
'<% _.each(workflow.get("workflows"), function(name) { %>',
'<li class="workflow_names"><%= name %></li>',
"<% }); %>",
"</ul>",
"</td>",
'<td class="datasetRow">',
'<ul class="workflow_tools">',
'<% _.each(workflow.get("tools"), function(tool) { %>',
'<li class="workflow_tools"><%= tool %></li>',
"<% }); %>",
"</ul>",
"</td>",
'<td class="datasetRow"><%= workflow.get("shed") %></td>',
'<td class="datasetRow"><%= workflow.get("repository") %></td>',
'<td class="datasetRow"><%= workflow.get("owner") %></td>',
'<td class="datasetRow">',
'<ul class="workflow_tools">',
'<li class="workflow_tools">',
'<input type="button" class="show_wf_repo btn btn-primary" data-shed="<%= workflow.get("shed") %>" data-owner="<%= workflow.get("owner") %>" data-repo="<%= workflow.get("repository") %>" data-toolids="<%= workflow.get("tools").join(",") %>" value="Show Repository" /></li>',
"</ul>",
"</td>",
"</tr>",
"<% }); %>",
"</ul>",
"</div>"
].join("")
)
templateWorkflows: function() {
_.template(
`<div class="unified-panel-header" id="panel_header" unselectable="on">
<div class="unified-panel-header-inner"><%= title %><a class="ml-auto" href="#/queue">Repository Queue (<%= queue %>)</a></div>
</div>
<style type="text/css">
.workflow_names, .workflow_tools { list-style-type: none; } ul.workflow_tools, ul.workflow_names { padding-left: 0px; }
</style>
<table id="workflows_missing_tools" class="grid" border="0" cellpadding="2" cellspacing="2" width="100%">
<thead id="grid-table-header">
<tr>
<th class="datasetRow">Workflows</th>
<th class="datasetRow">Tool IDs</th>
<th class="datasetRow">Shed</th>
<th class="datasetRow">Name</th>
<th class="datasetRow">Owner</th>
<th class="datasetRow">Actions</th>
</tr>
</thead>
<tbody>
<% _.each(workflows, function(workflow) { %>
<tr>
<td class="datasetRow">
<ul class="workflow_names">
<% _.each(workflow.get("workflows"), function(name) { %>
<li class="workflow_names"><%= name %></li>
<% }); %>
</ul>
</td>
<td class="datasetRow">
<ul class="workflow_tools">
<% _.each(workflow.get("tools"), function(tool) { %>
<li class="workflow_tools"><%= tool %></li>
<% }); %>
</ul>
</td>
<td class="datasetRow"><%= workflow.get("shed") %></td>
<td class="datasetRow"><%= workflow.get("repository") %></td>
<td class="datasetRow"><%= workflow.get("owner") %></td>
<td class="datasetRow">
<ul class="workflow_tools">
<li class="workflow_tools">
<input type="button" class="show_wf_repo btn btn-primary" data-shed="<%= workflow.get("shed") %>" data-owner="<%= workflow.get("owner") %>" data-repo="<%= workflow.get("repository") %>" data-toolids="<%= workflow.get("tools").join(",") %>" value="Show Repository" /></li>
</ul>
</td>
</tr>
<% }); %>
</ul>
</div>`
);
}
});
export default {
@@ -5,7 +5,7 @@ import Backbone from "backbone";
// TODO; tie into Galaxy state?
window.workflow_globals = window.workflow_globals || {};
var DataInputView = Backbone.View.extend({
const DataInputView = Backbone.View.extend({
className: "form-row dataRow input-data-row",
initialize: function(options) {
@@ -35,7 +35,7 @@ var DataInputView = Backbone.View.extend({
}
});
var DataOutputView = Backbone.View.extend({
const DataOutputView = Backbone.View.extend({
className: "form-row dataRow",
initialize: function(options) {
@@ -43,18 +43,18 @@ var DataOutputView = Backbone.View.extend({
this.terminalElement = options.terminalElement;
this.nodeView = options.nodeView;
var output = this.output;
var label = output.label || output.name;
var node = this.nodeView.node;
const output = this.output;
let label = output.label || output.name;
const node = this.nodeView.node;
var isInput = output.extensions.indexOf("input") >= 0 || output.extensions.indexOf("input_collection") >= 0;
const isInput = output.extensions.indexOf("input") >= 0 || output.extensions.indexOf("input_collection") >= 0;
if (!isInput) {
label = `${label} (${output.force_datatype || output.extensions.join(", ")})`;
}
this.$el.html(label);
this.calloutView = null;
if (["tool", "subworkflow"].indexOf(node.type) >= 0) {
var calloutView = new OutputCalloutView({
const calloutView = new OutputCalloutView({
label: label,
output: output,
node: node
@@ -86,7 +86,7 @@ var DataOutputView = Backbone.View.extend({
}
});
var ParameterOutputView = Backbone.View.extend({
const ParameterOutputView = Backbone.View.extend({
className: "form-row dataRow",
initialize: function(options) {
@@ -94,28 +94,20 @@ var ParameterOutputView = Backbone.View.extend({
this.terminalElement = options.terminalElement;
this.nodeView = options.nodeView;
var output = this.output;
var label = output.label || output.name;
var node = this.nodeView.node;
const output = this.output;
const label = output.label || output.name;
const node = this.nodeView.node;
this.$el.html(label);
this.calloutView = null;
if (["tool", "subworkflow"].indexOf(node.type) >= 0) {
var calloutView = new OutputCalloutView({
const calloutView = new OutputCalloutView({
label: label,
output: output,
node: node
});
this.calloutView = calloutView;
this.$el.append(calloutView.el);
this.$el.hover(
() => {
calloutView.hoverImage();
},
() => {
calloutView.resetImage();
}
);
}
this.$el.css({
position: "absolute",
@@ -141,21 +133,21 @@ var ParameterOutputView = Backbone.View.extend({
}
});
var OutputCalloutView = Backbone.View.extend({
const OutputCalloutView = Backbone.View.extend({
tagName: "div",
initialize: function(options) {
this.label = options.label;
this.node = options.node;
this.output = options.output;
var view = this;
var node = this.node;
const view = this;
const node = this.node;
this.$el
.attr("class", `callout-terminal ${this.label}`)
.css({ display: "none" })
.append(
$("<icon class='mark-terminal fa fa-asterisk'/>").click(() => {
var outputName = view.output.name;
const outputName = view.output.name;
if (node.isWorkflowOutput(outputName)) {
node.removeWorkflowOutput(outputName);
view.$("icon").removeClass("mark-terminal-active");
+2 -2
View File
@@ -306,9 +306,9 @@ define({
// ---------------------------------------------------------------------------- history-list
Histories: false,
// ---------------------------------------------------------------------------- shed-list-view
"Configured Galaxy Tool Sheds": false,
"Configured Tool Sheds": false,
// ---------------------------------------------------------------------------- repository-queue-view
"Repository Installation Queue": false,
"Repository Queue": false,
// ---------------------------------------------------------------------------- repo-status-view
"Repository Status": false,
// ---------------------------------------------------------------------------- workflows-view
+2 -2
View File
@@ -306,9 +306,9 @@ define({
// ---------------------------------------------------------------------------- history-list
Histories: false,
// ---------------------------------------------------------------------------- shed-list-view
"Configured Galaxy Tool Sheds": false,
"Configured Tool Sheds": false,
// ---------------------------------------------------------------------------- repository-queue-view
"Repository Installation Queue": false,
"Repository Queue": false,
// ---------------------------------------------------------------------------- repo-status-view
"Repository Status": false,
// ---------------------------------------------------------------------------- workflows-view
+6 -1
View File
@@ -4,14 +4,19 @@
import Vue from "vue";
import Vuex from "vuex";
import createCache from "vuex-cache";
import { gridSearchStore } from "./gridSearchStore";
import { tagStore } from "./tagStore";
import { jobMetricsStore } from "./jobMetricsStore";
Vue.use(Vuex);
export default new Vuex.Store({
plugins: [createCache()],
modules: {
gridSearch: gridSearchStore,
tags: tagStore
tags: tagStore,
jobMetrics: jobMetricsStore
}
});
@@ -0,0 +1,47 @@
export const state = {
jobMetricsByHdaId: {},
jobMetricsByLddaId: {},
jobMetricsByJobId: {}
};
import Vue from "vue";
import { getAppRoot } from "onload/loadConfig";
import axios from "axios";
const getters = {
getJobMetricsByDatasetId: state => (datasetId, datasetType = "hda") => {
const jobMetricsObject = datasetType == "hda" ? state.jobMetricsByHdaId : state.jobMetricsByLddaId;
return jobMetricsObject[datasetId] || [];
},
getJobMetricsByJobId: state => jobId => {
return state.jobMetricsByJobId[jobId] || [];
}
};
const actions = {
fetchJobMetricsForDatasetId: async ({ commit }, { datasetId, datasetType }) => {
const { data } = await axios.get(`${getAppRoot()}api/datasets/${datasetId}/metrics?hda_ldda=${datasetType}`);
commit("saveJobMetricsForDatasetId", { datasetId, datasetType, jobMetrics: data });
},
fetchJobMetricsForJobId: async ({ commit }, jobId) => {
const { data } = await axios.get(`${getAppRoot()}api/jobs/${jobId}/metrics`);
commit("saveJobMetricsForJobId", { jobId, jobMetrics: data });
}
};
const mutations = {
saveJobMetricsForDatasetId: (state, { datasetId, datasetType, jobMetrics }) => {
const jobMetricsObject = datasetType == "hda" ? state.jobMetricsByHdaId : state.jobMetricsByLddaId;
Vue.set(jobMetricsObject, datasetId, jobMetrics);
},
saveJobMetricsForJobId: (state, { jobId, jobMetrics }) => {
Vue.set(state.jobMetricsByJobId, jobId, jobMetrics);
}
};
export const jobMetricsStore = {
state,
getters,
actions,
mutations
};
+1
View File
@@ -36,6 +36,7 @@ $fa-font-path: "../../../node_modules/font-awesome/fonts/";
@import "flex.scss";
@import "charts.scss";
@import "message.scss";
@import "toolshed.scss";
// Mixins
@mixin user-select($select) {
+21
View File
@@ -0,0 +1,21 @@
@import "theme/blue.scss";
.shed-style-container {
width: 95%;
margin: auto;
margin-top: 1em;
overflow: auto !important;
.header {
h2 {
float: left;
}
span {
float: right;
}
}
}
.ui-autocomplete {
background-color: #fff;
li.ui-menu-item {
list-style-type: none;
}
}
+3 -2
View File
@@ -15,7 +15,7 @@
"@handsontable/vue": "^2.0.0-beta1",
"@johmun/vue-tags-input": "^2.0.1",
"@vue/test-utils": "1.0.0-beta.29",
"axios": "^0.18.0",
"axios": "^0.19.0",
"backbone": "1.4.0",
"bibtex-parse-js": "^0.0.24",
"bootstrap": "4.3.1",
@@ -47,7 +47,8 @@
"vue": "^2.6.10",
"vue-router": "^3.0.2",
"vue-rx": "^6.1.0",
"vuex": "^3.1.0"
"vuex": "^3.1.0",
"vuex-cache": "^3.1.0"
},
"scripts": {
"watch": "gulp && yarn run save-build-hash && yarn run webpack-watch",
+20 -8
View File
@@ -1717,13 +1717,13 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==
axios@^0.18.0:
version "0.18.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102"
integrity sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=
axios@^0.19.0:
version "0.19.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8"
integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==
dependencies:
follow-redirects "^1.3.0"
is-buffer "^1.1.5"
follow-redirects "1.5.10"
is-buffer "^2.0.2"
babel-code-frame@^6.26.0, babel-code-frame@^6.7.5:
version "6.26.0"
@@ -5556,7 +5556,14 @@ fn-name@^2.0.0:
resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7"
integrity sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=
follow-redirects@^1.0.0, follow-redirects@^1.3.0:
follow-redirects@1.5.10:
version "1.5.10"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
dependencies:
debug "=3.1.0"
follow-redirects@^1.0.0:
version "1.5.9"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.9.tgz#c9ed9d748b814a39535716e531b9196a845d89c6"
integrity sha512-Bh65EZI/RU8nx0wbYF9shkFZlqLP+6WT/5FnA3cE/djNSuKNHJEinGGZgu/cQEkeeb2GdFOgenAmn8qaqYke2w==
@@ -6753,7 +6760,7 @@ is-buffer@^1.1.5:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-buffer@^2.0.0:
is-buffer@^2.0.0, is-buffer@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
@@ -13067,6 +13074,11 @@ vue@^2.6.10, vue@^2.6.9:
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"
integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==
vuex-cache@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/vuex-cache/-/vuex-cache-3.1.0.tgz#aad576cfb39b325cc7a43ea9a42414e356374c4b"
integrity sha512-XDzQ/jddmErZVquyHhbOHc6DPhVSt5bU8433Fzsai3XydU3cxyYTUd3PH2Ww5sesB9yu5f0wKk6MFIqgjSa3Yw==
vuex@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.1.0.tgz#634b81515cf0cfe976bd1ffe9601755e51f843b9"
+2 -2
View File
@@ -950,12 +950,12 @@
<param id="docker_image_default">my-tool</param>
<param id="docker_tag_default">latest</param>
-->
<param id="max_pod_retrials">3</param>
<param id="max_pod_retries">3</param>
<!-- Allows pods to retry up to this number of times, before marking the galaxy job failed. k8s is a state
setter essentially, so by default it will try to take a job submitted to successful completion. A job
submits pods, until the number of successes (1 in this use case) is achieved, assuming that whatever is
making the pods fail will be fixed (such as a stale disk or a dead node that it is being restarted).
This option sets a limit of retrials, so that after that number of failed pods, the job is re-scaled to
This option sets a limit of retries, so that after that number of failed pods, the job is re-scaled to
zero (no execution) and the stderr/stdout of the k8s job is reported in galaxy (and the galaxy job set
to failed).
+3
View File
@@ -144,6 +144,9 @@ tool_shed:
# For searching repositories at /api/repositories:
#repo_owner_username_boost: 0.3
# For searching repositories at /api/repositories:
#categories_boost: 0.5
# For searching tools at /api/tools
#tool_name_boost: 1.2
@@ -4,10 +4,10 @@ Containers for Tool Dependencies
Galaxy tools (also called wrappers) are able to use Conda packages
(see more information in our `Galaxy Conda documentation`_) and Docker containers as dependency resolvers.
The IUC_ recommends to use Conda packages as primary dependency resolver, mainly because Docker is not
The IUC_ recommends to use Conda packages as the primary dependency resolver, mainly because Docker is not
available on every (HPC-) system. Conda on the other hand can be installed by Galaxy and maintained
entirely in user-space. Nevertheless, Docker (Containers in general) has some unique features and
there are many use-cases in the Galaxy community which makes containerized systems very appealing.
entirely in user-space. Nevertheless, Docker and containers in general have some unique features and
there are many use-cases in the Galaxy community that make containerized tools very appealing.
Since 2014 Galaxy supports running tools in Docker containers via a special `container annotation`_ inside of the
requirement field.
@@ -41,17 +41,16 @@ is not available already.
Automatic build of Linux containers
-----------------------------------
We utilize [mulled](https://github.com/mulled/mulled) with [involucro](https://github.com/involucro/involucro)
in an automatic way. This is for example used to convert all packages in bioconda_ into Linux Containers
(Docker and rkt at the moment) and made available at the `BioContainers Quay.io account`_.
We utilize mulled_ with involucro_ to automatically convert all packages in Bioconda_ into Linux containers images
(Docker and rkt at the moment) and make them available at the `BioContainers Quay.io account`_.
We have developed small utilities around this technology stack which is currently included in galaxy-lib_.
We have developed small utilities around this technology stack, which is currently included in galaxy-lib_.
Here is a short introduction:
Search for containers
^^^^^^^^^^^^^^^^^^^^^
This will search for containers in the biocontainers organisation.
This will search for containers in the biocontainers organization.
.. code-block:: bash
@@ -72,40 +71,40 @@ The BioConda community is building a container for every package they create wit
Building Docker containers for local Conda packages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Conda packages can be tested with creating a busybox based container for this particular package in the following way.
Conda packages can be tested with creating a *busybox* based container for this particular package in the following way.
This also demonstrates how you can build a container locally and on-the-fly.
> we modified the samtools package to version 3.0 to make clear we are using a local version
> we modified the ``samtools`` package to version 3.0 to make it clear we are using a local version
1) build your recipe
1) Build your recipe
.. code-block:: bash
$ conda build recipes/samtools
2) index your local builds
2) Index your local builds
.. code-block:: bash
$ conda index /home/bag/miniconda2/conda-bld/linux-64/
3) build a container for your local package
3) Build a container for your local package
.. code-block:: bash
$ mulled-build build-and-test 'samtools=3.0--0' \
--extra-channel file://home/bag/miniconda2/conda-bld/ --test 'samtools --help'
The ``--0`` indicates the build version of the conda package. It is recommended to specify this number otherwise
The ``--0`` indicates the build version of the conda package. It is recommended to specify this number, otherwise
you will override already existing images. For Python Conda packages this extension might look like this ``--py35_1``.
Build, test and push a conda-forge package to biocontainers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Build, test, and push a conda-forge package to biocontainers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> You need to have write access to the biocontainers repository
You can build packages from other Conda channels as well, not only from BioConda. ``pandoc`` is available from the
You can build packages from other Conda channels as well, not only from BioConda. ``pandoc`` tool is available from the
conda-forge channel and conda-forge is also enabled by default in Galaxy. To build ``pandoc`` and push it to biocontainrs
you could do something along these lines.
@@ -123,6 +122,8 @@ you could do something along these lines.
.. _IUC: https://galaxyproject.org/iuc/
.. _container annotation: https://github.com/galaxyproject/galaxy/blob/dev/test/functional/tools/catDocker.xml#L4
.. _BioContainers: https://github.com/biocontainers
.. _bioconda: https://github.com/bioconda/bioconda-recipes
.. _mulled: https://github.com/mulled/mulled
.. _involucro: https://github.com/involucro/involucro
.. _Bioconda: https://bioconda.github.io/
.. _BioContainers Quay.io account: https://quay.io/organization/biocontainers
.. _galaxy-lib: https://github.com/galaxyproject/galaxy-lib
+2 -2
View File
@@ -41,13 +41,13 @@ There's a new discussion forum to replace Biostars. It is accessible under the '
:alt: Galaxy's new help forum which replaces biostars
New Visualisations
New Visualizations
===========================================================
`Aequatus visualisation plugin <https://docs.google.com/presentation/d/1_KdwjbIyjUhdb_huAzOuI34693mciw_vXDCGLctKs9A/edit#slide=id.p2>`__ has been released which allows visualisation of gene alignments and gene family aggregations.
.. figure:: https://lh3.googleusercontent.com/wgNqZT2idSR4AkvUZ55ZQGXOfOPlAxFimO9795WvrQwP1ZMxxdYwNmRZErf-n5hZMGa1SulFry321vgHPoc11wsmJlmVPrmyxG8buV6P=s1600
:alt: The Aequatus visualisation allows analysing gene family alignments
:alt: The Aequatus visualization allows analyzing gene family alignments
New Datatypes
===========================================================
+721
View File
@@ -0,0 +1,721 @@
.. to_doc
19.05
===============================
.. announce_start
Enhancements
-------------------------------
* Implement the ability to favorite tools.
`Pull Request 7209`_
* Add data dialog option to tool form data selector.
`Pull Request 7553`_, `Pull Request 7460`_
* Many workflow editor connection fixes and enhancements making
them more correct, accessible, and transparent
(with huge thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7466`_, `Pull Request 7435`_, `Pull Request 7972`_,
`Pull Request 7979`_, `Pull Request 7642`_, `Pull Request 7989`_,
`Pull Request 7254`_
* Add a Galaxy IE for cellxgene.
`Pull Request 7268`_
* Implement expression tools and non-data tool outputs
(with thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7556`_, `Pull Request 7796`_, `Pull Request 7797`_,
`Pull Request 7944`_
* Add Galaxy cloud runner support
(thanks to `@nuwang <https://github.com/nuwang>`__).
`Pull Request 7226`_
* More robust task messaging
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7548`_
* Allow implicit conversion for input collection parameters
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7683`_
* Allow import of "Format 2" workflows by default.
`Pull Request 7659`_
* Decompose Galaxy into Python libraries in-tree.
`Pull Request 7524`_
* Rewrite and generalize History import and export - dozens of fixes, support for collections,
Python library support, etc..
`Pull Request 7367`_, `Pull Request 7214`_, `Pull Request 7366`_,
`Pull Request 7369`_, `Pull Request 7370`_, `Pull Request 7358`_,
`Pull Request 7505`_, `Pull Request 7507`_, `Pull Request 7363`_,
`Pull Request 7193`_, `Pull Request 7192`_, `Pull Request 7537`_,
`Pull Request 7540`_, `Pull Request 7684`_, `Pull Request 7704`_
* User facing release notes
(thanks to `@erasche <https://github.com/erasche>`__).
`Pull Request 7527`_
* Implement dataset source and hash tracking.
`Pull Request 7487`_, `Pull Request 4659`_, `Pull Request 7549`_
* Custos integration for AuthNZ
(thanks to `@machristie <https://github.com/machristie>`__).
`Pull Request 7195`_
* Flush out API support for AuthNZ and CloudAuthz
`Pull Request 7598`_, `Pull Request 7609`_,
`Pull Request 7592`_, `Pull Request 7597`_,
`Pull Request 7639`_
* Update to PSA 3.1 and support login with Globus identity.
`Pull Request 7463`_
* Swap from 'slug.js' to 'slugify.js' - saving 10 MB in client bundles.
`Pull Request 7538`_
* Update all client dependencies - including to Backbone 1.4, Bootstrap 4.2, Vue 2.6.
`Pull Request 7544`_, `Pull Request 7637`_
* Allow admins to import dynamic JSON-based tools.
`Pull Request 7545`_
* Implement environment modules mapping files
(thanks to `@FredericBGA <https://github.com/FredericBGA>`__).
`Pull Request 7398`_
* Allow tool testing of multiple files within a zip output
(thanks to `@thermokarst <https://github.com/thermokarst>`__).
`Pull Request 7400`_
* Add datatype converters between tabular and CSV.
`Pull Request 7246`_
* Add Azure and GCP support for ObjectStore Cloud backend.
`Pull Request 7272`_
* Add a validator that ensure metadata value is on a range.
(thanks to `@fmareuil <https://github.com/fmareuil>`__).
`Pull Request 7288`_
* Fix post job actions for "Database Operation" tools, implement ``change_datatype``
for collection output
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7480`_
* Implement and enforce ESLint linting of the entire client code base.
`Pull Request 7202`_, `Pull Request 7860`_
* Multiple enhancements to the LSF cli-plugin job runner - support
out of memory handling, project specification, and Spectrum LSF.
(thanks to `@pcm32 <https://github.com/pcm32>`__ and
`@selten <https://github.com/selten>`__).
`Pull Request 6866`_, `Pull Request 7581`_, `Pull Request 7486`_
* Drop support for Python 3.4 and officially support Python 3.5 or greater.
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7291`_
* Batch bulk hide and delete operations when multiple selected.
`Pull Request 5495`_
* Implement client initialization pipeline.
`Pull Request 7117`_
* Allow storing objects in the object store by UUID.
`Pull Request 7154`_, `Pull Request 7650`_
* Replace login and registration mako templates with VueJS components.
`Pull Request 6621`_, `Pull Request 7047`_, `Pull Request 7329`_,
`Pull Request 7442`_, `Pull Request 7756`_, `Pull Request 7347`_
* Track messages generated tool stdio tags in the database instead of just appending them
to tool standard error. Structured UI in reporting also.
(with help from `@bernt-matthias <https://github.com/bernt-matthias>`__)
`Pull Request 7095`_
* Track job script stdout and stderr separately from the tool's stdout and stderr in the database.
`Pull Request 7095`_
* Support loading/using tools that are not in the install database
(with help from `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7316`_, `Pull Request 8021`_
* Git providers error reporting plugins
(thanks to `@selten <https://github.com/selten>`__).
`Pull Request 7485`_
* Rename ``_future_expose_api`` to ``expose_api`` and ``expose_api`` to ``legacy_expose_api``
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7743`_
* Add ``mtx`` datatype
(thanks to `@bebatut <https://github.com/bebatut>`__ and
`@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7569`_, `Pull Request 7702`_, `Pull Request 7717`_
* Add ``geojson`` datatype
(thanks to `@bgruening <https://github.com/bgruening>`__).
`Pull Request 7773`_
* Add shapefile (``shp``) datatype
(thanks to `@bgruening <https://github.com/bgruening>`__).
`Pull Request 7819`_
* Add ``imgt.json`` datatype for IMGT immune system libraries
(thanks to `@jj-umn <https://github.com/jj-umn>`__).
`Pull Request 7587`_
* Add microarrays data types ``gpr`` and ``gal``
(thanks to `@bensellak <https://github.com/bensellak>`__).
`Pull Request 7457`_
* Add ``spaln`` database type
(thanks to `@pvanheus <https://github.com/pvanheus>`__).
`Pull Request 7718`_
* Redefine ``cel`` datatype
(thanks to `@bensellak <https://github.com/bensellak>`__).
`Pull Request 7514`_
* Run most tests formerly ran on Travis on CircleCI
(with help from `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7424`_, `Pull Request 7573`_, `Pull Request 7451`_,
`Pull Request 7207`_, `Pull Request 7539`_, `Pull Request 7574`_
* Toolshed API enhancements.
`Pull Request 6652`_
* Kubernetes job runner integration test and enhancements
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 6958`_
* Implement sniffing of datatypes for library datasets.
`Pull Request 7379`_
* Rewrite tool output metadata collection - now portable and more correct, tested,
and documented.
`Pull Request 7470`_, `Pull Request 7459`_, `Pull Request 7156`_
`Pull Request 7483`_, `Pull Request 7158`_, `Pull Request 7213`_,
`Pull Request 7694`_, `Pull Request 7596`_, `Pull Request 7186`_,
`Pull Request 7471`_
* Add ``python`` to ``Count1`` tool requirements
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7185`_
* Fixes and enhancements for the grouping1 tool - including not removing empty cells
at the begin/start of lines
(thanks to `@bernt-matthias <https://github.com/bernt-matthias>`__ and
`@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7205`_, `Pull Request 7844`_
* Workflow editor accessibility fixes.
`Pull Request 7750`_
* Python dependency updates and documentation fixes
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7215`_, `Pull Request 7247`_, `Pull Request 7285`_,
`Pull Request 7740`_
* Remove requirement pin on specific Sphinx version
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7365`_
* Drop conditional pygmentz requirement (autoinstalled as necessary), minor
formatting in conditional-reqs
`Pull Request 7219`_
* Fix spacing between checkbox and buttons in history sharing view.
`Pull Request 7222`_
* Use regular font-size and styling in uploader.
`Pull Request 7232`_
* Remove underline from history datasets.
`Pull Request 7235`_
* Add headless testing option for Selenium tests.
`Pull Request 7287`_
* Build tool XML schema docs using ``sphinx_markdown_tables``
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7313`_
* Refactor dataset controller to reuse input validation checks between get/set.
`Pull Request 7322`_
* Add web server documentation notes about ``Range`` support
(thanks to `@pvanheus <https://github.com/pvanheus>`__ and
`@nsoranzo <https://github.com/nsoranzo>`_).
`Pull Request 7323`_, `Pull Request 7334`_
* Fall back to binary comparison if BAM conversion fails during tool tests
(thanks to `@bernt-matthias <https://github.com/bernt-matthias>`__).
`Pull Request 7342`_
* Update ``area`` issue/PR labels
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7344`_
* Remove deprecated ``collect_outputs_from`` configuration option.
`Pull Request 7144`_
* Remove ``ToolsController._rerun_tool()`` API method
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7345`_
* Refactor ``item_attrs.py`` for reuse without mixin inheritance.
`Pull Request 7346`_
* Add ``--force_path_paste`` argument to tool test verify script.
`Pull Request 7356`_
* Separate client node version requirement into individual dotfile for reuse.
`Pull Request 7357`_
* Improve tool testing for counting datasets in paired collections
(thanks to `@bernt-matthias <https://github.com/bernt-matthias>`__).
`Pull Request 7359`_
* Do not default to ``DEV_WHEELS=1`` if no ``git`` is found
(thanks to `@ic4f <https://github.com/ic4f>`__).
`Pull Request 7371`_
* Restore gray scale difference between panel vs portlet background color for
contrast.
`Pull Request 7387`_
* Specify exceptions more precisely in user API controller.
`Pull Request 7397`_
* Automatically set ``cookie_path`` using ``url_for()``.
`Pull Request 7404`_
* Allow configuration location of user preferences extra configuration
(thanks to `@erasche <https://github.com/erasche>`__).
`Pull Request 7428`_
* Add hover styling to target tool in tool panel
(thanks to `@erasche <https://github.com/erasche>`__).
`Pull Request 7437`_
* Update Docker testing image
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7439`_, `Pull Request 7187`_
* Remove unused code
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7445`_
* Note `cannot import name _remove_dead_weakref` error and solution
(thanks to `@pvanheus <https://github.com/pvanheus>`__).
`Pull Request 7461`_
* Add option to pass in individual globs to client unit test watcher
`Pull Request 7477`_
* Update of tours overview according to `#5860
<https://github.com/galaxyproject/galaxy/issues/5860>`__
(thanks to `@selten <https://github.com/selten>`__).
`Pull Request 7478`_
* Add new metadata and data table tool validators
(thanks to `@bernt-matthias <https://github.com/bernt-matthias>`__).
`Pull Request 7500`_
* Updated documentation in ``admin/scaling.md`` for Systemd
(thanks to `@ooobik <https://github.com/ooobik>`__).
`Pull Request 7515`_
* Replace backbone tagging views with VueJs components.
`Pull Request 7516`_
* Eliminate import dependency of datatypes on galaxy.web (``url_for``).
`Pull Request 7521`_
* Static plugin staging as a part of client build instead of startup.
`Pull Request 7532`_
* Implement dockerized variant of ``update.sh`` for project Python dependencies.
`Pull Request 7546`_
* Refactor XSD output elements to share common output attributes.
`Pull Request 7555`_
* Improve linking between job conf handler assignment and documentation
(thanks to `@erasche <https://github.com/erasche>`__).
`Pull Request 7558`_
* Refactor ``galaxy.web.security`` into ``galaxy.security.idencoding``.
`Pull Request 7560`_
* Move the 'create new history' out of the history context menu
`Pull Request 7565`_, `Pull Request 7606`_
* Improve workflow cog menu user interface.
`Pull Request 7594`_, `Pull Request 7858`_
* Make ``galaxy.model.dataset_collections`` more usable outside manager context.
`Pull Request 7595`_
* Webpack bundle overhaul and initial dynamic loading.
`Pull Request 7605`_
* Don't un-hide mapped-over outputs when job fails
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7630`_
* Continue gracefully in set_meta if unable to count number of dataset lines.
`Pull Request 7641`_
* Implement functional dict-ifiable tool outputs and error detection.
`Pull Request 7651`_
* Refactor ``IntegrationTestCase`` to allow integration test functions.
`Pull Request 7657`_
* Drop .pyc files before attempting to migrate
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7677`_
* Add docs to OIDC backends configuration file.
`Pull Request 7691`_
* Update ``CITATION`` to latest Galaxy update paper
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7698`_
* Update pull request procedures to exempt notes, changelogs, and
packages from mandatory review.
`Pull Request 7706`_
* Update procedures to relax the vote requirement for fixing bugs in releases
`Pull Request 7707`_
* Improve error message if GFF file is missing attribute col
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7708`_
* Add hostname to task message queues
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7712`_
* OIDC login buttons based on configuration
(thanks to `@machristie <https://github.com/machristie>`__).
`Pull Request 7720`_
* Enable the selection of library datasets in the tool form
`Pull Request 7746`_
* Replace ``enable_beta_export_format2_default`` with
``default_workflow_export_format``
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7748`_
* Report a couple common errors in dataset/job report.
`Pull Request 7755`_
* Add singularity to valid types, allow customization of test history name
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7760`_
* Update parameter_input type when changing parameter type
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7780`_
* Don't clean up jobs when running tests if `$GALAXY_TEST_NO_CLEANUP` is set
`Pull Request 7798`_
* Add option to wait for the database to become available
(thanks to `@ic4f <https://github.com/ic4f>`__).
`Pull Request 7827`_
* Remove recursion from ``expand_nested_tokens()``
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7834`_
* Allow composite upload if all non-optional files are selected
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7872`_
* Cleanup integration test configuration code.
`Pull Request 7874`_
* Add "Reset" button to composite upload interface
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7875`_
* Add local namespaced resolver to default container resolvers
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7896`_
* Use node-watch instead of fs.watch to watch for db changes
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7967`_
* Remove reset handler from ruler input element.
`Pull Request 6321`_
* Declutter the history 'cog' menu.
`Pull Request 6437`_
* Remove deprecated OpenID features.
`Pull Request 7028`_, `Pull Request 7395`_
* Restores OpenID post authentication protocols.
`Pull Request 7676`_
* Replace custom UI colors with equivalent theme colors, consolidate color
handling.
`Pull Request 7203`_
* Modernize library toolbar client code.
`Pull Request 7234`_
* Large refactoring of model migrations
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7621`_, `Pull Request 7248`_,
`Pull Request 7737`_, `Pull Request 7695`_
* Implement a general purpose tagging component in the Galaxy client code.
`Pull Request 7270`_
* Define doctype method on XMLParser target
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7303`_
* Refactor ``galaxy.util.handlers`` -> ``galaxy.web.stack.handlers``.
`Pull Request 7339`_
* Move ``create_history_template`` out of ``galaxy.util``.
`Pull Request 7522`_
* Refactor ``galaxy.web.form_builder`` into ``galaxy.util.form_builder``.
`Pull Request 7529`_
* Drop unused install keyword and load TS workflows with utf-8 encoding
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7423`_
* Remove biostar integrations.
(with help from `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7443`_, `Pull Request 7510`_
* Refactor TagManager (back) to TagHandler.
`Pull Request 7530`_
* Refactor ``output_collect.py`` toward a database session-less modality.
`Pull Request 7541`_
* Drop D3 from publicly provided libs
`Pull Request 7542`_
* Fix dependency cycle between ``galaxy.security`` and ``galaxy.model``.
`Pull Request 7554`_
* Refactor ``galaxy.dataset_collections`` into ``galaxy.model.dataset_collections``.
`Pull Request 7588`_
* Toastr debowerization and refactoring.
`Pull Request 7640`_
* Tweak ``popup-menu.js`` error handling.
`Pull Request 7643`_
* Update Conda version that new Galaxies will install
`Pull Request 8048`_
Fixes
-------------------------------
* Fix client styleguide asset handling.
`Pull Request 7664`_
* Handle subworkflows in view workflow mako
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7276`_
* Fix removing tags from a dataset previously only the first tag could be removed
(thanks to `@gtrack <https://github.com/gtrack>`__).
`Pull Request 7674`_, `Pull Request 7680`_
* Fix displaying and editing SelectTagParameters in workflow editor
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7534`_
* Fix workflow output rectification.
`Pull Request 7101`_
* Interactive Environment Fixes
`Pull Request 7917`_
* Make job script actually return tool exit code
(thanks to `@bernt-matthias <https://github.com/bernt-matthias>`__).
`Pull Request 7147`_
* Fix client galaxy object instance access in visualizations.
`Pull Request 7198`_
* Assorted component bugfixes.
`Pull Request 7200`_
* Update IE proxy dependencies.
`Pull Request 7208`_
* Cleanup code for univa job runner
(thanks to `@bernt-matthias <https://github.com/bernt-matthias>`__).
`Pull Request 7210`_
* Verify and update .venv's node version.
`Pull Request 7220`_
* Update ``use_interactive`` default in docs
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7221`_
* Fix hotdata method access.
`Pull Request 7256`_
* Fix saving imported subworkflows
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7262`_
* Fix "occured" typo everywhere
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7266`_
* Fix flakey history import metadata test
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7279`_
* Do not skip the client build in dockerized selenium tests
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7280`_
* Fixes for the cluster documentation
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7281`_
* Fix ``ObjectNotFound`` exception when exporting an history
(thanks to `@abretaud <https://github.com/abretaud>`__).
`Pull Request 7286`_
* Do not remove tools from other installed revisions when uninstalling TS
repo
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7300`_
* Remove unused keyword in resend email helper.
`Pull Request 7315`_
* Fix popupmenu creation.
`Pull Request 7318`_
* Fix trackster toolbox filter for logged-in users
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7319`_
* Remove overlapping tooltip from dropdown button in library toolbar.
`Pull Request 7321`_
* UI fixes for libraries.
`Pull Request 7337`_
* Fix ``test_import_metadata_regeneration`` API test
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7340`_
* Possible fix for fasta file never getting filesize
(thanks to `@Slugger70 <https://github.com/Slugger70>`__).
`Pull Request 7374`_
* Fix upload button style.
`Pull Request 7381`_
* Fix link doc syntax
(thanks to `@galaxyproject <https://github.com/galaxyproject>`__).
`Pull Request 7388`_
* Update application documentation
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7391`_
* Fix pie chart and portlet height in flexboxes.
`Pull Request 7396`_
* Fix ``LocalShellRunner``
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7438`_
* Use a lock on cleanup, expire_tool and cache_tool
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7446`_
* Fix loading workflows with steps without default label
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7448`_
* Remove broken configuration option tool_submission_burst
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7449`_
* Restore ``get_filename`` to ``galaxy.tools.verify:verify()``
`Pull Request 7452`_
* Fix documentation for statsd and uwsgi
(thanks to `@abretaud <https://github.com/abretaud>`__).
`Pull Request 7453`_
* Fix hidden parameter use in workflows
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7458`_
* Fix syntax of XSD tool schema.
`Pull Request 7462`_
* Fix workflow building typo
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7472`_
* Correct ``virtualenv`` download with no ``wget``/``curl``
(thanks to `@hmenager <https://github.com/hmenager>`__).
`Pull Request 7476`_
* Use a relative ``output.publicPath`` to avoid 404 errors when serving with a url
prefix
(thanks to `@abretaud <https://github.com/abretaud>`__).
`Pull Request 7481`_
* Restrict loading of JSON files on the server via the workflow API to Galaxy
admins
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7499`_
* Fix warning message formatting in sharing controller
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7504`_
* Make sure ``temp_output_dir`` path is absolute
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7517`_
* Create directory before copying file there
(thanks to `@pvanheus <https://github.com/pvanheus>`__).
`Pull Request 7519`_
* Fix routing when serving Galaxy at a prefix.
`Pull Request 7523`_
* Small object store fixes.
`Pull Request 7536`_
* Fix entering workflow parameter in workflow run form
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7543`_
* Extend reload test case logging
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7547`_
* Correct db-self handler assignment method
(thanks to `@erasche <https://github.com/erasche>`__).
`Pull Request 7561`_
* Fix database config doctests when env vars are in use for dburi
`Pull Request 7562`_
* Fix help warnings style.
`Pull Request 7566`_
* Fix to run ``bootstrap_history.py`` inside Galaxy's virtualenv
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7584`_
* Update cloud imports to adhere with cloudbridge interface changes.
`Pull Request 7586`_
* Fix RStudio GIE
(thanks to `@erasche <https://github.com/erasche>`__).
`Pull Request 7590`_, `Pull Request 7925`_
* Fix styleguide.
`Pull Request 7602`_
* Fix history options menu href navigation
`Pull Request 7612`_
* Minor cli and metadata fixes
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7614`_
* Improve string escaping and changeset validation on toolshed.
`Pull Request 7616`_
* Delay workflow step execution for discovered & mapped-over input
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7633`_
* Fix float to int casting
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7634`_
* Adjust ``test_run_with_numeric_input_connection`` to extra line
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7645`_
* Fix incorrect LDDAs being used as collection members.
`Pull Request 7646`_
* Fix GenomeSpace tools.
`Pull Request 7647`_, `Pull Request 7697`_
* Bugfix for input selection with tag representation in ``ui-select-default``.
`Pull Request 7658`_
* Drop now unused import endpoint from workflow controller.
`Pull Request 7660`_
* Fix for ``trans.redirect`` not setting cookies/headers.
`Pull Request 7663`_
* Fix shutdown for Pulsar MQ Runner.
`Pull Request 7667`_
* Fix "Run workflow" jumps when clicking
(thanks to `@gtrack <https://github.com/gtrack>`__).
`Pull Request 7675`_
* Detect errors using exit code for sort tool
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7679`_
* Fix ``format_source`` for implicit conversion inputs and ``fasta.gz`` upload
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7682`_
* Plugin static staging fix.
`Pull Request 7689`_
* Fix side panel styling, adjust appearance in reports.
`Pull Request 7690`_
* Patch for metadata setting of minimal BIOM1 files
(thanks to `@bebatut <https://github.com/bebatut>`__).
`Pull Request 7696`_
* Only check for exit code on actual sort command
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7699`_
* Update ``pytest-posgresql`` to 1.4.0, which removes a hard dependency on
``psycopg2``
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7703`_
* Fix runner param validation in the DRMAA runner.
`Pull Request 7709`_
* Restrict workflow invocation index to current user
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7711`_
* Copy ``tools_by_id`` before collecting dependency status
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7713`_
* Fix uWSGI startup with separate ini file under Python 3
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7716`_
* Fix (re)starting Galaxy using paste, ``GALAXY_RUN_ALL=1`` and ``--wait``
under macOS
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7722`_
* Fix check on links in ``CompressedFile.safemembers()``
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7723`_
* Unpause dependent jobs when resuming jobs
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7724`_
* Commented-out cloudbridge requirement for the cloud/send tool.
`Pull Request 7727`_
* Fix comments
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7738`_
* Upgrade to latest Pulsar release for various remote job running fixes.
`Pull Request 7744`_, `Pull Request 7865`_
* Fix automatic user registration.
`Pull Request 7749`_
* Sanitize HTML in messages using ``galaxy.util.sanitize_html``.
`Pull Request 7751`_
* Fix Kubernetes integration tests for Docker on Mac.
`Pull Request 7754`_
* Fix BootstrapVue component specification in Citations.
`Pull Request 7778`_
* Symlink two more images that are accessed via non-webpack'd applications.
`Pull Request 7779`_
* Make ``url_get`` return unicode
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7782`_
* Disable flexible spreading of radio buttons by default.
`Pull Request 7788`_
* Fix default value handling of color parameter.
`Pull Request 7475`_
* Fix various Python deprecations
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7800`_
* Return HTTP 400 for `GET /api/datasets/nonexistent_id`
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7806`_
* Encode email messages using UTF-8
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7812`_
* Fix nested macro/token expansion on Python 3
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7823`_
* Possible fix for WSGI process issue `#7758
<https://github.com/galaxyproject/galaxy/issues/7758>`__
(thanks to `@tmcgowan <https://github.com/tmcgowan>`__).
`Pull Request 7824`_
* Fix ``InputValueWrapper`` gt/ge/lt/le comparisons
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7826`_
* Fix trackster issue with constraining (``overflow:non-visible``) containers.
`Pull Request 7845`_
* Improve upload accessibility.
`Pull Request 7848`_
* Adjust appearance of user creation form in admin panel.
`Pull Request 7851`_
* Use just the env name when checking ``CONDA_DEFAULT_ENV``
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7853`_
* Fix workflow extraction for jobs whose JobToDatasetOutputAssociation
references a discovered dataset
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7855`_
* Fix flag for library dataset option in data selector.
`Pull Request 7859`_
* Fix bug preventing handler runner plugin handling.
`Pull Request 7870`_
* Fix click targeting for quota usage details
`Pull Request 7877`_
* Allow typing e in float param field.
`Pull Request 7880`_
* Update Cheetah dependency, fixes ``AssertionError``
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7887`_
* Fix application of history default permissions to anonymous histories
carried over upon login.
`Pull Request 7904`_
* Fix multi-history copying of collections.
`Pull Request 7906`_
* Remove GFF headers during conversion and test fix
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7916`_
* Fix community tags showing JSON file.
`Pull Request 7923`_
* Fix upload of gzipped VCF files
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7933`_
* Fix documentation building
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7934`_
* Listen to history changes in tool form until job has been submitted.
`Pull Request 7943`_
* Fixed wrong example for ``amqp_ack_republish_time`` in
``job_conf.xml.sample_advanced``
(thanks to `@AndreasSko <https://github.com/AndreasSko>`__).
`Pull Request 7983`_
* Backport various upload encoding fixes from `#7995 <https://github.com/galaxyproject/galaxy/issues/7995>`__
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 8000`_, `Pull Request 8004`_
* Disable create user button while request is being processed
`Pull Request 8029`_
* Fix multipanel history search
`Pull Request 8085`_
.. include:: 19.05_prs.rst
+55 -3
View File
@@ -3,8 +3,60 @@
May 2019 Galaxy Release (v 19.05)
===========================================================
.. include:: _header.rst
Schedule
Highlights
===========================================================
* Planned Freeze Date: 2019-05-06
* Planned Release Date: 2019-05-27
**User Facing Release Notes**
Galaxy releases now include "user facing" release notes, you are reading
the traditional release notes which have always been relatively admin and developer
oriented but will likely be even more so now. Features such as favoriting tools,
improved workflow editor feedback, and an exciting new cellxgene GIE may have
been featured in these release notes in the past but are now featured in the
user release notes instead. A huge thanks to `@erasche <https://github.com/erasche>`__
for getting the ball rolling on this initiative.
Check out the `19.05 user release notes<https://docs.galaxyproject.org/en/release_19.05/releases/19.05_announce_user.html>`__.
**Login and Registration Rewrite**
The march toward replacing templated backend generated HTML with modern, reactive
components accelerated in Galaxy 19.05. Galaxy's login, logout, and registration pages
were replaced with VueJS components. Support for OIDC login options was added and
certain deprecated OpenID login options were removed. This release contains many other
client code enhancements including a new client initialization pipeline, ESLint based
linting, and greatly optimized initial dynamic loading of bundles.
**Improvements to Workflow Expressivity**
In 19.01, non-data connections were added to the workflow editor in the form of
explicit, typed, non-data inputs to workflows. This idea has been generalized in 19.05
and tool can now produce non-data outputs and a new class of tools called "Expression"
tools has been added to make this especially easy. The Format 2 workflow format is now
importable by default and admin-only extensions even allow embedding tool definitions
directly into workflows. Many thanks to `@mvdbeek <https://github.com/mvdbeek>`__ for
pushing this effort.
Get Galaxy
==========
The code lives at `GitHub <https://github.com/galaxyproject/galaxy>`__ and you should have `Git <https://git-scm.com/>`__ to obtain it.
To get a new Galaxy repository run:
.. code-block:: shell
$ git clone -b release_19.05 https://github.com/galaxyproject/galaxy.git
To update an existing Galaxy repository run:
.. code-block:: shell
$ git fetch origin && git checkout release_19.05 && git pull --ff-only origin release_19.05
See the `community hub <https://galaxyproject.org/develop/source-code/>`__ for additional details regarding the source code locations.
Release Notes
===========================================================
.. include:: 19.05.rst
:start-after: announce_start
.. include:: _thanks.rst
@@ -0,0 +1,97 @@
===========================================================
May 2019 Galaxy Release (v 19.05)
===========================================================
.. include:: _header.rst
Highlights
===========================================================
**Tool Favorites**
Tools can now be marked as favorites, and then they'll be easily accessible from the star button in your tool panel.
.. figure:: images/19.05-favs.gif
:alt: Adding a favorite tool.
**Workflow Editor Connection Feedback**
The editor now provides feedback on why connections are invalid, so you aren't left wondering why two tools won't connect. For complex data pipelines this should greatly simplify your life!
.. figure:: images/19.05-wf-hints.gif
:alt: Workflow editor connections provide feedback on why they won't connect.
**Data Dialog for Tool Form**
There is a new way to select datasets when running tools! It is a very simple method to select any number of files from both your History and Data Libraries.
.. figure:: images/19.05-inputs.gif
:alt: Data dialog for selecting dataset in the tool form.
Additionally the selector implements a highly requested feature, the ability to run tools on arbitrary datasets from a collection
.. figure:: images/19.05-input-collection.gif
:alt: Selecting datasets from within a collection.
**History Export/Import Reworked**
These features used to be clumsy in the past but do not despair since in this release they got a revamp and their reliability skyrocketed! Moving historic object across Galaxies should now be easier than ever. Rocketfuel included.
New Visualizations
===========================================================
.. visualizations
`@jxtx <https://github.com/jxtx>`__ has implemented a Galaxy Interactive
Environment for `cellxgene <https://github.com/chanzuckerberg/cellxgene>`__, an
interactive explorer for single-cell transcriptomics data. `Pull Request 7268`_
.. figure:: https://user-images.githubusercontent.com/79973/51766184-f5faea80-20a7-11e9-86c8-a3127d501076.gif
:alt: cellxgene demo
New Datatypes
===========================================================
* Add the single-cell datatype ``mtx``
(thanks to `@bebatut <https://github.com/bebatut>`__ and
`@nsoranzo <https://github.com/nsoranzo>`__).
`Pull Request 7569`_, `Pull Request 7702`_, `Pull Request 7717`_
* Add ``geojson`` and shapefile (``shp``) datatypes for better GIS data support
(thanks to `@bgruening <https://github.com/bgruening>`__).
`Pull Request 7773`_, `Pull Request 7819`_
* Add ``imgt.json`` datatype for IMGT immune system libraries
(thanks to `@jj-umn <https://github.com/jj-umn>`__).
`Pull Request 7587`_
* Add microarrays data types ``gpr`` and ``gal``
(thanks to `@bensellak <https://github.com/bensellak>`__).
`Pull Request 7457`_
* Add ``spaln`` (space-efficient spliced alignment) database type
(thanks to `@pvanheus <https://github.com/pvanheus>`__).
`Pull Request 7718`_
* Redefine ``cel`` datatype
(thanks to `@bensellak <https://github.com/bensellak>`__).
`Pull Request 7514`_
Builtin Tool Updates
===========================================================
.. tools
* Update grouping tool to not remove empty cells at the begin/start of lines
(thanks to `@bernt-matthias <https://github.com/bernt-matthias>`__).
`Pull Request 7205`_
* Add general purpose expression tool
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__).
`Pull Request 7796`_
Release Notes
===========================================================
Please see the `full release notes <19.05_announce.html>`_ for more details.
.. include:: 19.05_prs.rst
.. include:: _thanks.rst
+370
View File
@@ -0,0 +1,370 @@
.. github_links
.. _Pull Request 4659: https://github.com/galaxyproject/galaxy/pull/4659
.. _Pull Request 5495: https://github.com/galaxyproject/galaxy/pull/5495
.. _Pull Request 6321: https://github.com/galaxyproject/galaxy/pull/6321
.. _Pull Request 6437: https://github.com/galaxyproject/galaxy/pull/6437
.. _Pull Request 6621: https://github.com/galaxyproject/galaxy/pull/6621
.. _Pull Request 6652: https://github.com/galaxyproject/galaxy/pull/6652
.. _Pull Request 6866: https://github.com/galaxyproject/galaxy/pull/6866
.. _Pull Request 6958: https://github.com/galaxyproject/galaxy/pull/6958
.. _Pull Request 7028: https://github.com/galaxyproject/galaxy/pull/7028
.. _Pull Request 7047: https://github.com/galaxyproject/galaxy/pull/7047
.. _Pull Request 7095: https://github.com/galaxyproject/galaxy/pull/7095
.. _Pull Request 7101: https://github.com/galaxyproject/galaxy/pull/7101
.. _Pull Request 7117: https://github.com/galaxyproject/galaxy/pull/7117
.. _Pull Request 7144: https://github.com/galaxyproject/galaxy/pull/7144
.. _Pull Request 7147: https://github.com/galaxyproject/galaxy/pull/7147
.. _Pull Request 7154: https://github.com/galaxyproject/galaxy/pull/7154
.. _Pull Request 7156: https://github.com/galaxyproject/galaxy/pull/7156
.. _Pull Request 7158: https://github.com/galaxyproject/galaxy/pull/7158
.. _Pull Request 7177: https://github.com/galaxyproject/galaxy/pull/7177
.. _Pull Request 7185: https://github.com/galaxyproject/galaxy/pull/7185
.. _Pull Request 7186: https://github.com/galaxyproject/galaxy/pull/7186
.. _Pull Request 7187: https://github.com/galaxyproject/galaxy/pull/7187
.. _Pull Request 7192: https://github.com/galaxyproject/galaxy/pull/7192
.. _Pull Request 7193: https://github.com/galaxyproject/galaxy/pull/7193
.. _Pull Request 7195: https://github.com/galaxyproject/galaxy/pull/7195
.. _Pull Request 7198: https://github.com/galaxyproject/galaxy/pull/7198
.. _Pull Request 7200: https://github.com/galaxyproject/galaxy/pull/7200
.. _Pull Request 7202: https://github.com/galaxyproject/galaxy/pull/7202
.. _Pull Request 7203: https://github.com/galaxyproject/galaxy/pull/7203
.. _Pull Request 7205: https://github.com/galaxyproject/galaxy/pull/7205
.. _Pull Request 7207: https://github.com/galaxyproject/galaxy/pull/7207
.. _Pull Request 7208: https://github.com/galaxyproject/galaxy/pull/7208
.. _Pull Request 7209: https://github.com/galaxyproject/galaxy/pull/7209
.. _Pull Request 7210: https://github.com/galaxyproject/galaxy/pull/7210
.. _Pull Request 7213: https://github.com/galaxyproject/galaxy/pull/7213
.. _Pull Request 7214: https://github.com/galaxyproject/galaxy/pull/7214
.. _Pull Request 7215: https://github.com/galaxyproject/galaxy/pull/7215
.. _Pull Request 7219: https://github.com/galaxyproject/galaxy/pull/7219
.. _Pull Request 7220: https://github.com/galaxyproject/galaxy/pull/7220
.. _Pull Request 7221: https://github.com/galaxyproject/galaxy/pull/7221
.. _Pull Request 7222: https://github.com/galaxyproject/galaxy/pull/7222
.. _Pull Request 7226: https://github.com/galaxyproject/galaxy/pull/7226
.. _Pull Request 7232: https://github.com/galaxyproject/galaxy/pull/7232
.. _Pull Request 7234: https://github.com/galaxyproject/galaxy/pull/7234
.. _Pull Request 7235: https://github.com/galaxyproject/galaxy/pull/7235
.. _Pull Request 7246: https://github.com/galaxyproject/galaxy/pull/7246
.. _Pull Request 7247: https://github.com/galaxyproject/galaxy/pull/7247
.. _Pull Request 7248: https://github.com/galaxyproject/galaxy/pull/7248
.. _Pull Request 7254: https://github.com/galaxyproject/galaxy/pull/7254
.. _Pull Request 7255: https://github.com/galaxyproject/galaxy/pull/7255
.. _Pull Request 7256: https://github.com/galaxyproject/galaxy/pull/7256
.. _Pull Request 7262: https://github.com/galaxyproject/galaxy/pull/7262
.. _Pull Request 7266: https://github.com/galaxyproject/galaxy/pull/7266
.. _Pull Request 7268: https://github.com/galaxyproject/galaxy/pull/7268
.. _Pull Request 7270: https://github.com/galaxyproject/galaxy/pull/7270
.. _Pull Request 7272: https://github.com/galaxyproject/galaxy/pull/7272
.. _Pull Request 7276: https://github.com/galaxyproject/galaxy/pull/7276
.. _Pull Request 7279: https://github.com/galaxyproject/galaxy/pull/7279
.. _Pull Request 7280: https://github.com/galaxyproject/galaxy/pull/7280
.. _Pull Request 7281: https://github.com/galaxyproject/galaxy/pull/7281
.. _Pull Request 7285: https://github.com/galaxyproject/galaxy/pull/7285
.. _Pull Request 7286: https://github.com/galaxyproject/galaxy/pull/7286
.. _Pull Request 7287: https://github.com/galaxyproject/galaxy/pull/7287
.. _Pull Request 7288: https://github.com/galaxyproject/galaxy/pull/7288
.. _Pull Request 7291: https://github.com/galaxyproject/galaxy/pull/7291
.. _Pull Request 7300: https://github.com/galaxyproject/galaxy/pull/7300
.. _Pull Request 7303: https://github.com/galaxyproject/galaxy/pull/7303
.. _Pull Request 7313: https://github.com/galaxyproject/galaxy/pull/7313
.. _Pull Request 7315: https://github.com/galaxyproject/galaxy/pull/7315
.. _Pull Request 7316: https://github.com/galaxyproject/galaxy/pull/7316
.. _Pull Request 7318: https://github.com/galaxyproject/galaxy/pull/7318
.. _Pull Request 7319: https://github.com/galaxyproject/galaxy/pull/7319
.. _Pull Request 7321: https://github.com/galaxyproject/galaxy/pull/7321
.. _Pull Request 7322: https://github.com/galaxyproject/galaxy/pull/7322
.. _Pull Request 7323: https://github.com/galaxyproject/galaxy/pull/7323
.. _Pull Request 7329: https://github.com/galaxyproject/galaxy/pull/7329
.. _Pull Request 7334: https://github.com/galaxyproject/galaxy/pull/7334
.. _Pull Request 7337: https://github.com/galaxyproject/galaxy/pull/7337
.. _Pull Request 7339: https://github.com/galaxyproject/galaxy/pull/7339
.. _Pull Request 7340: https://github.com/galaxyproject/galaxy/pull/7340
.. _Pull Request 7342: https://github.com/galaxyproject/galaxy/pull/7342
.. _Pull Request 7344: https://github.com/galaxyproject/galaxy/pull/7344
.. _Pull Request 7345: https://github.com/galaxyproject/galaxy/pull/7345
.. _Pull Request 7346: https://github.com/galaxyproject/galaxy/pull/7346
.. _Pull Request 7347: https://github.com/galaxyproject/galaxy/pull/7347
.. _Pull Request 7350: https://github.com/galaxyproject/galaxy/pull/7350
.. _Pull Request 7356: https://github.com/galaxyproject/galaxy/pull/7356
.. _Pull Request 7357: https://github.com/galaxyproject/galaxy/pull/7357
.. _Pull Request 7358: https://github.com/galaxyproject/galaxy/pull/7358
.. _Pull Request 7359: https://github.com/galaxyproject/galaxy/pull/7359
.. _Pull Request 7363: https://github.com/galaxyproject/galaxy/pull/7363
.. _Pull Request 7365: https://github.com/galaxyproject/galaxy/pull/7365
.. _Pull Request 7366: https://github.com/galaxyproject/galaxy/pull/7366
.. _Pull Request 7367: https://github.com/galaxyproject/galaxy/pull/7367
.. _Pull Request 7369: https://github.com/galaxyproject/galaxy/pull/7369
.. _Pull Request 7370: https://github.com/galaxyproject/galaxy/pull/7370
.. _Pull Request 7371: https://github.com/galaxyproject/galaxy/pull/7371
.. _Pull Request 7374: https://github.com/galaxyproject/galaxy/pull/7374
.. _Pull Request 7379: https://github.com/galaxyproject/galaxy/pull/7379
.. _Pull Request 7381: https://github.com/galaxyproject/galaxy/pull/7381
.. _Pull Request 7387: https://github.com/galaxyproject/galaxy/pull/7387
.. _Pull Request 7388: https://github.com/galaxyproject/galaxy/pull/7388
.. _Pull Request 7391: https://github.com/galaxyproject/galaxy/pull/7391
.. _Pull Request 7395: https://github.com/galaxyproject/galaxy/pull/7395
.. _Pull Request 7396: https://github.com/galaxyproject/galaxy/pull/7396
.. _Pull Request 7397: https://github.com/galaxyproject/galaxy/pull/7397
.. _Pull Request 7398: https://github.com/galaxyproject/galaxy/pull/7398
.. _Pull Request 7400: https://github.com/galaxyproject/galaxy/pull/7400
.. _Pull Request 7404: https://github.com/galaxyproject/galaxy/pull/7404
.. _Pull Request 7423: https://github.com/galaxyproject/galaxy/pull/7423
.. _Pull Request 7424: https://github.com/galaxyproject/galaxy/pull/7424
.. _Pull Request 7428: https://github.com/galaxyproject/galaxy/pull/7428
.. _Pull Request 7435: https://github.com/galaxyproject/galaxy/pull/7435
.. _Pull Request 7437: https://github.com/galaxyproject/galaxy/pull/7437
.. _Pull Request 7438: https://github.com/galaxyproject/galaxy/pull/7438
.. _Pull Request 7439: https://github.com/galaxyproject/galaxy/pull/7439
.. _Pull Request 7442: https://github.com/galaxyproject/galaxy/pull/7442
.. _Pull Request 7443: https://github.com/galaxyproject/galaxy/pull/7443
.. _Pull Request 7445: https://github.com/galaxyproject/galaxy/pull/7445
.. _Pull Request 7446: https://github.com/galaxyproject/galaxy/pull/7446
.. _Pull Request 7448: https://github.com/galaxyproject/galaxy/pull/7448
.. _Pull Request 7449: https://github.com/galaxyproject/galaxy/pull/7449
.. _Pull Request 7451: https://github.com/galaxyproject/galaxy/pull/7451
.. _Pull Request 7452: https://github.com/galaxyproject/galaxy/pull/7452
.. _Pull Request 7453: https://github.com/galaxyproject/galaxy/pull/7453
.. _Pull Request 7457: https://github.com/galaxyproject/galaxy/pull/7457
.. _Pull Request 7458: https://github.com/galaxyproject/galaxy/pull/7458
.. _Pull Request 7459: https://github.com/galaxyproject/galaxy/pull/7459
.. _Pull Request 7460: https://github.com/galaxyproject/galaxy/pull/7460
.. _Pull Request 7461: https://github.com/galaxyproject/galaxy/pull/7461
.. _Pull Request 7462: https://github.com/galaxyproject/galaxy/pull/7462
.. _Pull Request 7463: https://github.com/galaxyproject/galaxy/pull/7463
.. _Pull Request 7466: https://github.com/galaxyproject/galaxy/pull/7466
.. _Pull Request 7470: https://github.com/galaxyproject/galaxy/pull/7470
.. _Pull Request 7471: https://github.com/galaxyproject/galaxy/pull/7471
.. _Pull Request 7472: https://github.com/galaxyproject/galaxy/pull/7472
.. _Pull Request 7475: https://github.com/galaxyproject/galaxy/pull/7475
.. _Pull Request 7476: https://github.com/galaxyproject/galaxy/pull/7476
.. _Pull Request 7477: https://github.com/galaxyproject/galaxy/pull/7477
.. _Pull Request 7478: https://github.com/galaxyproject/galaxy/pull/7478
.. _Pull Request 7480: https://github.com/galaxyproject/galaxy/pull/7480
.. _Pull Request 7481: https://github.com/galaxyproject/galaxy/pull/7481
.. _Pull Request 7483: https://github.com/galaxyproject/galaxy/pull/7483
.. _Pull Request 7485: https://github.com/galaxyproject/galaxy/pull/7485
.. _Pull Request 7486: https://github.com/galaxyproject/galaxy/pull/7486
.. _Pull Request 7487: https://github.com/galaxyproject/galaxy/pull/7487
.. _Pull Request 7499: https://github.com/galaxyproject/galaxy/pull/7499
.. _Pull Request 7500: https://github.com/galaxyproject/galaxy/pull/7500
.. _Pull Request 7504: https://github.com/galaxyproject/galaxy/pull/7504
.. _Pull Request 7505: https://github.com/galaxyproject/galaxy/pull/7505
.. _Pull Request 7507: https://github.com/galaxyproject/galaxy/pull/7507
.. _Pull Request 7510: https://github.com/galaxyproject/galaxy/pull/7510
.. _Pull Request 7514: https://github.com/galaxyproject/galaxy/pull/7514
.. _Pull Request 7515: https://github.com/galaxyproject/galaxy/pull/7515
.. _Pull Request 7516: https://github.com/galaxyproject/galaxy/pull/7516
.. _Pull Request 7517: https://github.com/galaxyproject/galaxy/pull/7517
.. _Pull Request 7518: https://github.com/galaxyproject/galaxy/pull/7518
.. _Pull Request 7519: https://github.com/galaxyproject/galaxy/pull/7519
.. _Pull Request 7521: https://github.com/galaxyproject/galaxy/pull/7521
.. _Pull Request 7522: https://github.com/galaxyproject/galaxy/pull/7522
.. _Pull Request 7523: https://github.com/galaxyproject/galaxy/pull/7523
.. _Pull Request 7524: https://github.com/galaxyproject/galaxy/pull/7524
.. _Pull Request 7527: https://github.com/galaxyproject/galaxy/pull/7527
.. _Pull Request 7529: https://github.com/galaxyproject/galaxy/pull/7529
.. _Pull Request 7530: https://github.com/galaxyproject/galaxy/pull/7530
.. _Pull Request 7532: https://github.com/galaxyproject/galaxy/pull/7532
.. _Pull Request 7534: https://github.com/galaxyproject/galaxy/pull/7534
.. _Pull Request 7536: https://github.com/galaxyproject/galaxy/pull/7536
.. _Pull Request 7537: https://github.com/galaxyproject/galaxy/pull/7537
.. _Pull Request 7538: https://github.com/galaxyproject/galaxy/pull/7538
.. _Pull Request 7539: https://github.com/galaxyproject/galaxy/pull/7539
.. _Pull Request 7540: https://github.com/galaxyproject/galaxy/pull/7540
.. _Pull Request 7541: https://github.com/galaxyproject/galaxy/pull/7541
.. _Pull Request 7542: https://github.com/galaxyproject/galaxy/pull/7542
.. _Pull Request 7543: https://github.com/galaxyproject/galaxy/pull/7543
.. _Pull Request 7544: https://github.com/galaxyproject/galaxy/pull/7544
.. _Pull Request 7545: https://github.com/galaxyproject/galaxy/pull/7545
.. _Pull Request 7546: https://github.com/galaxyproject/galaxy/pull/7546
.. _Pull Request 7547: https://github.com/galaxyproject/galaxy/pull/7547
.. _Pull Request 7548: https://github.com/galaxyproject/galaxy/pull/7548
.. _Pull Request 7549: https://github.com/galaxyproject/galaxy/pull/7549
.. _Pull Request 7553: https://github.com/galaxyproject/galaxy/pull/7553
.. _Pull Request 7554: https://github.com/galaxyproject/galaxy/pull/7554
.. _Pull Request 7555: https://github.com/galaxyproject/galaxy/pull/7555
.. _Pull Request 7556: https://github.com/galaxyproject/galaxy/pull/7556
.. _Pull Request 7558: https://github.com/galaxyproject/galaxy/pull/7558
.. _Pull Request 7560: https://github.com/galaxyproject/galaxy/pull/7560
.. _Pull Request 7561: https://github.com/galaxyproject/galaxy/pull/7561
.. _Pull Request 7562: https://github.com/galaxyproject/galaxy/pull/7562
.. _Pull Request 7565: https://github.com/galaxyproject/galaxy/pull/7565
.. _Pull Request 7566: https://github.com/galaxyproject/galaxy/pull/7566
.. _Pull Request 7569: https://github.com/galaxyproject/galaxy/pull/7569
.. _Pull Request 7570: https://github.com/galaxyproject/galaxy/pull/7570
.. _Pull Request 7571: https://github.com/galaxyproject/galaxy/pull/7571
.. _Pull Request 7572: https://github.com/galaxyproject/galaxy/pull/7572
.. _Pull Request 7573: https://github.com/galaxyproject/galaxy/pull/7573
.. _Pull Request 7574: https://github.com/galaxyproject/galaxy/pull/7574
.. _Pull Request 7575: https://github.com/galaxyproject/galaxy/pull/7575
.. _Pull Request 7581: https://github.com/galaxyproject/galaxy/pull/7581
.. _Pull Request 7584: https://github.com/galaxyproject/galaxy/pull/7584
.. _Pull Request 7586: https://github.com/galaxyproject/galaxy/pull/7586
.. _Pull Request 7587: https://github.com/galaxyproject/galaxy/pull/7587
.. _Pull Request 7588: https://github.com/galaxyproject/galaxy/pull/7588
.. _Pull Request 7589: https://github.com/galaxyproject/galaxy/pull/7589
.. _Pull Request 7590: https://github.com/galaxyproject/galaxy/pull/7590
.. _Pull Request 7592: https://github.com/galaxyproject/galaxy/pull/7592
.. _Pull Request 7594: https://github.com/galaxyproject/galaxy/pull/7594
.. _Pull Request 7595: https://github.com/galaxyproject/galaxy/pull/7595
.. _Pull Request 7596: https://github.com/galaxyproject/galaxy/pull/7596
.. _Pull Request 7597: https://github.com/galaxyproject/galaxy/pull/7597
.. _Pull Request 7598: https://github.com/galaxyproject/galaxy/pull/7598
.. _Pull Request 7601: https://github.com/galaxyproject/galaxy/pull/7601
.. _Pull Request 7602: https://github.com/galaxyproject/galaxy/pull/7602
.. _Pull Request 7605: https://github.com/galaxyproject/galaxy/pull/7605
.. _Pull Request 7606: https://github.com/galaxyproject/galaxy/pull/7606
.. _Pull Request 7609: https://github.com/galaxyproject/galaxy/pull/7609
.. _Pull Request 7612: https://github.com/galaxyproject/galaxy/pull/7612
.. _Pull Request 7614: https://github.com/galaxyproject/galaxy/pull/7614
.. _Pull Request 7616: https://github.com/galaxyproject/galaxy/pull/7616
.. _Pull Request 7621: https://github.com/galaxyproject/galaxy/pull/7621
.. _Pull Request 7630: https://github.com/galaxyproject/galaxy/pull/7630
.. _Pull Request 7633: https://github.com/galaxyproject/galaxy/pull/7633
.. _Pull Request 7634: https://github.com/galaxyproject/galaxy/pull/7634
.. _Pull Request 7637: https://github.com/galaxyproject/galaxy/pull/7637
.. _Pull Request 7639: https://github.com/galaxyproject/galaxy/pull/7639
.. _Pull Request 7640: https://github.com/galaxyproject/galaxy/pull/7640
.. _Pull Request 7641: https://github.com/galaxyproject/galaxy/pull/7641
.. _Pull Request 7642: https://github.com/galaxyproject/galaxy/pull/7642
.. _Pull Request 7643: https://github.com/galaxyproject/galaxy/pull/7643
.. _Pull Request 7645: https://github.com/galaxyproject/galaxy/pull/7645
.. _Pull Request 7646: https://github.com/galaxyproject/galaxy/pull/7646
.. _Pull Request 7647: https://github.com/galaxyproject/galaxy/pull/7647
.. _Pull Request 7650: https://github.com/galaxyproject/galaxy/pull/7650
.. _Pull Request 7651: https://github.com/galaxyproject/galaxy/pull/7651
.. _Pull Request 7652: https://github.com/galaxyproject/galaxy/pull/7652
.. _Pull Request 7655: https://github.com/galaxyproject/galaxy/pull/7655
.. _Pull Request 7656: https://github.com/galaxyproject/galaxy/pull/7656
.. _Pull Request 7657: https://github.com/galaxyproject/galaxy/pull/7657
.. _Pull Request 7658: https://github.com/galaxyproject/galaxy/pull/7658
.. _Pull Request 7659: https://github.com/galaxyproject/galaxy/pull/7659
.. _Pull Request 7660: https://github.com/galaxyproject/galaxy/pull/7660
.. _Pull Request 7663: https://github.com/galaxyproject/galaxy/pull/7663
.. _Pull Request 7664: https://github.com/galaxyproject/galaxy/pull/7664
.. _Pull Request 7666: https://github.com/galaxyproject/galaxy/pull/7666
.. _Pull Request 7667: https://github.com/galaxyproject/galaxy/pull/7667
.. _Pull Request 7674: https://github.com/galaxyproject/galaxy/pull/7674
.. _Pull Request 7675: https://github.com/galaxyproject/galaxy/pull/7675
.. _Pull Request 7676: https://github.com/galaxyproject/galaxy/pull/7676
.. _Pull Request 7677: https://github.com/galaxyproject/galaxy/pull/7677
.. _Pull Request 7678: https://github.com/galaxyproject/galaxy/pull/7678
.. _Pull Request 7679: https://github.com/galaxyproject/galaxy/pull/7679
.. _Pull Request 7680: https://github.com/galaxyproject/galaxy/pull/7680
.. _Pull Request 7681: https://github.com/galaxyproject/galaxy/pull/7681
.. _Pull Request 7682: https://github.com/galaxyproject/galaxy/pull/7682
.. _Pull Request 7683: https://github.com/galaxyproject/galaxy/pull/7683
.. _Pull Request 7684: https://github.com/galaxyproject/galaxy/pull/7684
.. _Pull Request 7689: https://github.com/galaxyproject/galaxy/pull/7689
.. _Pull Request 7690: https://github.com/galaxyproject/galaxy/pull/7690
.. _Pull Request 7691: https://github.com/galaxyproject/galaxy/pull/7691
.. _Pull Request 7693: https://github.com/galaxyproject/galaxy/pull/7693
.. _Pull Request 7694: https://github.com/galaxyproject/galaxy/pull/7694
.. _Pull Request 7695: https://github.com/galaxyproject/galaxy/pull/7695
.. _Pull Request 7696: https://github.com/galaxyproject/galaxy/pull/7696
.. _Pull Request 7697: https://github.com/galaxyproject/galaxy/pull/7697
.. _Pull Request 7698: https://github.com/galaxyproject/galaxy/pull/7698
.. _Pull Request 7699: https://github.com/galaxyproject/galaxy/pull/7699
.. _Pull Request 7702: https://github.com/galaxyproject/galaxy/pull/7702
.. _Pull Request 7703: https://github.com/galaxyproject/galaxy/pull/7703
.. _Pull Request 7704: https://github.com/galaxyproject/galaxy/pull/7704
.. _Pull Request 7706: https://github.com/galaxyproject/galaxy/pull/7706
.. _Pull Request 7707: https://github.com/galaxyproject/galaxy/pull/7707
.. _Pull Request 7708: https://github.com/galaxyproject/galaxy/pull/7708
.. _Pull Request 7709: https://github.com/galaxyproject/galaxy/pull/7709
.. _Pull Request 7711: https://github.com/galaxyproject/galaxy/pull/7711
.. _Pull Request 7712: https://github.com/galaxyproject/galaxy/pull/7712
.. _Pull Request 7713: https://github.com/galaxyproject/galaxy/pull/7713
.. _Pull Request 7716: https://github.com/galaxyproject/galaxy/pull/7716
.. _Pull Request 7717: https://github.com/galaxyproject/galaxy/pull/7717
.. _Pull Request 7718: https://github.com/galaxyproject/galaxy/pull/7718
.. _Pull Request 7719: https://github.com/galaxyproject/galaxy/pull/7719
.. _Pull Request 7720: https://github.com/galaxyproject/galaxy/pull/7720
.. _Pull Request 7722: https://github.com/galaxyproject/galaxy/pull/7722
.. _Pull Request 7723: https://github.com/galaxyproject/galaxy/pull/7723
.. _Pull Request 7724: https://github.com/galaxyproject/galaxy/pull/7724
.. _Pull Request 7727: https://github.com/galaxyproject/galaxy/pull/7727
.. _Pull Request 7737: https://github.com/galaxyproject/galaxy/pull/7737
.. _Pull Request 7738: https://github.com/galaxyproject/galaxy/pull/7738
.. _Pull Request 7740: https://github.com/galaxyproject/galaxy/pull/7740
.. _Pull Request 7743: https://github.com/galaxyproject/galaxy/pull/7743
.. _Pull Request 7744: https://github.com/galaxyproject/galaxy/pull/7744
.. _Pull Request 7746: https://github.com/galaxyproject/galaxy/pull/7746
.. _Pull Request 7748: https://github.com/galaxyproject/galaxy/pull/7748
.. _Pull Request 7749: https://github.com/galaxyproject/galaxy/pull/7749
.. _Pull Request 7750: https://github.com/galaxyproject/galaxy/pull/7750
.. _Pull Request 7751: https://github.com/galaxyproject/galaxy/pull/7751
.. _Pull Request 7754: https://github.com/galaxyproject/galaxy/pull/7754
.. _Pull Request 7755: https://github.com/galaxyproject/galaxy/pull/7755
.. _Pull Request 7756: https://github.com/galaxyproject/galaxy/pull/7756
.. _Pull Request 7760: https://github.com/galaxyproject/galaxy/pull/7760
.. _Pull Request 7773: https://github.com/galaxyproject/galaxy/pull/7773
.. _Pull Request 7777: https://github.com/galaxyproject/galaxy/pull/7777
.. _Pull Request 7778: https://github.com/galaxyproject/galaxy/pull/7778
.. _Pull Request 7779: https://github.com/galaxyproject/galaxy/pull/7779
.. _Pull Request 7780: https://github.com/galaxyproject/galaxy/pull/7780
.. _Pull Request 7782: https://github.com/galaxyproject/galaxy/pull/7782
.. _Pull Request 7785: https://github.com/galaxyproject/galaxy/pull/7785
.. _Pull Request 7788: https://github.com/galaxyproject/galaxy/pull/7788
.. _Pull Request 7789: https://github.com/galaxyproject/galaxy/pull/7789
.. _Pull Request 7796: https://github.com/galaxyproject/galaxy/pull/7796
.. _Pull Request 7797: https://github.com/galaxyproject/galaxy/pull/7797
.. _Pull Request 7798: https://github.com/galaxyproject/galaxy/pull/7798
.. _Pull Request 7800: https://github.com/galaxyproject/galaxy/pull/7800
.. _Pull Request 7806: https://github.com/galaxyproject/galaxy/pull/7806
.. _Pull Request 7812: https://github.com/galaxyproject/galaxy/pull/7812
.. _Pull Request 7815: https://github.com/galaxyproject/galaxy/pull/7815
.. _Pull Request 7819: https://github.com/galaxyproject/galaxy/pull/7819
.. _Pull Request 7823: https://github.com/galaxyproject/galaxy/pull/7823
.. _Pull Request 7824: https://github.com/galaxyproject/galaxy/pull/7824
.. _Pull Request 7826: https://github.com/galaxyproject/galaxy/pull/7826
.. _Pull Request 7827: https://github.com/galaxyproject/galaxy/pull/7827
.. _Pull Request 7834: https://github.com/galaxyproject/galaxy/pull/7834
.. _Pull Request 7839: https://github.com/galaxyproject/galaxy/pull/7839
.. _Pull Request 7840: https://github.com/galaxyproject/galaxy/pull/7840
.. _Pull Request 7844: https://github.com/galaxyproject/galaxy/pull/7844
.. _Pull Request 7845: https://github.com/galaxyproject/galaxy/pull/7845
.. _Pull Request 7848: https://github.com/galaxyproject/galaxy/pull/7848
.. _Pull Request 7851: https://github.com/galaxyproject/galaxy/pull/7851
.. _Pull Request 7853: https://github.com/galaxyproject/galaxy/pull/7853
.. _Pull Request 7855: https://github.com/galaxyproject/galaxy/pull/7855
.. _Pull Request 7856: https://github.com/galaxyproject/galaxy/pull/7856
.. _Pull Request 7858: https://github.com/galaxyproject/galaxy/pull/7858
.. _Pull Request 7859: https://github.com/galaxyproject/galaxy/pull/7859
.. _Pull Request 7860: https://github.com/galaxyproject/galaxy/pull/7860
.. _Pull Request 7864: https://github.com/galaxyproject/galaxy/pull/7864
.. _Pull Request 7865: https://github.com/galaxyproject/galaxy/pull/7865
.. _Pull Request 7866: https://github.com/galaxyproject/galaxy/pull/7866
.. _Pull Request 7870: https://github.com/galaxyproject/galaxy/pull/7870
.. _Pull Request 7872: https://github.com/galaxyproject/galaxy/pull/7872
.. _Pull Request 7874: https://github.com/galaxyproject/galaxy/pull/7874
.. _Pull Request 7875: https://github.com/galaxyproject/galaxy/pull/7875
.. _Pull Request 7877: https://github.com/galaxyproject/galaxy/pull/7877
.. _Pull Request 7880: https://github.com/galaxyproject/galaxy/pull/7880
.. _Pull Request 7887: https://github.com/galaxyproject/galaxy/pull/7887
.. _Pull Request 7896: https://github.com/galaxyproject/galaxy/pull/7896
.. _Pull Request 7904: https://github.com/galaxyproject/galaxy/pull/7904
.. _Pull Request 7906: https://github.com/galaxyproject/galaxy/pull/7906
.. _Pull Request 7916: https://github.com/galaxyproject/galaxy/pull/7916
.. _Pull Request 7917: https://github.com/galaxyproject/galaxy/pull/7917
.. _Pull Request 7923: https://github.com/galaxyproject/galaxy/pull/7923
.. _Pull Request 7925: https://github.com/galaxyproject/galaxy/pull/7925
.. _Pull Request 7933: https://github.com/galaxyproject/galaxy/pull/7933
.. _Pull Request 7934: https://github.com/galaxyproject/galaxy/pull/7934
.. _Pull Request 7943: https://github.com/galaxyproject/galaxy/pull/7943
.. _Pull Request 7944: https://github.com/galaxyproject/galaxy/pull/7944
.. _Pull Request 7954: https://github.com/galaxyproject/galaxy/pull/7954
.. _Pull Request 7956: https://github.com/galaxyproject/galaxy/pull/7956
.. _Pull Request 7967: https://github.com/galaxyproject/galaxy/pull/7967
.. _Pull Request 7969: https://github.com/galaxyproject/galaxy/pull/7969
.. _Pull Request 7972: https://github.com/galaxyproject/galaxy/pull/7972
.. _Pull Request 7979: https://github.com/galaxyproject/galaxy/pull/7979
.. _Pull Request 7983: https://github.com/galaxyproject/galaxy/pull/7983
.. _Pull Request 7989: https://github.com/galaxyproject/galaxy/pull/7989
.. _Pull Request 8000: https://github.com/galaxyproject/galaxy/pull/8000
.. _Pull Request 8004: https://github.com/galaxyproject/galaxy/pull/8004
.. _Pull Request 8021: https://github.com/galaxyproject/galaxy/pull/8021
.. _Pull Request 8029: https://github.com/galaxyproject/galaxy/pull/8029
.. _Pull Request 8048: https://github.com/galaxyproject/galaxy/pull/8048
.. _Pull Request 8085: https://github.com/galaxyproject/galaxy/pull/8085
+10
View File
@@ -0,0 +1,10 @@
===========================================================
September 2019 Galaxy Release (v 19.09)
===========================================================
Schedule
===========================================================
* Planned Freeze Date: 2019-09-02
* Planned Release Date: 2019-09-23
Binary file not shown.

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 983 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

+1
View File
@@ -4,6 +4,7 @@ Releases
.. toctree::
:maxdepth: 1
19.05_announce
19.01_announce
18.09_announce
18.05_announce
+3 -3
View File
@@ -108,15 +108,15 @@ class JobInstrumenter(object):
return "\n".join([c for c in commands if c])
def collect_properties(self, job_id, job_directory):
per_plugin_properites = {}
per_plugin_properties = {}
for plugin in self.plugins:
try:
properties = plugin.job_properties(job_id, job_directory)
if properties:
per_plugin_properites[plugin.plugin_type] = properties
per_plugin_properties[plugin.plugin_type] = properties
except Exception:
log.exception("Failed to collect job properties for plugin %s", plugin)
return per_plugin_properites
return per_plugin_properties
def __plugins_from_source(self, plugins_source):
return plugin_config.load_plugins(self.plugin_classes, plugins_source, self.extra_kwargs)
+6 -4
View File
@@ -1401,6 +1401,7 @@ class JobWrapper(HasResourceParameters):
job_stderr=None,
check_output_detected_state=None,
remote_metadata_directory=None,
job_metrics_directory=None,
):
"""
Called to indicate that the associated command has been run. Updates
@@ -1640,7 +1641,7 @@ class JobWrapper(HasResourceParameters):
job.set_final_state(final_job_state)
if not job.tasks:
# If job was composed of tasks, don't attempt to recollect statisitcs
self._collect_metrics(job)
self._collect_metrics(job, job_metrics_directory)
self.sa_session.flush()
log.debug('job %d ended (finish() executed in %s)' % (self.job_id, finish_timer))
if job.state == job.states.ERROR:
@@ -1727,11 +1728,12 @@ class JobWrapper(HasResourceParameters):
except Exception as e:
log.debug("Error in collect_associated_files: %s" % (e))
def _collect_metrics(self, has_metrics):
def _collect_metrics(self, has_metrics, job_metrics_directory=None):
job = has_metrics.get_job()
per_plugin_properties = self.app.job_metrics.collect_properties(job.destination_id, self.job_id, self.working_directory)
job_metrics_directory = job_metrics_directory or self.working_directory
per_plugin_properties = self.app.job_metrics.collect_properties(job.destination_id, self.job_id, job_metrics_directory)
if per_plugin_properties:
log.info("Collecting metrics for %s %s" % (type(has_metrics).__name__, getattr(has_metrics, 'id', None)))
log.info("Collecting metrics for %s %s in %s" % (type(has_metrics).__name__, getattr(has_metrics, 'id', None), job_metrics_directory))
for plugin, properties in per_plugin_properties.items():
for metric_name, metric_value in properties.items():
if metric_value is not None:
+1 -1
View File
@@ -144,7 +144,7 @@ def __externalize_commands(job_wrapper, shell, commands_builder, remote_command_
tool_commands
)
write_script(local_container_script, script_contents, config)
commands = local_container_script
commands = "%s %s" % (shell, local_container_script)
if 'working_directory' in remote_command_params:
commands = "%s %s" % (shell, join(remote_command_params['working_directory'], script_name))
commands += " > ../tool_stdout 2> ../tool_stderr"
+15 -8
View File
@@ -59,6 +59,7 @@ class KubernetesJobRunner(AsynchronousJobRunner):
k8s_default_requests_memory=dict(map=str, default=None),
k8s_default_limits_cpu=dict(map=str, default=None),
k8s_default_limits_memory=dict(map=str, default=None),
k8s_pod_retries=dict(map=int, valid=lambda x: int >= 0, default=3),
k8s_pod_retrials=dict(map=int, valid=lambda x: int >= 0, default=3))
if 'runner_param_specs' not in kwargs:
@@ -396,11 +397,17 @@ class KubernetesJobRunner(AsynchronousJobRunner):
active = 0
failed = 0
max_pod_retrials = 1
if 'k8s_pod_retrials' in self.runner_params:
max_pod_retrials = int(self.runner_params['k8s_pod_retrials'])
if 'max_pod_retrials' in job_destination.params:
max_pod_retrials = int(job_destination.params['max_pod_retrials'])
max_pod_retries = 1
if 'max_pod_retries' in job_destination.params:
max_pod_retries = int(job_destination.params['max_pod_retries'])
elif 'k8s_pod_retries' in self.runner_params:
max_pod_retries = int(self.runner_params['k8s_pod_retries'])
elif 'max_pod_retrials' in job_destination.params:
# For backward compatibility
max_pod_retries = int(job_destination.params['max_pod_retrials'])
elif 'k8s_pod_retrials' in self.runner_params:
# For backward compatibility
max_pod_retries = int(self.runner_params['max_pod_retrials'])
if 'succeeded' in job.obj['status']:
succeeded = job.obj['status']['succeeded']
@@ -416,12 +423,12 @@ class KubernetesJobRunner(AsynchronousJobRunner):
return None
elif failed > 0 and self.__job_failed_due_to_low_memory(job_state):
return self._handle_job_failure(job, job_state, reason="OOM")
elif active > 0 and failed <= max_pod_retrials:
elif active > 0 and failed <= max_pod_retries:
if not job_state.running:
job_state.running = True
job_state.job_wrapper.change_state(model.Job.states.RUNNING)
return job_state
elif failed > max_pod_retrials:
elif failed > max_pod_retries:
return self._handle_job_failure(job, job_state)
elif job_state.job_wrapper.get_job().state == model.Job.states.DELETED:
# Job has been deleted via stop_job, cleanup and remove from watched_jobs by returning `None`
@@ -443,7 +450,7 @@ class KubernetesJobRunner(AsynchronousJobRunner):
# there is more than one job associated to the expected unique job id used as selector.
log.error("More than one Kubernetes Job associated to job id '%s'", job_state.job_id)
with open(job_state.error_file, 'w') as error_file:
error_file.write("More than one Kubernetes Job associated to job id '%s'\n" % job_state.job_id)
error_file.write("More than one Kubernetes Job associated with job id '%s'\n" % job_state.job_id)
self.mark_as_failed(job_state)
return job_state
+13 -1
View File
@@ -517,11 +517,18 @@ class PulsarJobRunner(AsynchronousJobRunner):
self._handle_metadata_externally(job_wrapper, resolve_requirements=True)
# Finish the job
try:
job_metrics_directory = os.path.join(job_wrapper.working_directory, "metadata")
# Following check is a hack for jobs started during 19.01 or earlier release
# and finishing with a 19.05 code base. Eliminate the hack in 19.09 or later
# along with hacks for legacy metadata compute strategy.
if not os.path.exists(job_metrics_directory) or not any(["__instrument" in f for f in os.listdir(job_metrics_directory)]):
job_metrics_directory = job_wrapper.working_directory
job_wrapper.finish(
stdout,
stderr,
exit_code,
remote_metadata_directory=remote_metadata_directory,
job_metrics_directory=job_metrics_directory,
)
except Exception:
log.exception("Job wrapper finish method failed")
@@ -616,9 +623,14 @@ class PulsarJobRunner(AsynchronousJobRunner):
def __client_outputs(self, client, job_wrapper):
work_dir_outputs = self.get_work_dir_outputs(job_wrapper)
output_files = self.get_output_files(job_wrapper)
if self.app.config.metadata_strategy == "legacy":
# Drop this branch in 19.09.
metadata_directory = job_wrapper.working_directory
else:
metadata_directory = os.path.join(job_wrapper.working_directory, "metadata")
client_outputs = ClientOutputs(
working_directory=job_wrapper.tool_working_directory,
metadata_directory=job_wrapper.working_directory,
metadata_directory=metadata_directory,
work_dir_outputs=work_dir_outputs,
output_files=output_files,
version_file=job_wrapper.get_version_string_path(),
+11 -7
View File
@@ -13,7 +13,7 @@ from six.moves import cPickle
import galaxy.model
from galaxy.model.metadata import FileParameter, MetadataTempFile
from galaxy.util import in_directory
from galaxy.util import in_directory, safe_makedirs
log = getLogger(__name__)
@@ -73,7 +73,11 @@ class MetadataCollectionStrategy(object):
normalized_remote_metadata_directory = remote_metadata_directory and os.path.normpath(remote_metadata_directory)
normalized_path = os.path.normpath(path)
if remote_metadata_directory and normalized_path.startswith(normalized_remote_metadata_directory):
return normalized_path.replace(normalized_remote_metadata_directory, working_directory, 1)
if self.portable:
target_directory = os.path.join(working_directory, "metadata")
else:
target_directory = working_directory
return normalized_path.replace(normalized_remote_metadata_directory, target_directory, 1)
return path
dataset.metadata.from_JSON_dict(metadata_output_path, path_rewriter=path_rewriter)
@@ -88,6 +92,7 @@ class MetadataCollectionStrategy(object):
class PortableDirectoryMetadataGenerator(MetadataCollectionStrategy):
portable = True
def __init__(self, job_id):
self.job_id = job_id
@@ -104,7 +109,8 @@ class PortableDirectoryMetadataGenerator(MetadataCollectionStrategy):
tmp_dir = _init_tmp_dir(tmp_dir)
metadata_dir = os.path.join(tmp_dir, "metadata")
os.mkdir(metadata_dir)
# may already exist (i.e. metadata collection in the job handler)
safe_makedirs(metadata_dir)
def job_relative_path(path):
path_relative = os.path.relpath(path, tmp_dir)
@@ -171,6 +177,7 @@ class JobExternalOutputMetadataWrapper(MetadataCollectionStrategy):
DatasetInstance object which will use pickle (in the future this could be
JSONified as well)
"""
portable = False
def __init__(self, job_id):
self.job_id = job_id
@@ -393,8 +400,5 @@ def _get_filename_override(output_fnames, file_name):
def _init_tmp_dir(tmp_dir):
assert tmp_dir is not None
if not os.path.exists(tmp_dir):
os.makedirs(tmp_dir)
safe_makedirs(tmp_dir)
return tmp_dir
+12 -8
View File
@@ -8,6 +8,7 @@ from six.moves.urllib.parse import (
)
from galaxy import (
exceptions,
util,
web
)
@@ -167,14 +168,17 @@ class ToolShedController(BaseAPIController):
tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry(trans.app, tool_shed_url)
url = util.build_url(tool_shed_url, pathspec=['api', 'categories'])
categories = []
for category in json.loads(util.url_get(url)):
api_url = web.url_for(controller='api/tool_shed',
action='category',
tool_shed_url=urlquote(tool_shed_url),
category_id=category['id'],
qualified=True)
category['url'] = api_url
categories.append(category)
try:
for category in json.loads(util.url_get(url)):
api_url = web.url_for(controller='api/tool_shed',
action='category',
tool_shed_url=urlquote(tool_shed_url),
category_id=category['id'],
qualified=True)
category['url'] = api_url
categories.append(category)
except Exception:
raise exceptions.ObjectNotFound("Tool Shed %s is not responding." % tool_shed_url)
return categories
@expose_api
@@ -492,8 +492,8 @@ class RepositoriesController(BaseAPIController):
if not conf.whoosh_index_dir:
raise ConfigDoesNotAllowException('There is no directory for the search index specified. Please contact the administrator.')
search_term = q.strip()
if len(search_term) < 3:
raise RequestParameterInvalidException('The search term has to be at least 3 characters long.')
if len(search_term) < 1:
raise RequestParameterInvalidException('The search term has to be at least one character long.')
repo_search = RepoSearch()
@@ -502,12 +502,14 @@ class RepositoriesController(BaseAPIController):
'repo_long_description_boost',
'repo_homepage_url_boost',
'repo_remote_repository_url_boost',
'categories_boost',
'repo_owner_username_boost'])
boosts = Boosts(float(conf.get('repo_name_boost', 0.9)),
float(conf.get('repo_description_boost', 0.6)),
float(conf.get('repo_long_description_boost', 0.5)),
float(conf.get('repo_homepage_url_boost', 0.3)),
float(conf.get('repo_remote_repository_url_boost', 0.2)),
float(conf.get('categories_boost', 0.5)),
float(conf.get('repo_owner_username_boost', 0.3)))
results = repo_search.search(trans,
+2 -2
View File
@@ -90,8 +90,8 @@ class ToolsController(BaseAPIController):
if not conf.whoosh_index_dir:
raise exceptions.ConfigDoesNotAllowException('There is no directory for the search index specified. Please contact the administrator.')
search_term = q.strip()
if len(search_term) < 3:
raise exceptions.RequestParameterInvalidException('The search term has to be at least 3 characters long.')
if len(search_term) < 1:
raise exceptions.RequestParameterInvalidException('The search term has to be at least one character long.')
tool_search = ToolSearch()
+55 -48
View File
@@ -14,7 +14,7 @@ mapping:
desc: |
Verbosity of console log messages. Acceptable values can be found here:
https://docs.python.org/library/logging.html#logging-levels
database_connection:
type: str
default: sqlite:///./database/community.sqlite?isolation_level=IMMEDIATE
@@ -24,35 +24,35 @@ mapping:
may use a SQLAlchemy connection string to specify an external database
instead. This string takes many options which are explained in detail in the
config file documentation.
hgweb_config_dir:
type: str
required: false
desc: |
Where the hgweb.config file is stored.
The default is the Galaxy installation directory.
file_path:
type: str
default: database/community_files
required: false
desc: |
Where Tool Shed repositories are stored.
new_file_path:
type: str
default: database/tmp
required: false
desc: |
Where temporary files are stored.
builds_file_path:
type: str
default: tool-data/shared/ucsc/builds.txt
required: false
desc: |
File containing old-style genome builds
pretty_datetime_format:
type: str
default: $locale (UTC)
@@ -65,7 +65,7 @@ mapping:
- $locale (complete format string for the server locale),
- $iso8601 (complete format string as specified by ISO 8601 international
standard).
toolshed_search_on:
type: bool
default: true
@@ -76,7 +76,7 @@ mapping:
you can generate search index and allow full text API searching over
the repositories and tools within the Tool Shed given that you specify
the following two config options.
whoosh_index_dir:
type: str
default: database/toolshed_whoosh_indexes
@@ -87,84 +87,91 @@ mapping:
you can generate search index and allow full text API searching over
the repositories and tools within the Tool Shed given that you specify
the following two config options.
repo_name_boost:
type: float
default: 0.9
required: false
desc: |
For searching repositories at /api/repositories:
repo_description_boost:
type: float
default: 0.6
required: false
desc: |
For searching repositories at /api/repositories:
repo_long_description_boost:
type: float
default: 0.5
required: false
desc: |
For searching repositories at /api/repositories:
repo_homepage_url_boost:
type: float
default: 0.3
required: false
desc: |
For searching repositories at /api/repositories:
repo_remote_repository_url_boost:
type: float
default: 0.2
required: false
desc: |
For searching repositories at /api/repositories:
repo_owner_username_boost:
type: float
default: 0.3
required: false
desc: |
For searching repositories at /api/repositories:
categories_boost:
type: float
default: 0.5
required: false
desc: |
For searching repositories at /api/repositories:
tool_name_boost:
type: float
default: 1.2
required: false
desc: |
For searching tools at /api/tools
tool_description_boost:
type: float
default: 0.6
required: false
desc: |
For searching tools at /api/tools
tool_help_boost:
type: float
default: 0.4
required: false
desc: |
For searching tools at /api/tools
tool_repo_owner_username:
type: float
default: 0.3
required: false
desc: |
For searching tools at /api/tools
ga_code:
type: str
required: false
desc: |
You can enter tracking code here to track visitor's behavior
through your Google Analytics account. Example: UA-XXXXXXXX-Y
id_secret:
type: str
default: changethisinproductiontoo
@@ -177,7 +184,7 @@ mapping:
them access to others' sessions.
One simple way to generate a value for this is with the shell command:
python -c 'from __future__ import print_function; import time; print(time.time())' | md5sum | cut -f 1 -d ' '
use_remote_user:
type: bool
default: false
@@ -187,7 +194,7 @@ mapping:
Apache). The upstream proxy should set a REMOTE_USER header in the request.
Enabling remote user disables regular logins. For more information, see:
https://galaxyproject.org/admin/config/apache-external-user-auth/
remote_user_secret:
type: str
default: changethisinproductiontoo
@@ -226,35 +233,35 @@ mapping:
desc: |
If use_remote_user is enabled, you can set this to a URL that will log your
users out.
debug:
type: bool
default: false
required: false
desc: |
Configuration for debugging middleware
use_lint:
type: bool
default: false
required: false
desc: |
Check for WSGI compliance.
use_printdebug:
type: bool
default: true
required: false
desc: |
Intercept print statements and show them on the returned page.
use_interactive:
type: bool
default: false
required: false
desc: |
NEVER enable this on a public site (even test or QA)
admin_users:
type: str
required: false
@@ -263,7 +270,7 @@ mapping:
users (email addresses). These users will have access to the Admin section
of the server, and will have access to create users, groups, roles,
libraries, and more.
require_login:
type: bool
default: false
@@ -286,21 +293,21 @@ mapping:
desc: |
Allow administrators to delete accounts.
smtp_server:
type: str
default: smtp.your_tool_shed_server
required: false
desc: |
For use by email messages sent from the Tool Shed.
email_from:
type: str
default: your_tool_shed_email@server
required: false
desc: |
For use by email messages sent from the Tool Shed.
smtp_username:
type: str
required: false
@@ -308,7 +315,7 @@ mapping:
If your SMTP server requires a username and password, you can provide them
here (password in cleartext here, but if your server supports STARTTLS it
will be sent over the network encrypted).
smtp_password:
type: str
required: false
@@ -316,28 +323,28 @@ mapping:
If your SMTP server requires a username and password, you can provide them
here (password in cleartext here, but if your server supports STARTTLS it
will be sent over the network encrypted).
smtp_ssl:
type: bool
default: false
required: false
desc: |
If your SMTP server requires SSL from the beginning of the connection
support_url:
type: str
default: https://galaxyproject.org/support/
required: false
desc: |
The URL linked by the "Support" link in the "Help" menu.
mailing_join_addr:
type: str
default: galaxy-announce-join@bx.psu.edu
required: false
desc: |
Address to join mailing list
use_heartbeat:
type: bool
default: true
@@ -345,34 +352,34 @@ mapping:
desc: |
Write thread status periodically to 'heartbeat.log' (careful, uses disk
space rapidly!)
use_profile:
type: bool
default: true
required: false
desc: |
Profiling middleware (cProfile based)
enable_galaxy_flavor_docker_image:
type: bool
default: false
required: false
desc: |
Enable creation of Galaxy flavor Docker Image
message_box_visible:
type: bool
default: false
required: false
desc: |
Show a message box under the masthead.
message_box_content:
type: str
required: false
desc: |
Show a message box under the masthead.
message_box_class:
type: str
default: info
@@ -380,49 +387,49 @@ mapping:
desc: |
Class of the message box under the masthead. Possible values are:
'info' (the default), 'warning', 'error', 'done'.
static_enabled:
type: bool
default: true
required: false
desc: |
Serving static files (needed if running standalone)
static_cache_time:
type: int
default: 360
required: false
desc: |
Serving static files (needed if running standalone)
static_dir:
type: str
default: static/
required: false
desc: |
Serving static files (needed if running standalone)
static_images_dir:
type: str
default: static/images
required: false
desc: |
Serving static files (needed if running standalone)
static_favicon_dir:
type: str
default: static/favicon.ico
required: false
desc: |
Serving static files (needed if running standalone)
static_scripts_dir:
type: str
default: static/scripts/
required: false
desc: |
Serving static files (needed if running standalone)
static_style_dir:
type: str
default: static/style/blue
@@ -1,11 +1,13 @@
"""Module for searching the toolshed repositories"""
import logging
import re
import sys
import whoosh.index
from whoosh import scoring
from whoosh.fields import Schema, STORED, TEXT
from whoosh.fields import KEYWORD, Schema, STORED, TEXT
from whoosh.qparser import MultifieldParser
from whoosh.query import And, Term
from galaxy import exceptions
from galaxy.exceptions import ObjectNotFound
@@ -13,6 +15,7 @@ from galaxy.exceptions import ObjectNotFound
if sys.version_info > (3,):
long = int
RESERVED_SEARCH_TERMS = ["category", "owner"]
log = logging.getLogger(__name__)
schema = Schema(
@@ -23,9 +26,11 @@ schema = Schema(
homepage_url=TEXT(stored=True),
remote_repository_url=TEXT(stored=True),
repo_owner_username=TEXT(stored=True),
categories=KEYWORD(stored=True, commas=True, scorable=True),
times_downloaded=STORED,
approved=STORED,
last_updated=STORED,
repo_lineage=STORED,
full_last_updated=STORED)
@@ -66,8 +71,10 @@ class RepoSearch(object):
:param search_term: unicode encoded string with the search term(s)
:param boosts: namedtuple containing custom boosts for searchfields, see api/repositories.py
:param page_size: integer defining a length of one page
:param page: integer with the number of page requested
:returns results: dictionary containing number of hits, hits themselves and matched terms for each
:returns results: dictionary containing hits themselves and the number of hits
"""
whoosh_index_dir = trans.app.config.whoosh_index_dir
index_exists = whoosh.index.exists_in(whoosh_index_dir)
@@ -83,26 +90,30 @@ class RepoSearch(object):
'long_description_B' : boosts.repo_long_description_boost,
'homepage_url_B' : boosts.repo_homepage_url_boost,
'remote_repository_url_B' : boosts.repo_remote_repository_url_boost,
'repo_owner_username' : boosts.repo_owner_username_boost})
'repo_owner_username_B' : boosts.repo_owner_username_boost,
'categories_B' : boosts.categories_boost})
searcher = index.searcher(weighting=repo_weighting)
allow_query, search_term_without_filters = self._parse_reserved_filters(search_term)
parser = MultifieldParser([
'name',
'description',
'long_description',
'homepage_url',
'remote_repository_url',
'repo_owner_username'], schema=schema)
user_query = parser.parse('*' + search_term + '*')
'repo_owner_username',
'categories'], schema=schema)
user_query = parser.parse('*' + search_term_without_filters + '*')
try:
hits = searcher.search_page(user_query, page, pagelen=page_size, terms=True)
hits = searcher.search_page(user_query, page, pagelen=page_size, filter=allow_query, terms=True)
except ValueError:
raise ObjectNotFound('The requested page does not exist.')
log.debug('searching for: #' + str(search_term))
log.debug('user search query: #' + str(search_term))
log.debug('term without filters: #' + str(search_term_without_filters))
log.debug('total hits: ' + str(len(hits)))
log.debug('scored hits: ' + str(hits.scored_length()))
results = {}
@@ -111,6 +122,7 @@ class RepoSearch(object):
results['page_size'] = str(page_size)
results['hits'] = []
for hit in hits:
log.debug('matched terms: ' + str(hit.matched_terms()))
hit_dict = {}
hit_dict['id'] = trans.security.encode_id(hit.get('id'))
hit_dict['repo_owner_username'] = hit.get('repo_owner_username')
@@ -121,11 +133,72 @@ class RepoSearch(object):
hit_dict['description'] = hit.get('description')
hit_dict['last_updated'] = hit.get('last_updated')
hit_dict['full_last_updated'] = hit.get('full_last_updated')
hit_dict['repo_lineage'] = hit.get('repo_lineage')
hit_dict['categories'] = hit.get('categories')
hit_dict['approved'] = hit.get('approved')
hit_dict['times_downloaded'] = hit.get('times_downloaded')
results['hits'].append({'repository': hit_dict, 'matched_terms': hit.matched_terms(), 'score': hit.score})
results['hits'].append({'repository': hit_dict, 'score': hit.score})
return results
finally:
searcher.close()
else:
raise exceptions.InternalServerError('The search index file is missing.')
def _parse_reserved_filters(self, search_term):
"""
Support github-like filters for narrowing the results.
Order of chunks does not matter, only recognized
filter names are allowed.
:param search_term: the original search str from user input
:returns allow_query: whoosh Query object used for filtering
results of searching in index
:returns search_term_without_filters: str that represents user's
search phrase without the wildcards
>>> rs = RepoSearch()
>>> rs._parse_reserved_filters("category:assembly")
(And([Term('categories', 'assembly')]), '')
>>> rs._parse_reserved_filters("category:assembly abyss")
(And([Term('categories', 'assembly')]), 'abyss')
>>> rs._parse_reserved_filters("category:'Climate Analysis' psy_maps")
(And([Term('categories', 'Climate Analysis')]), 'psy_maps')
>>> rs._parse_reserved_filters("climate category:'Climate Analysis' owner:'bjoern gruening' psy_maps")
(And([Term('categories', 'Climate Analysis'), Term('repo_owner_username', 'bjoern gruening')]), 'climate psy_maps')
>>> rs._parse_reserved_filters("abyss category:assembly")
(And([Term('categories', 'assembly')]), 'abyss')
>>> rs._parse_reserved_filters("abyss category:assembly greg")
(And([Term('categories', 'assembly')]), 'abyss greg')
>>> rs._parse_reserved_filters("owner:greg")
(And([Term('repo_owner_username', 'greg')]), '')
>>> rs._parse_reserved_filters("owner:greg category:assembly abyss")
(And([Term('repo_owner_username', 'greg'), Term('categories', 'assembly')]), 'abyss')
>>> rs._parse_reserved_filters("meaningoflife:42")
(None, 'meaningoflife:42')
"""
allow_query = None
allow_terms = []
# Split query string on spaces that are not followed by <anytext>singlequote_space_
# to allow for quoting filtering values. Also unify double and single quotes into single quotes.
search_term_chunks = re.split(r"\s+(?!\w+'\s)", search_term.replace('"', "'"), re.MULTILINE)
reserved_terms = []
for term_chunk in search_term_chunks:
if ":" in term_chunk:
reserved_filter = term_chunk.split(":")[0]
# Remove the quotes used for delimiting values with space(s)
reserved_filter_value = term_chunk.split(":")[1].replace("'", "")
if reserved_filter in RESERVED_SEARCH_TERMS:
reserved_terms.append(term_chunk)
if reserved_filter == "category":
allow_terms.append(Term('categories', reserved_filter_value))
elif reserved_filter == "owner":
allow_terms.append(Term('repo_owner_username', reserved_filter_value))
else:
pass # Treat unrecognized filter as normal search term.
if allow_terms:
allow_query = And(allow_terms)
search_term_without_filters = " ".join([chunk for chunk in search_term_chunks if chunk not in reserved_terms])
else:
search_term_without_filters = search_term
return allow_query, search_term_without_filters
@@ -16,7 +16,7 @@ from galaxy.exceptions import ObjectNotFound
log = logging.getLogger(__name__)
tool_schema = Schema(
schema = Schema(
name=TEXT(stored=True),
description=TEXT(stored=True),
owner=TEXT(stored=True),
@@ -58,7 +58,7 @@ class ToolSearch(object):
'name',
'description',
'help',
'repo_owner_username'], schema=tool_schema)
'repo_owner_username'], schema=schema)
user_query = parser.parse('*' + search_term + '*')
+7 -2
View File
@@ -77,7 +77,8 @@ def set_metadata():
def set_metadata_portable():
import galaxy.model
galaxy.model.metadata.MetadataTempFile.tmp_dir = tool_job_working_directory = os.path.abspath(os.getcwd())
tool_job_working_directory = os.path.abspath(os.getcwd())
galaxy.model.metadata.MetadataTempFile.tmp_dir = os.path.join(tool_job_working_directory, "metadata")
metadata_params_path = os.path.join("metadata", "params.json")
try:
@@ -191,7 +192,11 @@ def validate_and_load_datatypes_config(datatypes_config):
galaxy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir))
if not os.path.exists(datatypes_config):
print("Metadata setting failed because registry.xml could not be found. You may retry setting metadata.")
# Hack for Pulsar on usegalaxy.org, drop ASAP.
datatypes_config = "configs/registry.xml"
if not os.path.exists(datatypes_config):
print("Metadata setting failed because registry.xml [%s] could not be found. You may retry setting metadata." % datatypes_config)
sys.exit(1)
import galaxy.datatypes.registry
datatypes_registry = galaxy.datatypes.registry.Registry()
+45
View File
@@ -0,0 +1,45 @@
#!/usr/bin/env python
# Modify version...
import datetime
import os
import re
import subprocess
import sys
DEV_RELEASE = os.environ.get("DEV_RELEASE", None) == "1"
PROJECT_DIRECTORY = os.getcwd()
PROJECT_DIRECTORY_NAME = os.path.basename(os.path.abspath(PROJECT_DIRECTORY))
PROJECT_MODULE_FILENAME = "project_galaxy_%s.py" % PROJECT_DIRECTORY_NAME
PROJECT_NAME = PROJECT_DIRECTORY_NAME.replace("_", "-")
def main(argv):
source_dir = argv[1]
version = argv[2]
mod_path = os.path.join(PROJECT_DIRECTORY, source_dir, PROJECT_MODULE_FILENAME)
if not DEV_RELEASE:
history_path = os.path.join(PROJECT_DIRECTORY, "HISTORY.rst")
history = open(history_path, "r").read()
today = datetime.datetime.today()
today_str = today.strftime('%Y-%m-%d')
history = history.replace(".dev0", " (%s)" % today_str)
open(history_path, "w").write(history)
mod = open(mod_path, "r").read()
mod = re.sub(r"__version__ = '[\d\.]*\.dev0'",
"__version__ = '%s'" % version,
mod)
mod = open(mod_path, "w").write(mod)
tag = "galaxy-%s-%s" % (PROJECT_NAME, version)
shell(["git", "commit", "-m", "Version %s of %s (tag %s)." % (version, PROJECT_NAME, tag),
"HISTORY.rst", mod_path])
shell(["git", "tag", tag])
def shell(cmds, **kwds):
p = subprocess.Popen(cmds, **kwds)
return p.wait()
if __name__ == "__main__":
main(sys.argv)
+70
View File
@@ -0,0 +1,70 @@
#!/usr/bin/env python
# Modify version...
import os
import re
import subprocess
import sys
from distutils.version import StrictVersion
DEV_RELEASE = os.environ.get("DEV_RELEASE", None) == "1"
PROJECT_DIRECTORY = os.getcwd()
PROJECT_DIRECTORY_NAME = os.path.basename(os.path.abspath(PROJECT_DIRECTORY))
PROJECT_MODULE_FILENAME = "project_galaxy_%s.py" % PROJECT_DIRECTORY_NAME
PROJECT_NAME = PROJECT_DIRECTORY_NAME.replace("_", "-")
def main(argv):
source_dir = argv[1]
version = argv[2]
if not DEV_RELEASE:
old_version = StrictVersion(version)
old_version_tuple = old_version.version
new_version_tuple = list(old_version_tuple)
new_version_tuple[1] = old_version_tuple[1] + 1
new_version_tuple[2] = 0
new_version = ".".join(map(str, new_version_tuple))
new_dev_version = 0
else:
dev_version = re.compile(r'dev([\d]+)').search(version).group(1)
new_dev_version = int(dev_version) + 1
new_version = version.replace("dev%s" % dev_version, "dev%s" % new_dev_version)
history_path = os.path.join(PROJECT_DIRECTORY, "HISTORY.rst")
if not DEV_RELEASE:
history = open(history_path, "r").read()
def extend(from_str, line):
from_str += "\n"
return history.replace(from_str, from_str + line + "\n")
history = extend(".. to_doc", """
---------------------
%s.dev0
---------------------
""" % new_version)
open(history_path, "w").write(history)
mod_path = os.path.join(PROJECT_DIRECTORY, source_dir, PROJECT_MODULE_FILENAME)
mod = open(mod_path, "r").read()
if not DEV_RELEASE:
mod = re.sub(r"__version__ = '[\d\.]+'",
"__version__ = '%s.dev0'" % new_version,
mod, 1)
else:
mod = re.sub("dev%s" % dev_version,
"dev%s" % new_dev_version,
mod, 1)
mod = open(mod_path, "w").write(mod)
shell(["git", "commit", "-m", "Starting work on %s %s" % (PROJECT_NAME, new_version),
"HISTORY.rst", mod_path])
def shell(cmds, **kwds):
p = subprocess.Popen(cmds, **kwds)
return p.wait()
if __name__ == "__main__":
main(sys.argv)
@@ -0,0 +1,27 @@
from __future__ import print_function
import ast
import os
import re
import sys
from distutils.version import LooseVersion
DEV_RELEASE = os.environ.get("DEV_RELEASE", None) == "1"
PROJECT_DIRECTORY = os.getcwd()
PROJECT_DIRECTORY_NAME = os.path.basename(os.path.abspath(PROJECT_DIRECTORY))
PROJECT_MODULE_FILENAME = "project_galaxy_%s.py" % PROJECT_DIRECTORY_NAME
source_dir = sys.argv[1]
PROJECT_MODULE_PATH = os.path.join(PROJECT_DIRECTORY, source_dir, PROJECT_MODULE_FILENAME)
_version_re = re.compile(r'__version__\s+=\s+(.*)')
with open(PROJECT_MODULE_PATH, 'rb') as f:
version = str(ast.literal_eval(_version_re.search(
f.read().decode('utf-8')).group(1)))
if not DEV_RELEASE:
# Strip .devN
version_tuple = LooseVersion(version).version[0:3]
print(".".join(map(str, version_tuple)))
else:
print(version)
+2 -2
View File
@@ -6,7 +6,7 @@ History
.. to_doc
---------------------
19.5.0.dev0
19.9.0.dev0
---------------------
* Initial import from dev branch of Galaxy during 19.05 release cycle.
* Initial import from dev branch of Galaxy during 19.09 development cycle.
+1
View File
@@ -0,0 +1 @@
../package.Makefile
+1
View File
@@ -0,0 +1 @@
../package-dev-requirements.txt
+2 -1
View File
@@ -1,11 +1,12 @@
# -*- coding: utf-8 -*-
__version__ = '19.5.0.dev0'
__version__ = '19.9.0.dev1'
PROJECT_NAME = "galaxy-data"
PROJECT_OWNER = PROJECT_USERAME = "galaxyproject"
PROJECT_URL = "https://github.com/galaxyproject/galaxy"
PROJECT_AUTHOR = 'Galaxy Project and Community'
PROJECT_DESCRIPTION = 'Galaxy Datatype Framework and Datatypes'
PROJECT_EMAIL = 'jmchilton@gmail.com'
RAW_CONTENT_URL = "https://raw.github.com/%s/%s/master/" % (
PROJECT_USERAME, PROJECT_NAME
+1
View File
@@ -0,0 +1 @@
../build_scripts
+2 -2
View File
@@ -26,9 +26,9 @@ with open('%s/project_galaxy_data.py' % SOURCE_DIR, 'rb') as f:
PROJECT_URL = get_var("PROJECT_URL")
PROJECT_AUTHOR = get_var("PROJECT_AUTHOR")
PROJECT_EMAIL = get_var("PROJECT_EMAIL")
PROJECT_DESCRIPTION = get_var("PROJECT_DESCRIPTION")
TEST_DIR = 'tests'
PROJECT_DESCRIPTION = 'Galaxy Datatype Framework and Datatypes'
PACKAGES = [
'galaxy',
'galaxy.datatypes',
@@ -77,6 +77,7 @@ setup(
version=version,
description=PROJECT_DESCRIPTION,
long_description=readme + '\n\n' + history,
long_description_content_type='text/x-rst',
author=PROJECT_AUTHOR,
author_email=PROJECT_EMAIL,
url=PROJECT_URL,
@@ -101,7 +102,6 @@ setup(
'Natural Language :: English',
"Programming Language :: Python :: 2",
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
+1 -1
View File
@@ -9,4 +9,4 @@ History
19.9.0.dev0
---------------------
* Initial import from dev branch of Galaxy during 19.09 release cycle.
* Initial import from dev branch of Galaxy during 19.09 development cycle.
+1
View File
@@ -0,0 +1 @@
../package.Makefile
+1
View File
@@ -0,0 +1 @@
../package-dev-requirements.txt
@@ -1,11 +1,12 @@
# -*- coding: utf-8 -*-
__version__ = '19.9.0.dev0'
__version__ = '19.9.0.dev1'
PROJECT_NAME = "galaxy-job-metrics"
PROJECT_OWNER = PROJECT_USERAME = "galaxyproject"
PROJECT_URL = "https://github.com/galaxyproject/galaxy"
PROJECT_AUTHOR = 'Galaxy Project and Community'
PROJECT_DESCRIPTION = 'Galaxy Job Metrics'
PROJECT_EMAIL = 'jmchilton@gmail.com'
RAW_CONTENT_URL = "https://raw.github.com/%s/%s/master/" % (
PROJECT_USERAME, PROJECT_NAME
+1
View File
@@ -0,0 +1 @@
../build_scripts
+3 -3
View File
@@ -26,13 +26,13 @@ with open('%s/project_galaxy_job_metrics.py' % SOURCE_DIR, 'rb') as f:
PROJECT_URL = get_var("PROJECT_URL")
PROJECT_AUTHOR = get_var("PROJECT_AUTHOR")
PROJECT_EMAIL = get_var("PROJECT_EMAIL")
PROJECT_DESCRIPTION = get_var("PROJECT_DESCRIPTION")
TEST_DIR = 'tests'
PROJECT_DESCRIPTION = 'Galaxy Job Metrics'
PACKAGES = [
'galaxy',
'galaxy.job_metrics',
'galaxy.job_metrics.instrumers',
'galaxy.job_metrics.instrumenters',
'galaxy.job_metrics.collectl',
]
ENTRY_POINTS = '''
@@ -67,6 +67,7 @@ setup(
version=version,
description=PROJECT_DESCRIPTION,
long_description=readme + '\n\n' + history,
long_description_content_type='text/x-rst',
author=PROJECT_AUTHOR,
author_email=PROJECT_EMAIL,
url=PROJECT_URL,
@@ -91,7 +92,6 @@ setup(
'Natural Language :: English',
"Programming Language :: Python :: 2",
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
+2 -2
View File
@@ -6,7 +6,7 @@ History
.. to_doc
---------------------
19.5.0.dev0
19.9.0.dev0
---------------------
* Initial import from dev branch of Galaxy during 19.05 release cycle.
* Initial import from dev branch of Galaxy during 19.09 development cycle.
+1
View File
@@ -0,0 +1 @@
../package.Makefile
+1
View File
@@ -0,0 +1 @@
../package-dev-requirements.txt
@@ -1,11 +1,12 @@
# -*- coding: utf-8 -*-
__version__ = '19.5.0.dev0'
__version__ = '19.9.0.dev1'
PROJECT_NAME = "galaxy-objectstore"
PROJECT_OWNER = PROJECT_USERAME = "galaxyproject"
PROJECT_URL = "https://github.com/galaxyproject/galaxy"
PROJECT_AUTHOR = 'Galaxy Project and Community'
PROJECT_DESCRIPTION = 'Galaxy Objectstore Framework and Plugins'
PROJECT_EMAIL = 'jmchilton@gmail.com'
RAW_CONTENT_URL = "https://raw.github.com/%s/%s/master/" % (
PROJECT_USERAME, PROJECT_NAME
+1
View File
@@ -0,0 +1 @@
../build_scripts
+2 -2
View File
@@ -26,9 +26,9 @@ with open('%s/project_galaxy_objectstore.py' % SOURCE_DIR, 'rb') as f:
PROJECT_URL = get_var("PROJECT_URL")
PROJECT_AUTHOR = get_var("PROJECT_AUTHOR")
PROJECT_EMAIL = get_var("PROJECT_EMAIL")
PROJECT_DESCRIPTION = get_var("PROJECT_DESCRIPTION")
TEST_DIR = 'tests'
PROJECT_DESCRIPTION = 'Galaxy Datatype Framework and Datatypes'
PACKAGES = [
'galaxy',
'galaxy.objectstore',
@@ -65,6 +65,7 @@ setup(
version=version,
description=PROJECT_DESCRIPTION,
long_description=readme + '\n\n' + history,
long_description_content_type='text/x-rst',
author=PROJECT_AUTHOR,
author_email=PROJECT_EMAIL,
url=PROJECT_URL,
@@ -89,7 +90,6 @@ setup(
'Natural Language :: English',
"Programming Language :: Python :: 2",
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
+9
View File
@@ -0,0 +1,9 @@
# For testing
pytest
# For dev
sphinx
# For release
wheel
twine
+89
View File
@@ -0,0 +1,89 @@
# Location of virtualenv used for development.
VENV?=.venv
# Open resource on Mac OS X or Linux
OPEN_RESOURCE=bash -c 'open $$0 || xdg-open $$0'
# Source virtualenv to execute command (flake8, sphinx, twine, etc...)
IN_VENV=if [ -f $(VENV)/bin/activate ]; then . $(VENV)/bin/activate; fi;
UPSTREAM?=galaxyproject
SOURCE_DIR?=galaxy
BUILD_SCRIPTS_DIR=scripts
DEV_RELEASE?=0
VERSION?=$(shell DEV_RELEASE=$(DEV_RELEASE) python $(BUILD_SCRIPTS_DIR)/print_version_for_release.py $(SOURCE_DIR) $(DEV_RELEASE))
PROJECT_NAME?="galaxy-$(shell basename $(CURDIR))"
PROJECT_NAME:=$(subst _,-,$(PROJECT_NAME))
TEST_DIR?=test
TESTS?=$(SOURCE_DIR) $(TEST_DIR)
.PHONY: clean-pyc clean-build docs clean
help:
@echo "clean - remove all build, test, coverage and Python artifacts"
@echo "clean-build - remove build artifacts"
@echo "clean-pyc - remove Python file artifacts"
@echo "clean-test - remove test and coverage artifacts"
@echo "setup-venv - setup a development virutalenv in current directory."
@echo "lint-dist - twine check dist results, including validating README content"
@echo "dist - package project for PyPI distribution"
clean: clean-build clean-pyc clean-tests
clean-build:
rm -fr build/
rm -fr dist/
rm -fr galaxy_*.egg-info
clean-pyc:
find . -name '*.pyc' -exec rm -f {} +
find . -name '*.pyo' -exec rm -f {} +
find . -name '*~' -exec rm -f {} +
find . -name '__pycache__' -exec rm -fr {} +
clean-tests:
rm -fr .tox/
setup-venv:
if [ ! -d $(VENV) ]; then virtualenv $(VENV); exit; fi;
$(IN_VENV) pip install -r requirements.txt && pip install -r dev-requirements.txt
test:
$(IN_VENV) pytest $(TESTS)
develop:
python setup.py develop
dist: clean
$(IN_VENV) python setup.py sdist bdist_wheel
ls -l dist
lint-dist: dist
$(IN_VENV) twine check dist/*
_release-test-artifacts:
$(IN_VENV) twine upload -r test dist/*
$(OPEN_RESOURCE) https://testpypi.python.org/pypi/$(PROJECT_NAME)
release-test-artifacts: lint-dist _release-test-artifacts
_release-artifacts:
@while [ -z "$$CONTINUE" ]; do \
read -r -p "Have you executed release-test and reviewed results? [y/N]: " CONTINUE; \
done ; \
[ $$CONTINUE = "y" ] || [ $$CONTINUE = "Y" ] || (echo "Exiting."; exit 1;)
@echo "Releasing"
$(IN_VENV) twine upload dist/*
release-artifacts: release-test-artifacts _release-artifacts
commit-version:
$(IN_VENV) DEV_RELEASE=$(DEV_RELEASE) python $(BUILD_SCRIPTS_DIR)/commit_version.py $(SOURCE_DIR) $(VERSION)
new-version:
$(IN_VENV) DEV_RELEASE=$(DEV_RELEASE) python $(BUILD_SCRIPTS_DIR)/new_version.py $(SOURCE_DIR) $(VERSION)
release-local: commit-version release-artifacts new-version
push-release:
git push $(UPSTREAM) dev
git push upstream $(UPSTREAM)/tags/galaxy-$(PROJECT_NAME)-$(VERSION)
release: release-local push-release
+1 -1
View File
@@ -9,4 +9,4 @@ History
19.9.0.dev0
---------------------
* Initial import from dev branch of Galaxy during 19.09 release cycle.
* Initial import from dev branch of Galaxy during 19.09 development cycle.
+1
View File
@@ -0,0 +1 @@
../package.Makefile
+1
View File
@@ -0,0 +1 @@
../package-dev-requirements.txt
@@ -1,11 +1,12 @@
# -*- coding: utf-8 -*-
__version__ = '19.9.0.dev0'
__version__ = '19.9.0.dev1'
PROJECT_NAME = "galaxy-tool-util"
PROJECT_OWNER = PROJECT_USERAME = "galaxyproject"
PROJECT_URL = "https://github.com/galaxyproject/galaxy"
PROJECT_AUTHOR = 'Galaxy Project and Community'
PROJECT_DESCRIPTION = 'Galaxy Tool and Tool Dependency Utilities'
PROJECT_EMAIL = 'jmchilton@gmail.com'
RAW_CONTENT_URL = "https://raw.github.com/%s/%s/master/" % (
PROJECT_USERAME, PROJECT_NAME
+1
View File
@@ -0,0 +1 @@
../build_scripts
+2 -2
View File
@@ -26,9 +26,9 @@ with open('%s/project_galaxy_tool_util.py' % SOURCE_DIR, 'rb') as f:
PROJECT_URL = get_var("PROJECT_URL")
PROJECT_AUTHOR = get_var("PROJECT_AUTHOR")
PROJECT_EMAIL = get_var("PROJECT_EMAIL")
PROJECT_DESCRIPTION = get_var("PROJECT_DESCRIPTION")
TEST_DIR = 'tests'
PROJECT_DESCRIPTION = 'Galaxy Tool Utilities'
PACKAGES = [
'galaxy',
'galaxy.tool_util',
@@ -79,6 +79,7 @@ setup(
version=version,
description=PROJECT_DESCRIPTION,
long_description=readme + '\n\n' + history,
long_description_content_type='text/x-rst',
author=PROJECT_AUTHOR,
author_email=PROJECT_EMAIL,
url=PROJECT_URL,
@@ -103,7 +104,6 @@ setup(
'Natural Language :: English',
"Programming Language :: Python :: 2",
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
+2 -2
View File
@@ -6,7 +6,7 @@ History
.. to_doc
---------------------
19.5.0.dev0
19.9.0.dev0
---------------------
* Initial import from dev branch of Galaxy during 19.05 release cycle.
* Initial import from dev branch of Galaxy during 19.09 development cycle.
+1
View File
@@ -0,0 +1 @@
../package.Makefile
+1
View File
@@ -0,0 +1 @@
../package-dev-requirements.txt
+2 -1
View File
@@ -1,11 +1,12 @@
# -*- coding: utf-8 -*-
__version__ = '19.5.0.dev0'
__version__ = '19.9.0.dev2'
PROJECT_NAME = "galaxy-util"
PROJECT_OWNER = PROJECT_USERAME = "galaxyproject"
PROJECT_URL = "https://github.com/galaxyproject/galaxy"
PROJECT_AUTHOR = 'Galaxy Project and Community'
PROJECT_DESCRIPTION = 'Galaxy Generic Utilities'
PROJECT_EMAIL = 'jmchilton@gmail.com'
RAW_CONTENT_URL = "https://raw.github.com/%s/%s/master/" % (
PROJECT_USERAME, PROJECT_NAME
+1
View File
@@ -0,0 +1 @@
../build_scripts
+3 -2
View File
@@ -26,11 +26,12 @@ with open('%s/project_galaxy_util.py' % SOURCE_DIR, 'rb') as f:
PROJECT_URL = get_var("PROJECT_URL")
PROJECT_AUTHOR = get_var("PROJECT_AUTHOR")
PROJECT_EMAIL = get_var("PROJECT_EMAIL")
PROJECT_DESCRIPTION = get_var("PROJECT_DESCRIPTION")
TEST_DIR = 'tests'
PROJECT_DESCRIPTION = 'Galaxy Datatype Framework and Datatypes'
PACKAGES = [
'galaxy',
'galaxy.exceptions',
'galaxy.util',
'galaxy.util.logging',
'galaxy.util.path',
@@ -69,6 +70,7 @@ setup(
version=version,
description=PROJECT_DESCRIPTION,
long_description=readme + '\n\n' + history,
long_description_content_type='text/x-rst',
author=PROJECT_AUTHOR,
author_email=PROJECT_EMAIL,
url=PROJECT_URL,
@@ -93,7 +95,6 @@ setup(
'Natural Language :: English',
"Programming Language :: Python :: 2",
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
+84 -27
View File
@@ -38,7 +38,7 @@ DEVTEAM = [
"davebx", "martenson", "jmchilton",
"tnabtaf", "natefoo", "jgoecks",
"guerler", "jennaj", "nekrut", "jxtx",
"VJalili"
"VJalili", "WilliamHolden", "Nerdinacan"
]
TEMPLATE = string.Template("""
@@ -143,15 +143,21 @@ Highlights
Feature description.
New Visualisations
New Visualizations
===========================================================
.. visualizations
New Datatypes
===========================================================
.. datatypes
Builtin Tool Updates
===========================================================
.. tools
Release Notes
===========================================================
@@ -174,6 +180,9 @@ Schedule
* Planned Release Date: ${release_date}
""")
PRS_TEMPLATE = """
.. github_links
"""
RELEASE_ISSUE_TEMPLATE = string.Template("""
@@ -337,7 +346,7 @@ def do_release(argv):
release=release_name
)
announce_file = _release_file(release_name + "_announce.rst")
open(announce_file, "w").write(announce_info.encode("utf-8"))
_write_file(announce_file, announce_info)
announce_user_info = ANNOUNCE_USER_TEMPLATE.substitute(
month_name=month_name,
@@ -345,7 +354,10 @@ def do_release(argv):
release=release_name
)
announce_user_file = _release_file(release_name + "_announce_user.rst")
open(announce_user_file, "w").write(announce_user_info.encode("utf-8"))
_write_file(announce_user_file, announce_user_info)
prs_file = _release_file(release_name + "_prs.rst")
_write_file(prs_file, PRS_TEMPLATE)
next_version_params = _next_version_params(release_name)
next_version = next_version_params["version"]
@@ -354,10 +366,9 @@ def do_release(argv):
next_announce = NEXT_TEMPLATE.substitute(**next_version_params)
open(next_release_file, "w").write(next_announce.encode("utf-8"))
releases_index = _release_file("index.rst")
releases_index_contents = open(releases_index, "r").read()
releases_index_contents = _read_file(releases_index)
releases_index_contents = releases_index_contents.replace(".. announcements\n", ".. announcements\n " + next_version + "_announce\n")
with open(releases_index, "w") as f:
f.write(releases_index_contents)
_write_file(releases_index, releases_index_contents)
for pr in _get_prs(release_name):
# 2015-06-29 18:32:13 2015-04-22 19:11:53 2015-08-12 21:15:45
@@ -365,15 +376,16 @@ def do_release(argv):
"title": pr.title,
"number": pr.number,
"head": pr.head,
"labels": _pr_to_labels(pr),
}
main([argv[0], "--release_file", "%s_prs.rst" % release_name, "--request", as_dict, "pr" + str(pr.number)])
main([argv[0], "--release_file", "%s.rst" % release_name, "--request", as_dict, "pr" + str(pr.number)])
def check_release(argv):
github = _github_client()
release_name = argv[2]
for pr in _get_prs(release_name):
_text_target(github, pr)
_text_target(github, pr, labels=_pr_to_labels(pr))
def check_blocking_prs(argv):
@@ -451,8 +463,16 @@ def _get_prs(release_name, state="closed"):
user=PROJECT_OWNER,
repo=PROJECT_NAME,
)
reached_old_prs = False
for page in pull_requests:
if reached_old_prs:
break
for pr in page:
if pr.created_at < datetime.datetime(2016, 11, 1, 0, 0):
reached_old_prs = True
pass
merged_at = pr.merged_at
milestone = pr.milestone
proper_state = state != "closed" or merged_at
@@ -504,10 +524,15 @@ def main(argv):
if newest_release is None:
newest_release = sorted(os.listdir(RELEASES_PATH))[-1]
history_path = os.path.join(RELEASES_PATH, newest_release)
history = open(history_path, "r").read().decode("utf-8")
user_announce_path = history_path[0:-len(".rst")] + "_announce_user.rst"
prs_path = history_path[0:-len(".rst")] + "_prs.rst"
def extend(from_str, line, source=history):
from_str += "\n"
history = _read_file(history_path)
user_announce = _read_file(user_announce_path)
prs_content = _read_file(prs_path)
def extend_target(target, line, source=history):
from_str = ".. %s\n" % target
return source.replace(from_str, from_str + line + "\n")
ident = argv[1]
@@ -548,48 +573,72 @@ def main(argv):
if owner in DEVTEAM:
owner = None
text = ".. _Pull Request {0}: {1}/pull/{0}".format(pull_request, PROJECT_URL)
history = extend(".. github_links", text)
prs_content = extend_target("github_links", text, prs_content)
if owner:
to_doc += "\n(thanks to `@%s <https://github.com/%s>`__)." % (
owner, owner,
)
to_doc += "\n`Pull Request {0}`_".format(pull_request)
if github:
text_target = _text_target(github, pull_request)
labels = None
if req and 'labels' in req:
labels = req['labels']
text_target = _text_target(github, pull_request, labels=labels)
elif ident.startswith("issue"):
issue = ident[len("issue"):]
text = ".. _Issue {0}: {1}/issues/{0}".format(issue, PROJECT_URL)
history = extend(".. github_links", text)
prs_content = extend_target("github_links", text, prs_content)
to_doc += "`Issue {0}`_".format(issue)
else:
short_rev = ident[:7]
text = ".. _{0}: {1}/commit/{0}".format(short_rev, PROJECT_URL)
history = extend(".. github_links", text)
prs_content = extend_target("github_links", text, prs_content)
to_doc += "{0}_".format(short_rev)
to_doc = wrap(to_doc)
history = extend(".. %s\n" % text_target, to_doc, history)
open(history_path, "w").write(history.encode("utf-8"))
history = extend_target(text_target, to_doc, history)
if req and 'labels' in req:
labels = req['labels']
if 'area/datatypes' in labels:
user_announce = extend_target("datatypes", to_doc, user_announce)
if 'area/visualizations' in labels:
user_announce = extend_target("visualizations", to_doc, user_announce)
if 'area/tools' in labels:
user_announce = extend_target("tools", to_doc, user_announce)
_write_file(history_path, history)
_write_file(prs_path, prs_content)
_write_file(user_announce_path, user_announce)
def _text_target(github, pull_request):
labels = []
def _read_file(path):
with open(path, "r") as f:
return f.read().decode("utf-8")
def _write_file(path, contents):
with open(path, "w") as f:
f.write(contents.encode("utf-8"))
def _text_target(github, pull_request, labels=None):
pr_number = None
if isinstance(pull_request, string_types):
pr_number = pull_request
else:
pr_number = pull_request.number
try:
labels = github.issues.labels.list_by_issue(int(pr_number), user=PROJECT_OWNER, repo=PROJECT_NAME)
except Exception as e:
print(e)
if labels is None:
labels = []
try:
labels = github.issues.labels.list_by_issue(int(pr_number), user=PROJECT_OWNER, repo=PROJECT_NAME)
labels = [l.name.lower() for l in labels]
except Exception as e:
print(e)
is_bug = is_enhancement = is_feature = is_minor = is_major = is_merge = is_small_enhancement = False
if len(labels) == 0:
print('No labels found for %s' % pr_number)
return None
for label in labels:
label_name = label.name.lower()
for label_name in labels:
if label_name == "minor":
is_minor = True
elif label_name == "major":
@@ -604,11 +653,14 @@ def _text_target(github, pull_request):
is_enhancement = True
elif label_name in ["kind/testing", "kind/refactoring"]:
is_small_enhancement = True
elif label_name == "procedures":
# Treat procedures as an implicit enhancement.
is_enhancement = True
is_some_kind_of_enhancement = is_enhancement or is_feature or is_small_enhancement
if not(is_bug or is_some_kind_of_enhancement or is_minor or is_merge):
print("No kind/ or minor or merge label found for %s" % _pr_to_str(pull_request))
print("No 'kind/*' or 'minor' or 'merge' or 'procedures' label found for %s" % _pr_to_str(pull_request))
text_target = None
if is_minor or is_merge:
@@ -632,6 +684,11 @@ def _text_target(github, pull_request):
return text_target
def _pr_to_labels(pr):
labels = [l["name"].lower() for l in pr.labels]
return labels
def _previous_release(to):
previous_release = None
for release in _releases():
+31 -32
View File
@@ -17,8 +17,8 @@ import os
import sys
from optparse import OptionParser
from mercurial import hg, ui
from six.moves import configparser
from whoosh.fields import Schema, STORED, TEXT
from whoosh.filedb.filestore import FileStorage
sys.path.insert(1, os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, 'lib')))
@@ -31,38 +31,17 @@ from galaxy.util import (
unicodify
)
from galaxy.webapps.tool_shed import config, model
from galaxy.webapps.tool_shed.search.repo_search import schema as repo_schema
from galaxy.webapps.tool_shed.search.tool_search import schema as tool_schema
from galaxy.webapps.tool_shed.util.hgweb_config import HgWebConfigManager
if sys.version_info > (3,):
long = int
logging.basicConfig(level='DEBUG')
repo_schema = Schema(
id=STORED,
name=TEXT(stored=True),
description=TEXT(stored=True),
long_description=TEXT(stored=True),
homepage_url=TEXT(stored=True),
remote_repository_url=TEXT(stored=True),
repo_owner_username=TEXT(stored=True),
times_downloaded=STORED,
approved=STORED,
last_updated=STORED,
full_last_updated=STORED)
tool_schema = Schema(
name=TEXT(stored=True),
description=TEXT(stored=True),
owner=TEXT(stored=True),
id=TEXT(stored=True),
help=TEXT(stored=True),
version=TEXT(stored=True),
repo_name=TEXT(stored=True),
repo_owner_username=TEXT(stored=True),
repo_id=STORED)
def build_index(sa_session, whoosh_index_dir, path_to_repositories):
def build_index(sa_session, whoosh_index_dir, path_to_repositories, hgweb_config_dir):
"""
Build the search indexes. One for repositories and another for tools within.
"""
@@ -85,7 +64,7 @@ def build_index(sa_session, whoosh_index_dir, path_to_repositories):
repos_indexed = 0
tools_indexed = 0
for repo in get_repos(sa_session, path_to_repositories):
for repo in get_repos(sa_session, path_to_repositories, hgweb_config_dir):
repo_index_writer.add_document(id=repo.get('id'),
name=unicodify(repo.get('name')),
@@ -94,10 +73,12 @@ def build_index(sa_session, whoosh_index_dir, path_to_repositories):
homepage_url=unicodify(repo.get('homepage_url')),
remote_repository_url=unicodify(repo.get('remote_repository_url')),
repo_owner_username=unicodify(repo.get('repo_owner_username')),
categories=unicodify(repo.get('categories')),
times_downloaded=repo.get('times_downloaded'),
approved=repo.get('approved'),
last_updated=repo.get('last_updated'),
full_last_updated=repo.get('full_last_updated'))
full_last_updated=repo.get('full_last_updated'),
repo_lineage=unicodify(repo.get('repo_lineage')))
# Tools get their own index
for tool in repo.get('tools_list'):
tool_index_writer.add_document(id=unicodify(tool.get('id')),
@@ -121,13 +102,19 @@ def build_index(sa_session, whoosh_index_dir, path_to_repositories):
print("TOTAL tools indexed: ", tools_indexed)
def get_repos(sa_session, path_to_repositories):
def get_repos(sa_session, path_to_repositories, hgweb_config_dir):
"""
Load repos from DB and included tools from .xml configs.
"""
hgwcm = HgWebConfigManager()
hgwcm.hgweb_config_dir = hgweb_config_dir
results = []
for repo in sa_session.query(model.Repository).filter_by(deleted=False).filter_by(deprecated=False).filter(model.Repository.type != 'tool_dependency_definition'):
category_names = []
for rca in sa_session.query(model.RepositoryCategoryAssociation).filter(model.RepositoryCategoryAssociation.repository_id == repo.id):
for category in sa_session.query(model.Category).filter(model.Category.id == rca.category.id):
category_names.append(category.name)
categories = (",").join(category_names)
repo_id = repo.id
name = repo.name
description = repo.description
@@ -154,6 +141,14 @@ def get_repos(sa_session, path_to_repositories):
last_updated = pretty_print_time_interval(repo.update_time)
full_last_updated = repo.update_time.strftime("%Y-%m-%d %I:%M %p")
# load all changesets of the repo
repo_path = hgwcm.get_entry(os.path.join("repos", repo.user.username, repo.name))
hg_repo = hg.repository(ui.ui(), repo_path)
lineage = []
for changeset in hg_repo.changelog:
lineage.append(str(changeset) + ":" + str(hg_repo.changectx(changeset)))
repo_lineage = str(lineage)
# Parse all the tools within repo for separate index.
tools_list = []
path = os.path.join(path_to_repositories, *directory_hash_id(repo.id))
@@ -178,7 +173,9 @@ def get_repos(sa_session, path_to_repositories):
approved=approved,
last_updated=last_updated,
full_last_updated=full_last_updated,
tools_list=tools_list))
tools_list=tools_list,
repo_lineage=repo_lineage,
categories=categories))
return results
@@ -218,9 +215,11 @@ def get_sa_session_and_needed_config_settings(path_to_tool_shed_config):
if __name__ == "__main__":
parser = OptionParser()
parser.add_option("-c", "--config", dest="path_to_tool_shed_config", default="config/tool_shed.ini", help="specify tool_shed.ini location")
parser.add_option("-r", "--hgweb", dest="hgweb_config_dir", default=".", help="specify hgweb.config location")
(options, args) = parser.parse_args()
path_to_tool_shed_config = options.path_to_tool_shed_config
hgweb_config_dir = options.hgweb_config_dir
sa_session, config_settings = get_sa_session_and_needed_config_settings(path_to_tool_shed_config)
whoosh_index_dir = config_settings.get('whoosh_index_dir', None)
path_to_repositories = config_settings.get('file_path', 'database/community_files')
build_index(sa_session, whoosh_index_dir, path_to_repositories)
build_index(sa_session, whoosh_index_dir, path_to_repositories, hgweb_config_dir)
+3
View File
@@ -1,3 +1,6 @@
[wheel]
universal = 1
[flake8]
# These are exceptions allowed by Galaxy style guidelines.
# E128 continuation line under-indented for visual indent
+5 -5
View File
@@ -1,5 +1,5 @@
FROM ubuntu:16.04
MAINTAINER John Chilton <jmchilton@gmail.com>
LABEL maintainer="John Chilton <jmchilton@gmail.com>"
ARG CHROME_VERSION="google-chrome-beta"
ARG CHROME_DRIVER_VERSION="2.38"
@@ -79,7 +79,7 @@ RUN cd $GALAXY_ROOT && \
RUN for VENV in $GALAXY_VIRTUAL_ENV_3 $GALAXY_VIRTUAL_ENV_2; do \
export GALAXY_VIRTUAL_ENV=$VENV && \
. $GALAXY_VIRTUAL_ENV/bin/activate && \
pip install psycopg2; done && \
pip install psycopg2-binary; done && \
cd $GALAXY_ROOT && \
echo "Prepopulating postgres database" && \
su -c '/usr/lib/postgresql/${POSTGRES_MAJOR}/bin/pg_ctl -o "-F" start -D /opt/galaxy/db' postgres && \
@@ -156,8 +156,8 @@ USER root
ADD run_test_wrapper.sh /usr/local/bin/run_test_wrapper.sh
EXPOSE :9009
EXPOSE :8080
EXPOSE :80
EXPOSE 9009
EXPOSE 8080
EXPOSE 80
ENTRYPOINT ["/bin/bash", "/usr/local/bin/run_test_wrapper.sh"]
+5 -1
View File
@@ -45,7 +45,11 @@ class TestCommandFactory(TestCase):
self.include_work_dir_outputs = False
dep_commands = [". /opt/galaxy/tools/bowtie/default/env.sh"]
self.job_wrapper.dependency_shell_commands = dep_commands
self.__assert_command_is(_surround_command("%s/tool_script.sh > ../tool_stdout 2> ../tool_stderr; return_code=$?" % self.job_wrapper.working_directory))
self.__assert_command_is(_surround_command(
"%s %s/tool_script.sh > ../tool_stdout 2> ../tool_stderr; return_code=$?" % (
self.job_wrapper.shell,
self.job_wrapper.working_directory,
)))
self.__assert_tool_script_is("#!/bin/sh\n%s; %s" % (dep_commands[0], MOCK_COMMAND_LINE))
def test_remote_dependency_resolution(self):