(merge dev); Testing, histories: update tests to reflect allowing anon to create/copy histories via the API

This commit is contained in:
carlfeberhard
2015-12-11 13:44:48 -05:00
69 changed files with 583 additions and 381 deletions
+19
View File
@@ -0,0 +1,19 @@
GRUNT_DOCKER_NAME:=galaxy/client-builder:16.01
all:
@echo "This makefile is primarily used for building Galaxy's JS client. A sensible all target is not yet implemented."
npm-deps:
cd client && npm install
grunt: npm-deps
cd client && grunt
grunt-docker-image:
docker build -t ${GRUNT_DOCKER_NAME} client
grunt-docker: grunt-docker-image
docker run -it -v `pwd`:/data ${GRUNT_DOCKER_NAME}
clean-grunt-docker-image:
docker rmi ${GRUNT_DOCKER_NAME}
+4
View File
@@ -0,0 +1,4 @@
#!/bin/bash
cd /data/client && \
npm install && \
grunt
+13
View File
@@ -0,0 +1,13 @@
FROM digitallyseamless/nodejs-bower-grunt
RUN mkdir /gx
COPY package.json /gx/package.json
RUN cd /gx && \
npm install -g && \
cd / && \
rm -rf /gx
WORKDIR /data/client
ADD ./.docker-build.sh /build.sh
CMD ["/build.sh"]
+2 -1
View File
@@ -151,7 +151,8 @@ window.app = function app( options, bootstrapped ){
// page render. It's re-created each time because there is no render function and can't be re-rendered without
// re-creating it.
Galaxy.listenTo( analysisPage.right.historyView, 'history-size-change', function(){
Galaxy.user.fetch();
// fetch to update the quota meter adding 'current' for any anon-user's id
Galaxy.user.fetch({ url: Galaxy.user.urlRoot() + '/' + ( Galaxy.user.id || 'current' ) });
});
analysisPage.right.historyView.connectToQuotaMeter( analysisPage.masthead.quotaMeter );
+1 -1
View File
@@ -66,7 +66,7 @@ var SessionStorageModel = Backbone.Model.extend({
_checkEnabledSessionStorage : function(){
try {
return sessionStorage.length;
return window.sessionStorage.length >= 0;
} catch( err ){
alert( 'Please enable cookies in your browser for this Galaxy site' );
return false;
@@ -2,7 +2,7 @@ define([
"libs/bibtex",
"mvc/base-mvc",
"utils/localization"
], function( bibtex, baseMVC, _l ){
], function( BibtexParser, baseMVC, _l ){
/* global Backbone */
var logNamespace = 'citation';
@@ -14,9 +14,9 @@ var logNamespace = 'citation';
var Citation = Backbone.Model.extend( baseMVC.LoggableMixin ).extend( {
_logNamespace : logNamespace,
initialize: function( ) {
var bibtex = this.attributes.content;
var entry = new bibtex.BibtexParser(bibtex).entries[0];
initialize: function() {
var bibtex = this.get( 'content' );
var entry = BibtexParser(bibtex).entries[0];
this.entry = entry;
this._fields = {};
var rawFields = entry.Fields;
@@ -61,6 +61,7 @@ var ToolCitationCollection = BaseCitationCollection.extend( {
partial : false, // If a tool has citations, assume they are complete.
} );
//==============================================================================
return {
Citation : Citation,
@@ -30,6 +30,7 @@ var View = Backbone.View.extend({
// link elements
this.$select = this.$el.find('.select');
this.$icon_dropdown = this.$el.find('.icon-dropdown');
this.$icon_dropdown.on( 'click', function() { self.$select.select2 && self.$select.select2( 'open' ) });
// allow regular multi-select field to be resized
var minHeight = null;
@@ -1,4 +1,8 @@
define(['mvc/workflow/workflow-connector'], function( Connector ) {
define([
'mvc/workflow/workflow-connector',
'libs/toastr'
],
function( Connector, Toastr ) {
function Workflow( app, canvas_container ) {
this.app = app;
this.canvas_container = canvas_container;
@@ -7,10 +11,49 @@ define(['mvc/workflow/workflow-connector'], function( Connector ) {
this.name = null;
this.has_changes = false;
this.active_form_has_changes = false;
this.nodeLabels = {}; // TODO: track and enforce output labels also
}
$.extend( Workflow.prototype, {
create_node: function ( type, title_text, tool_id ) {
var node = this.app.prebuildNode( type, title_text, tool_id );
canLabelNodeWith: function( label ) {
if( label ) {
return ! (label in this.nodeLabels);
} else {
// empty labels are non-exclusive, so allow this one.
return true;
}
},
registerNodeLabel: function( label ) {
if( label ) {
this.nodeLabels[label] = true;
}
},
unregisterNodeLabel: function( label ) {
if( label ) {
delete this.nodeLabels[label];
}
},
updateNodeLabel: function( fromLabel, toLabel ) {
if( fromLabel ) {
this.unregisterNodeLabel( fromLabel );
}
if( ! this.canLabelNodeWith( toLabel ) ) {
Toastr.warning("Workflow contains duplicate node labels " + toLabel + ". This must be fixed before it can be saved.");
}
if( toLabel ) {
this.registerNodeLabel( toLabel );
}
},
attemptUpdateNodeLabel: function( node, label ) {
if( this.canLabelNodeWith( label ) ) {
node.setLabel( label );
return true;
} else {
return false;
}
},
create_node: function ( type, title_text, content_id ) {
var node = this.app.prebuildNode( type, title_text, content_id );
this.add_node( node );
this.fit_canvas_to_nodes();
this.app.canvas_manager.draw_overview();
@@ -131,7 +174,7 @@ define(['mvc/workflow/workflow-connector'], function( Connector ) {
var node_data = {
id : node.id,
type : node.type,
tool_id : node.tool_id,
tool_id : node.content_id,
tool_state : node.tool_state,
tool_errors : node.tool_errors,
input_connections : input_connections,
@@ -383,4 +426,4 @@ define(['mvc/workflow/workflow-connector'], function( Connector ) {
}
});
return Workflow;
});
});
@@ -124,6 +124,10 @@ define(['mvc/workflow/workflow-view-node'], function( NodeView ) {
// Remove active class
$(element).removeClass( "toolForm-active" );
},
setLabel: function(label) {
this.app.workflow.updateNodeLabel(this.label, label);
this.label = label || null;
},
init_field_data : function ( data ) {
if ( data.type ) {
this.type = data.type;
@@ -135,7 +139,7 @@ define(['mvc/workflow/workflow-view-node'], function( NodeView ) {
this.tooltip = data.tooltip ? data.tooltip : "";
this.annotation = data.annotation;
this.post_job_actions = data.post_job_actions ? data.post_job_actions : {};
this.label = data.label;
this.setLabel(data.label);
this.uuid = data.uuid;
this.workflow_outputs = data.workflow_outputs ? data.workflow_outputs : [];
@@ -165,6 +169,8 @@ define(['mvc/workflow/workflow-view-node'], function( NodeView ) {
this.form_html = data.form_html;
this.tool_errors = data.tool_errors;
this.annotation = data['annotation'];
this.setLabel(data.label);
if( "post_job_actions" in data ) {
// Won't be present in response for data inputs
var pja_in = $.parseJSON(data.post_job_actions);
@@ -184,6 +190,7 @@ define(['mvc/workflow/workflow-view-node'], function( NodeView ) {
unusedView.el.terminal.destroy();
} );
nodeView.terminalViews = newTerminalViews;
node.nodeView.render();
// In general workflow editor assumes tool outputs don't change in # or
// type (not really valid right?) but adding special logic here for
// data collection input parameters that can have their collection
@@ -11,6 +11,14 @@ define(['mvc/workflow/workflow-view-terminals', 'mvc/workflow/workflow-view-data
},
render: function() {
var label = this.node.label;
var title;
if(label) {
title = label;
} else {
title = this.node.name;
}
this.$el.find(".nodeTitle").text(title);
this.renderToolErrors();
this.$el.css( "width", Math.min(250, Math.max( this.$el.width(), this.output_width )));
},
@@ -7,7 +7,9 @@ define([
'mvc/workflow/workflow-node',
'mvc/tool/tools-form-workflow',
'utils/async-save-text',
], function( Utils, Globals, Workflow, WorkflowCanvas, Node, ToolsForm, async_save_text ){
'libs/toastr',
'ui/editable-text'
], function( Utils, Globals, Workflow, WorkflowCanvas, Node, ToolsForm, async_save_text, Toastr ){
// Reset tool search to start state.
function reset_tool_search( initValue ) {
@@ -44,6 +46,21 @@ function reset_tool_search( initValue ) {
}
}
NODE_ICONS = {
'tool': 'fa-wrench',
'data_input': 'fa-file-o',
'data_collection_input': 'fa-folder-o',
'pause': 'fa-pause'
}
add_node_icon = function($to_el, nodeType) {
var iconStyle = NODE_ICONS[nodeType];
if(iconStyle) {
var $icon = $('<i class="icon fa">&nbsp;</i>').addClass(iconStyle);
$to_el.before($icon);
}
}
// Really a shell of a real backbone view, but refactoring in the right
// direction I think.
@@ -61,7 +78,33 @@ EditorFormView = Backbone.View.extend({
this.setElement($el);
if (node && node.id != 'no-node') {
$el.find('.toolForm:first').after(this._genericStepAttributesTemplate( node ));
$el.find('table:first').after(this._genericStepAttributesTemplate( node ));
var nodeType = node.type;
add_node_icon($el.find('.portlet-title-text'), nodeType);
var $titleText = $el.find(".portlet-title-text");
$titleText.data('last-value', $titleText.text());
$titleText.make_text_editable({
on_finish: function( newLabel ){
var lastValue = $titleText.data("last-value");
if( newLabel == lastValue ) {
return;
}
var workflow = workflowView.workflow;
if( workflow.attemptUpdateNodeLabel( node, newLabel ) ) {
$el.find("input[name='label']").val(newLabel);
$titleText.data("last-value", newLabel);
$el.find('form').submit();
if(newLabel == "") {
// If label unset restore default name as title.
$titleText.text(node.name);
}
} else {
Toastr.warning("Step label " + newLabel + " already exists, cannot update label.");
$titleText.text(lastValue);
}
}
});
($el.find( 'form' ).length > 0) && $el.find( 'form' ).ajaxForm( {
type: 'POST',
dataType: 'json',
@@ -525,12 +568,10 @@ EditorFormView = Backbone.View.extend({
cc.css( { left: left, top: top } );
},
// Add a new step to the workflow by tool id
add_node_for_tool: function ( id, title ) {
node = this.workflow.create_node( 'tool', title, id );
_moduleInitAjax: function(node, request_data) {
$.ajax( {
url: this.urls.get_new_module_info,
data: { type: "tool", tool_id: id, "_": "true" },
data: request_data,
global: false,
dataType: "json",
success: function( data ) {
@@ -546,23 +587,21 @@ EditorFormView = Backbone.View.extend({
});
},
// Add a new step to the workflow by tool id
add_node_for_tool: function ( id, title ) {
node = this.workflow.create_node( 'tool', title, id );
this._moduleInitAjax(node, { type: "tool", content_id: id, "_": "true" });
},
// Add a new step to the workflow by tool id
add_node_for_subworkflow: function ( id, title ) {
node = this.workflow.create_node( 'subworkflow', title, id );
this._moduleInitAjax(node, { type: "subworkflow", subworkflow_id: id, "_": "true" });
},
add_node_for_module: function ( type, title ) {
node = this.workflow.create_node( type, title );
$.ajax( {
url: this.urls.get_new_module_info,
data: { type: type, "_": "true" },
dataType: "json",
success: function( data ) {
node.init_field_data( data );
},
error: function( x, e ) {
var m = "error loading field data"
if ( x.status == 0 ) {
m += ", server unavailable"
}
node.error( m );
}
});
this._moduleInitAjax(node, { type: type, "_": "true" });
},
// This function preloads how to display known pja's.
@@ -704,22 +743,27 @@ EditorFormView = Backbone.View.extend({
return ( this.type_to_type[child] ) && ( parent in this.type_to_type[child] );
},
prebuildNode: function ( type, title_text, tool_id ) {
$newNodeElement: function(type, title_text) {
var $f = $("<div class='toolForm toolFormInCanvas'></div>");
var $title = $("<div class='toolFormTitle unselectable'><span class='nodeTitle'>" + title_text + "</div></div>" );
add_node_icon($title.find('.nodeTitle'), type);
$f.append( $title );
$f.css( "left", $(window).scrollLeft() + 20 );
$f.css( "top", $(window).scrollTop() + 20 );
var $b = $("<div class='toolFormBody'></div>");
$f.append($b);
return $f
},
prebuildNode: function ( type, title_text, content_id ) {
var self = this;
var f = $("<div class='toolForm toolFormInCanvas'></div>");
var node = new Node( this, { element: f } );
var $f = this.$newNodeElement( type, title_text );
var node = new Node( this, { element: $f } );
node.type = type;
if ( type == 'tool' ) {
node.tool_id = tool_id;
}
var title = $("<div class='toolFormTitle unselectable'>" + title_text + "</div>" );
f.append( title );
f.css( "left", $(window).scrollLeft() + 20 ); f.css( "top", $(window).scrollTop() + 20 );
var b = $("<div class='toolFormBody'></div>");
node.content_id = content_id;
var tmp = "<div><img height='16' align='middle' src='" + Galaxy.root + "static/images/loading_small_white_bg.gif'/> loading tool info...</div>";
b.append( tmp );
$f.find(".toolFormBody").append(tmp);
node.form_html = tmp;
f.append( b );
// Fix width to computed width
// Now add floats
var buttons = $("<div class='buttons' style='float: right;'></div>");
@@ -727,17 +771,17 @@ EditorFormView = Backbone.View.extend({
node.destroy();
}));
// Place inside container
f.appendTo( "#canvas-container" );
$f.appendTo( "#canvas-container" );
// Position in container
var o = $("#canvas-container").position();
var p = $("#canvas-container").parent();
var width = f.width();
var height = f.height();
f.css( { left: ( - o.left ) + ( p.width() / 2 ) - ( width / 2 ), top: ( - o.top ) + ( p.height() / 2 ) - ( height / 2 ) } );
buttons.prependTo( title );
var width = $f.width();
var height = $f.height();
$f.css( { left: ( - o.left ) + ( p.width() / 2 ) - ( width / 2 ), top: ( - o.top ) + ( p.height() / 2 ) - ( height / 2 ) } );
buttons.prependTo( $f.find(".toolFormTitle" ) );
width += ( buttons.width() + 10 );
f.css( "width", width );
$(f).bind( "dragstart", function() {
$f.css( "width", width );
$f.bind( "dragstart", function() {
self.workflow.activate_node( node );
}).bind( "dragend", function() {
self.workflow.node_changed( this );
+4 -4
View File
@@ -51,17 +51,17 @@
};
// ------------------------------------------------------------------ can't/won't polyfill
var incompatibilities = [
var features = [
{ name: 'canvas', compatible: function(){ return window.CanvasRenderingContext2D; } },
{ name: 'sessionStorage', compatible: function(){
try {
return Number.isInteger( sessionStorage.length );
return window.sessionStorage.length >= 0;
} catch( err ){}
return false;
}},
];
// build a list of feature names for features that were not found
incompatibilities = incompatibilities
var incompatibilities = features
.filter( function( feature ){ return !feature.compatible(); })
.map( function( feature ){ return feature.name; });
@@ -69,7 +69,7 @@
if( !!incompatibilities.length ){
var root = document.querySelectorAll( 'link[rel="index"]' ).item( 0 );
if( root ){
window.location.href = root.href + 'static/incompatible-browser.html';
window.location = root.href + 'static/incompatible-browser.html';
}
console.log( 'incompatible browser:\n' + incompatibilities.join( '\n' ) );
}
+1
View File
@@ -578,6 +578,7 @@
position: absolute;
top: 8px;
right: 8px;
cursor: pointer;
}
.icon-resize {
display: none;
+13
View File
@@ -10,3 +10,16 @@ to provide relatively concrete answers for specific Galaxy development scenarios
This can be done with either IPython/Jupyter or a plain python console, depending on your preferences::
python -i scripts/db_shell.py
... build Galaxy Javascript frontend client?
--------------------------------------------
We've added a makefile which will let you do this. If you have nodejs and npm installed, you can simple run::
make grunt
If you prefer docker and aren't a JS developer primarily, you can run
make grunt-docker
+68 -15
View File
@@ -11,7 +11,7 @@ import subprocess
import tempfile
from galaxy.datatypes.data import get_file_peek, Text
from galaxy.datatypes.metadata import MetadataElement
from galaxy.datatypes.metadata import MetadataElement, MetadataParameter
from galaxy.util import nice_size, string_as_bool
log = logging.getLogger(__name__)
@@ -122,45 +122,98 @@ class Ipynb( Json ):
pass
class Biom1(Json):
class Biom1( Json ):
"""
BIOM version 1.0 file format description
http://biom-format.org/documentation/format_versions/biom-1.0.html
"""
file_ext = "biom1"
def set_peek(self, dataset, is_multi_byte=False):
super(Biom1, self).set_peek(dataset, is_multi_byte)
MetadataElement( name="table_rows", default=[], desc="table_rows", param=MetadataParameter, readonly=True, visible=False, optional=True, no_value=[] )
MetadataElement( name="table_matrix_element_type", default="", desc="table_matrix_element_type", param=MetadataParameter, readonly=True, visible=False, optional=True, no_value="" )
MetadataElement( name="table_format", default="", desc="table_format", param=MetadataParameter, readonly=True, visible=False, optional=True, no_value="" )
MetadataElement( name="table_generated_by", default="", desc="table_generated_by", param=MetadataParameter, readonly=True, visible=True, optional=True, no_value="" )
MetadataElement( name="table_matrix_type", default="", desc="table_matrix_type", param=MetadataParameter, readonly=True, visible=False, optional=True, no_value="" )
MetadataElement( name="table_shape", default=[], desc="table_shape", param=MetadataParameter, readonly=True, visible=False, optional=True, no_value=[] )
MetadataElement( name="table_format_url", default="", desc="table_format_url", param=MetadataParameter, readonly=True, visible=False, optional=True, no_value="" )
MetadataElement( name="table_date", default="", desc="table_date", param=MetadataParameter, readonly=True, visible=True, optional=True, no_value="" )
MetadataElement( name="table_type", default="", desc="table_type", param=MetadataParameter, readonly=True, visible=True, optional=True, no_value="" )
MetadataElement( name="table_id", default=None, desc="table_id", param=MetadataParameter, readonly=True, visible=True, optional=True, no_value=None )
MetadataElement( name="table_columns", default=[], desc="table_columns", param=MetadataParameter, readonly=True, visible=False, optional=True, no_value=[] )
def set_peek( self, dataset, is_multi_byte=False ):
super( Biom1, self ).set_peek( dataset, is_multi_byte )
if not dataset.dataset.purged:
dataset.blurb = "Biological Observation Matrix v1"
def sniff(self, filename):
def sniff( self, filename ):
is_biom = False
if self._looks_like_json( filename ):
is_biom = self._looks_like_biom(filename)
is_biom = self._looks_like_biom( filename )
return is_biom
def _looks_like_biom(self, filepath, load_size=50000):
def _looks_like_biom( self, filepath, load_size=50000 ):
"""
@param filepath: [str] The path to the evaluated file.
@param load_size: [int] The size of the file block load in RAM (in
bytes).
"""
is_biom = False
segment_size = int(load_size / 2)
segment_size = int( load_size / 2 )
try:
with open(filepath, "r") as fh:
with open( filepath, "r" ) as fh:
prev_str = ""
segment_str = fh.read(segment_size)
if segment_str.strip().startswith('{'):
while segment_str and not is_biom:
segment_str = fh.read( segment_size )
if segment_str.strip().startswith( '{' ):
while segment_str:
current_str = prev_str + segment_str
if '"format"' in current_str:
current_str = re.sub(r'\s', '', current_str)
current_str = re.sub( r'\s', '', current_str )
if '"format":"BiologicalObservationMatrix' in current_str:
is_biom = True
break
prev_str = segment_str
segment_str = fh.read(segment_size)
except:
segment_str = fh.read( segment_size )
except Exception:
pass
return is_biom
def set_meta( self, dataset, **kwd ):
"""
Store metadata information from the BIOM file.
"""
if dataset.has_data():
with open( dataset.file_name ) as fh:
try:
json_dict = json.load( fh )
except Exception:
return
def _transform_dict_list_ids( dict_list ):
if dict_list:
return [ x.get( 'id', None ) for x in dict_list ]
return []
b_transform = { 'rows': _transform_dict_list_ids, 'columns': _transform_dict_list_ids }
for ( m_name, b_name ) in [ ('table_rows', 'rows'),
('table_matrix_element_type', 'matrix_element_type'),
('table_format', 'format'),
('table_generated_by', 'generated_by'),
('table_matrix_type', 'matrix_type'),
('table_shape', 'shape'),
('table_format_url', 'format_url'),
('table_date', 'date'),
('table_type', 'type'),
('table_id', 'id'),
('table_columns', 'columns') ]:
try:
metadata_value = json_dict.get( b_name, None )
if b_name in b_transform:
metadata_value = b_transform[ b_name ]( metadata_value )
setattr( dataset.metadata, m_name, metadata_value )
except Exception:
pass
class Obo( Text ):
"""
+11 -5
View File
@@ -112,6 +112,16 @@ def get_class( class_name ):
return item_class
def decode_id(app, id):
try:
# note: use str - occasionally a fully numeric id will be placed in post body and parsed as int via JSON
# resulting in error for valid id
return app.security.decode_id( str( id ) )
except ( ValueError, TypeError ):
msg = "Malformed id ( %s ) specified, unable to decode" % ( str( id ) )
raise exceptions.MalformedId( msg, id=str( id ) )
def get_object( trans, id, class_name, check_ownership=False, check_accessible=False, deleted=None ):
"""
Convenience method to get a model object with the specified checks. This is
@@ -119,11 +129,7 @@ def get_object( trans, id, class_name, check_ownership=False, check_accessible=F
controller mixin code - however whenever possible the managers for a
particular model should be used to load objects.
"""
try:
decoded_id = trans.security.decode_id( id )
except:
raise exceptions.MessageException( "Malformed %s id ( %s ) specified, unable to decode"
% ( class_name, str( id ) ), type='error' )
decoded_id = decode_id(trans.app, id)
try:
item_class = get_class( class_name )
assert item_class is not None
+2 -3
View File
@@ -235,7 +235,7 @@ class UserManager( base.ModelManager, deletable.PurgableManagerMixin ):
if self.is_anonymous( user ):
return False
request_types = self.app.security_agent.get_accessible_request_types( trans, user )
return ( user.requests or request_types )
return bool( user.requests or request_types )
class UserSerializer( base.ModelSerializer, deletable.PurgableSerializerMixin ):
@@ -283,8 +283,7 @@ class UserSerializer( base.ModelSerializer, deletable.PurgableSerializerMixin ):
'quota_percent' : lambda i, k, **c: self.user_manager.quota( i ),
'tags_used' : lambda i, k, **c: self.user_manager.tags_used( i ),
# TODO: 'has_requests' is more apt
'requests' : lambda i, k, trans=None, **c: self.user_manager.has_requests( i, trans )
'has_requests' : lambda i, k, trans=None, **c: self.user_manager.has_requests( i, trans )
})
+47 -7
View File
@@ -2,12 +2,18 @@ from __future__ import absolute_import
from collections import namedtuple
import json
import uuid
from sqlalchemy import and_
from galaxy import model
from galaxy import util
from galaxy import exceptions
from galaxy.model.item_attrs import UsesAnnotations
from galaxy.workflow import modules
from .base import decode_id
# For WorkflowContentManager
from galaxy.util.sanitize_html import sanitize_html
from galaxy.workflow.steps import attach_ordered_steps
@@ -26,6 +32,38 @@ class WorkflowsManager( object ):
def __init__( self, app ):
self.app = app
def get_stored_workflow( self, trans, workflow_id ):
""" Use a supplied ID (UUID or encoded stored workflow ID) to find
a workflow.
"""
if util.is_uuid(workflow_id):
# see if they have passed in the UUID for a workflow that is attached to a stored workflow
workflow_uuid = uuid.UUID(workflow_id)
stored_workflow = trans.sa_session.query(trans.app.model.StoredWorkflow).filter( and_(
trans.app.model.StoredWorkflow.latest_workflow_id == trans.app.model.Workflow.id,
trans.app.model.Workflow.uuid == workflow_uuid
)).first()
if stored_workflow is None:
raise exceptions.ObjectNotFound( "Workflow not found: %s" % workflow_id )
else:
workflow_id = decode_id( self.app, workflow_id )
query = trans.sa_session.query( trans.app.model.StoredWorkflow )
stored_workflow = query.get( workflow_id )
if stored_workflow is None:
raise exceptions.ObjectNotFound( "No such workflow found." )
return stored_workflow
def get_stored_accessible_workflow( self, trans, workflow_id ):
stored_workflow = self.get_stored_workflow( trans, workflow_id )
# check to see if user has permissions to selected workflow
if stored_workflow.user != trans.user and not trans.user_is_admin():
if trans.sa_session.query(trans.app.model.StoredWorkflowUserShareAssociation).filter_by(user=trans.user, stored_workflow=stored_workflow).count() == 0:
message = "Workflow is not owned by or shared with current user"
raise exceptions.ItemAccessibilityException( message )
return stored_workflow
def check_security( self, trans, has_workflow, check_ownership=True, check_accessible=True):
""" check accessibility or ownership of workflows, storedworkflows, and
workflowinvocations. Throw an exception or returns True if user has
@@ -352,7 +390,7 @@ class WorkflowContentsManager(UsesAnnotations):
step_dict = {
'id': step.order_index,
'type': module.type,
'tool_id': module.get_tool_id(),
'tool_id': module.get_content_id(),
'name': module.get_name(),
'tool_state': module.get_state(),
'tooltip': module.get_tooltip( static_path=url_for( '/static' ) ),
@@ -395,11 +433,13 @@ class WorkflowContentsManager(UsesAnnotations):
action_arguments=pja.action_arguments
)
step_dict['post_job_actions'] = pja_dict
# workflow outputs
outputs = []
for output in step.workflow_outputs:
outputs.append({"output_name": output.output_name})
step_dict['workflow_outputs'] = outputs
# workflow outputs
outputs = []
for output in step.workflow_outputs:
outputs.append({"output_name": output.output_name})
step_dict['workflow_outputs'] = outputs
# Encode input connections as dictionary
input_conn_dict = {}
for conn in input_connections:
@@ -453,7 +493,7 @@ class WorkflowContentsManager(UsesAnnotations):
step_dict = {
'id': step.order_index,
'type': module.type,
'tool_id': module.get_tool_id(),
'tool_id': module.get_content_id(),
'tool_version': step.tool_version,
'name': module.get_name(),
'tool_state': module.get_state( secure=False ),
+1 -8
View File
@@ -11,7 +11,6 @@ from paste.httpexceptions import HTTPBadRequest, HTTPInternalServerError
from paste.httpexceptions import HTTPNotImplemented, HTTPRequestRangeNotSatisfiable
from galaxy.exceptions import ItemAccessibilityException, ItemDeletionException, ItemOwnershipException
from galaxy.exceptions import MessageException
from galaxy import exceptions
from galaxy import web
from galaxy import model
@@ -94,13 +93,7 @@ class BaseController( object ):
# ---- parsing query params
def decode_id( self, id ):
try:
# note: use str - occasionally a fully numeric id will be placed in post body and parsed as int via JSON
# resulting in error for valid id
return self.app.security.decode_id( str( id ) )
except ( ValueError, TypeError ):
msg = "Malformed id ( %s ) specified, unable to decode" % ( str( id ) )
raise exceptions.MalformedId( msg, id=str( id ) )
return managers_base.decode_id( self.app, id )
def encode_all_ids( self, trans, rval, recursive=False ):
"""
+3 -27
View File
@@ -4,11 +4,10 @@ API operations for Workflows
from __future__ import absolute_import
import uuid
import logging
import copy
import urllib
from sqlalchemy import and_, desc, false, or_, true
from sqlalchemy import desc, false, or_, true
from galaxy import exceptions, util
from galaxy.model.item_attrs import UsesAnnotations
from galaxy.managers import histories
@@ -570,33 +569,10 @@ class WorkflowsAPIController(BaseAPIController, UsesStoredWorkflowMixin, UsesAnn
)
def __get_stored_accessible_workflow( self, trans, workflow_id ):
stored_workflow = self.__get_stored_workflow( trans, workflow_id )
# check to see if user has permissions to selected workflow
if stored_workflow.user != trans.user and not trans.user_is_admin():
if trans.sa_session.query(trans.app.model.StoredWorkflowUserShareAssociation).filter_by(user=trans.user, stored_workflow=stored_workflow).count() == 0:
message = "Workflow is not owned by or shared with current user"
raise exceptions.ItemAccessibilityException( message )
return stored_workflow
return self.workflow_manager.get_stored_accessible_workflow( trans, workflow_id )
def __get_stored_workflow( self, trans, workflow_id ):
if util.is_uuid(workflow_id):
# see if they have passed in the UUID for a workflow that is attached to a stored workflow
workflow_uuid = uuid.UUID(workflow_id)
stored_workflow = trans.sa_session.query(trans.app.model.StoredWorkflow).filter( and_(
trans.app.model.StoredWorkflow.latest_workflow_id == trans.app.model.Workflow.id,
trans.app.model.Workflow.uuid == workflow_uuid
)).first()
if stored_workflow is None:
raise exceptions.ObjectNotFound( "Workflow not found: %s" % workflow_id )
else:
workflow_id = self.decode_id( workflow_id )
query = trans.sa_session.query( trans.app.model.StoredWorkflow )
stored_workflow = query.get( workflow_id )
if stored_workflow is None:
raise exceptions.ObjectNotFound( "No such workflow found." )
return stored_workflow
return self.workflow_manager.get_stored_workflow( trans, workflow_id )
def __encode_invocation( self, trans, invocation, view="element", step_details=False ):
return self.encode_all_ids(
@@ -503,7 +503,7 @@ class AdminToolshed( AdminGalaxy ):
if err_msg:
message += err_msg
status = 'error'
message += "Installed tool dependencies: %s" % ','.join( td.name for td in installed_tool_dependencies )
message += "Installed tool dependencies: %s" % ', '.join( td.name for td in installed_tool_dependencies )
td_ids = [ trans.security.encode_id( td.id ) for td in tool_shed_repository.tool_dependencies ]
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
action='manage_tool_dependencies',
@@ -1919,8 +1919,8 @@ class AdminToolshed( AdminGalaxy ):
if new_repository_dependencies == original_repository_dependencies:
for new_repository_tup in new_repository_dependencies:
# Make sure all dependencies are installed.
# TODO: Repository dependencies that are not installed should be displayed to to the user,
# giving them the option to install them or now. This is the same behavior as when initially
# TODO: Repository dependencies that are not installed should be displayed to the user,
# giving them the option to install them or not. This is the same behavior as when initially
# installing and when re-installing.
new_tool_shed, new_name, new_owner, new_changeset_revision, new_pir, new_oicct = \
common_util.parse_repository_dependency_tuple( new_repository_tup )
@@ -281,14 +281,6 @@ class RootController( controller.JSAppLauncher, UsesAnnotations ):
yield "No data with id=%d" % id
# ---- History management -----------------------------------------------
@web.expose
def history_options( self, trans ):
"""Displays a list of history related actions.
"""
return trans.fill_template( "/history/options.mako",
user=trans.get_user(),
history=trans.get_history( create=True ) )
@web.expose
def history_delete( self, trans, id ):
"""Backward compatibility with check_galaxy script.
@@ -613,7 +613,7 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
return trans.fill_template( "workflow/editor.mako", stored=stored, annotation=self.get_item_annotation_str( trans.sa_session, trans.user, stored ) )
@web.json
def editor_form_post( self, trans, type='tool', tool_id=None, annotation=None, **incoming ):
def editor_form_post( self, trans, type='tool', tool_id=None, annotation=None, label=None, **incoming ):
"""
Accepts a tool state and incoming values, and generates a new tool
form and some additional information, packed into a json dictionary.
@@ -625,12 +625,14 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
module = module_factory.from_dict( trans, {
'type': type,
'tool_id': tool_id,
'tool_state': tool_state
'tool_state': tool_state,
'label': label or None,
} )
# update module state
module.update_state( incoming )
if type == 'tool':
return {
'label': module.label,
'tool_state': module.get_state(),
'data_inputs': module.get_data_inputs(),
'data_outputs': module.get_data_outputs(),
@@ -641,6 +643,7 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
}
else:
return {
'label': module.label,
'tool_state': module.get_state(),
'data_inputs': module.get_data_inputs(),
'data_outputs': module.get_data_outputs(),
@@ -664,7 +667,7 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
return {
'type': module.type,
'name': module.get_name(),
'tool_id': module.get_tool_id(),
'tool_id': module.get_content_id(),
'tool_state': module.get_state(),
'tool_model': tool_model,
'tooltip': module.get_tooltip( static_path=url_for( '/static' ) ),
@@ -462,6 +462,7 @@ class WorkflowStep( object ):
self.position = None
self.input_connections = []
self.config = None
self.label = None
class WorkflowStepConnection( object ):
+19 -9
View File
@@ -42,7 +42,7 @@ class WorkflowModule( object ):
# ---- Creating modules from various representations ---------------------
@classmethod
def new( Class, trans, tool_id=None ):
def new( Class, trans, content_id=None ):
"""
Create a new instance of the module with default state
"""
@@ -73,7 +73,10 @@ class WorkflowModule( object ):
def get_name( self ):
return self.name
def get_tool_id( self ):
def get_content_id( self ):
""" If this component has an identifier external to the step (such
as a tool or another workflow) return the identifier for that content.
"""
return None
def get_tooltip( self, static_path='' ):
@@ -194,9 +197,10 @@ class WorkflowModule( object ):
class SimpleWorkflowModule( WorkflowModule ):
@classmethod
def new( Class, trans, tool_id=None ):
def new( Class, trans, content_id=None ):
module = Class( trans )
module.state = Class.default_state()
module.label = None
return module
@classmethod
@@ -204,12 +208,14 @@ class SimpleWorkflowModule( WorkflowModule ):
module = Class( trans )
state = loads( d["tool_state"] )
module.recover_state( state )
module.label = d.get("label", None) or None
return module
@classmethod
def from_workflow_step( Class, trans, step ):
module = Class( trans )
module.recover_state( step.tool_inputs )
module.label = step.label
return module
@classmethod
@@ -502,12 +508,13 @@ class ToolModule( WorkflowModule ):
self.errors[ tool_id ] = 'Tool unavailable'
@classmethod
def new( Class, trans, tool_id=None ):
module = Class( trans, tool_id )
def new( Class, trans, content_id=None ):
module = Class( trans, content_id )
if module.tool is None:
error_message = "Attempted to create new workflow module for invalid tool_id, no tool with id - %s." % tool_id
error_message = "Attempted to create new workflow module for invalid tool_id, no tool with id - %s." % content_id
raise Exception( error_message )
module.state = module.tool.new_state( trans )
module.label = None
return module
@classmethod
@@ -516,6 +523,7 @@ class ToolModule( WorkflowModule ):
tool_version = str( d.get( 'tool_version', None ) )
module = Class( trans, tool_id, tool_version=tool_version )
module.state = galaxy.tools.DefaultToolState()
module.label = d.get("label", None) or None
if module.tool is not None:
message = ""
if tool_id != module.tool_id:
@@ -560,6 +568,7 @@ class ToolModule( WorkflowModule ):
module.recover_state( step.tool_inputs )
module.errors = step.tool_errors
module.workflow_outputs = step.workflow_outputs
module.label = step.label or None
pjadict = {}
for pja in step.post_job_actions:
pjadict[pja.action_type] = pja
@@ -623,7 +632,7 @@ class ToolModule( WorkflowModule ):
return self.tool.name
return 'unavailable'
def get_tool_id( self ):
def get_content_id( self ):
return self.tool_id
def get_tool_version( self ):
@@ -735,6 +744,7 @@ class ToolModule( WorkflowModule ):
# set. We also need to make sure all datasets have a dummy value
# for dependencies to see
self.label = incoming.get("label", None) or None
self.post_job_actions = ActionBox.handle_incoming(incoming)
make_runtime_key = incoming.get( 'make_runtime', None )
@@ -951,13 +961,13 @@ class WorkflowModuleFactory( object ):
def __init__( self, module_types ):
self.module_types = module_types
def new( self, trans, type, tool_id=None ):
def new( self, trans, type, content_id=None ):
"""
Return module for type and (optional) tool_id intialized with
new / default state.
"""
assert type in self.module_types
return self.module_types[type].new( trans, tool_id )
return self.module_types[type].new( trans, content_id )
def from_dict( self, trans, d, **kwargs ):
"""
+2 -2
View File
@@ -235,8 +235,8 @@ class WorkflowProgress( object ):
if not hasattr( step, 'module' ):
self.module_injector.inject( step )
if step_id not in step_states:
template = "Workflow invocation [%s] has no step state for step id [%s]. States are [%s]."
message = template % (self.workflow_invocation.id, step_id, step_states)
template = "Workflow invocation [%s] has no step state for step id [%s]. States ids are %s."
message = template % (self.workflow_invocation.id, step_id, step_states.keys())
raise Exception(message)
runtime_state = step_states[ step_id ].value
step.state = step.module.recover_runtime_state( runtime_state )
@@ -126,10 +126,10 @@ class InstallToolDependencyManager( object ):
# Since there was an installation error, update the tool dependency status to Error. The remove_installation_path option must
# be left False here.
error_message = '%s\n%s' % ( self.format_traceback(), str( e ) )
tool_dependency = tool_dependency_util.handle_tool_dependency_installation_error( self.app,
tool_dependency,
error_message,
remove_installation_path=False )
tool_dependency = tool_dependency_util.set_tool_dependency_attributes(self.app,
tool_dependency=tool_dependency,
status=self.app.install_model.ToolDependency.installation_status.ERROR,
error_message=error_message)
tool_dependency = self.mark_tool_dependency_installed( tool_dependency )
return tool_dependency
@@ -204,10 +204,10 @@ class InstallToolDependencyManager( object ):
# Since there was an installation error, update the tool dependency status to Error. The
# remove_installation_path option must be left False here.
tool_dependency = \
tool_dependency_util.handle_tool_dependency_installation_error( self.app,
tool_dependency,
error_message,
remove_installation_path=False )
tool_dependency_util.set_tool_dependency_attributes(self.app,
tool_dependency=tool_dependency,
status=self.app.install_model.ToolDependency.installation_status.ERROR,
error_message=error_message)
if tool_dependency and tool_dependency.status in [ self.install_model.ToolDependency.installation_status.INSTALLED,
self.install_model.ToolDependency.installation_status.ERROR ]:
installed_packages.append( tool_dependency )
@@ -422,9 +422,7 @@ class InstallToolDependencyManager( object ):
status = self.install_model.ToolDependency.installation_status.INSTALLED
tool_dependency = tool_dependency_util.set_tool_dependency_attributes( self.app,
tool_dependency=tool_dependency,
status=status,
error_message=None,
remove_from_disk=False )
status=status )
return tool_dependency
@@ -204,9 +204,7 @@ class RepairRepositoryManager():
tool_dependency = \
tool_dependency_util.set_tool_dependency_attributes( self.app,
tool_dependency=tool_dependency,
status=self.app.install_model.ToolDependency.installation_status.UNINSTALLED,
error_message=None,
remove_from_disk=True )
status=self.app.install_model.ToolDependency.installation_status.UNINSTALLED )
# Install tool dependencies.
irm.update_tool_shed_repository_status( repository,
self.app.install_model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
@@ -19,7 +19,7 @@ from galaxy.util import unicodify
from tool_shed.galaxy_install.tool_dependencies.recipe import asynchronous_reader
from tool_shed.util import basic_util
from tool_shed.util import basic_util, tool_dependency_util
log = logging.getLogger( __name__ )
@@ -113,7 +113,6 @@ class InstallEnvironment( object ):
def handle_command( self, tool_dependency, cmd, return_output=False, job_name="" ):
"""Handle a command and log the results."""
context = self.app.install_model.context
command = str( cmd )
output = self.handle_complex_command( command, job_name=job_name )
self.log_results( cmd, output, os.path.join( self.install_dir, basic_util.INSTALLATION_LOG ) )
@@ -126,17 +125,19 @@ class InstallEnvironment( object ):
log.warn( "Length of stderr > %s, so only a portion will be saved in the database." % str( DATABASE_MAX_STRING_SIZE_PRETTY ) )
stderr = shrink_string_by_size( stderr, DATABASE_MAX_STRING_SIZE, join_by="\n..\n", left_larger=True, beginning_on_size_error=True )
if output.return_code not in [ 0 ]:
tool_dependency.status = self.app.install_model.ToolDependency.installation_status.ERROR
status = self.app.install_model.ToolDependency.installation_status.ERROR
if stderr:
tool_dependency.error_message = unicodify( stderr )
error_message = unicodify( stderr )
elif stdout:
tool_dependency.error_message = unicodify( stdout )
error_message = unicodify( stdout )
else:
# We have a problem if there was no stdout and no stderr.
tool_dependency.error_message = "Unknown error occurred executing shell command %s, return_code: %s" % \
error_message = "Unknown error occurred executing shell command %s, return_code: %s" % \
( str( cmd ), str( output.return_code ) )
context.add( tool_dependency )
context.flush()
tool_dependency_util.set_tool_dependency_attributes(self.app,
tool_dependency=tool_dependency,
status=status,
error_message=error_message)
if return_output:
return output
return output.return_code
@@ -156,6 +157,8 @@ class InstallEnvironment( object ):
if len( job_name ) > 0:
llog_name += ':' + job_name
llog = logging.getLogger( llog_name )
# Print the command we're about to execute, ``set -x`` style.
llog.debug('+ ' + str( command ) )
# Launch the command as subprocess. A bufsize of 1 means line buffered.
process_handle = subprocess.Popen( str( command ),
stdout=subprocess.PIPE,
@@ -284,8 +284,7 @@ class AssertDirectoryExecutable( RecipeStep ):
tool_dependency = tool_dependency_util.set_tool_dependency_attributes( self.app,
tool_dependency,
status=status,
error_message=error_message,
remove_from_disk=False )
error_message=error_message )
return tool_dependency, None, None
def prepare_step( self, tool_dependency, action_elem, action_dict, install_environment, is_binary_download ):
@@ -330,8 +329,7 @@ class AssertDirectoryExists( RecipeStep ):
tool_dependency = tool_dependency_util.set_tool_dependency_attributes( self.app,
tool_dependency,
status=status,
error_message=error_message,
remove_from_disk=False )
error_message=error_message )
return tool_dependency, None, None
def prepare_step( self, tool_dependency, action_elem, action_dict, install_environment, is_binary_download ):
@@ -380,8 +378,7 @@ class AssertFileExecutable( RecipeStep ):
tool_dependency = tool_dependency_util.set_tool_dependency_attributes( self.app,
tool_dependency,
status=status,
error_message=error_message,
remove_from_disk=False )
error_message=error_message )
return tool_dependency, None, None
def prepare_step( self, tool_dependency, action_elem, action_dict, install_environment, is_binary_download ):
@@ -427,8 +424,7 @@ class AssertFileExists( RecipeStep ):
tool_dependency = tool_dependency_util.set_tool_dependency_attributes( self.app,
tool_dependency,
status=status,
error_message=error_message,
remove_from_disk=False )
error_message=error_message )
return tool_dependency, None, None
def prepare_step( self, tool_dependency, action_elem, action_dict, install_environment, is_binary_download ):
@@ -180,10 +180,10 @@ class Install( RecipeTag, SyncDatabase ):
error_message += 'tag set.'
# Since there was an installation error, update the tool dependency status to Error.
# The remove_installation_path option must be left False here.
tool_dependency = tool_dependency_util.handle_tool_dependency_installation_error( self.app,
tool_dependency,
error_message,
remove_installation_path=False )
tool_dependency = tool_dependency_util.set_tool_dependency_attributes(self.app,
tool_dependency=tool_dependency,
status=self.app.install_model.ToolDependency.installation_status.ERROR,
error_message=error_message)
else:
raise NotImplementedError( 'Only install version 1.0 is currently supported (i.e., change your tag to be <install version="1.0">).' )
return tool_dependency, proceed_with_install, actions_elem_tuples
@@ -213,9 +213,7 @@ class Package( RecipeTag ):
tool_dependency = \
tool_dependency_util.set_tool_dependency_attributes( self.app,
tool_dependency=tool_dependency,
status=self.app.install_model.ToolDependency.installation_status.ERROR,
error_message=None,
remove_from_disk=False )
status=self.app.install_model.ToolDependency.installation_status.ERROR )
else:
proceed_with_install = True
return tool_dependency, proceed_with_install, action_elem_tuples
@@ -329,18 +327,18 @@ class Repository( RecipeTag, SyncDatabase ):
error_message = 'Error defining env.sh file for package %s, return_code: %s' % \
( str( package_name ), str( return_code ) )
tool_dependency = \
tool_dependency_util.handle_tool_dependency_installation_error( self.app,
tool_dependency,
error_message,
remove_installation_path=False )
tool_dependency_util.set_tool_dependency_attributes(self.app,
tool_dependency=tool_dependency,
status=self.app.install_model.ToolDependency.installation_status.ERROR,
error_message=error_message)
elif required_tool_dependency is not None and required_tool_dependency.in_error_state:
error_message = "This tool dependency's required tool dependency %s version %s has status %s." % \
( str( required_tool_dependency.name ), str( required_tool_dependency.version ), str( required_tool_dependency.status ) )
tool_dependency = \
tool_dependency_util.handle_tool_dependency_installation_error( self.app,
tool_dependency,
error_message,
remove_installation_path=False )
tool_dependency_util.set_tool_dependency_attributes(self.app,
tool_dependency=tool_dependency,
status=self.app.install_model.ToolDependency.installation_status.ERROR,
error_message=error_message)
else:
tool_dependency = \
tool_dependency_util.set_tool_dependency_attributes( self.app,
@@ -556,18 +554,10 @@ class SetEnvironment( RecipeTag ):
else:
attr_tups_of_dependencies_for_install = [ ( td.name, td.version, td.type ) for td in tool_dependency_db_records ]
try:
tool_dependencies = self.set_environment( package_elem, tool_shed_repository, attr_tups_of_dependencies_for_install )
self.set_environment( package_elem, tool_shed_repository, attr_tups_of_dependencies_for_install )
except Exception, e:
error_message = "Error setting environment for tool dependency: %s" % str( e )
log.debug( error_message )
for tool_dependency in tool_dependencies:
if tool_dependency and tool_dependency.status == self.app.install_model.ToolDependency.installation_status.ERROR:
# Since there was an installation error, update the tool dependency status to Error. The
# remove_installation_path option must be left False here.
tool_dependency = tool_dependency_util.handle_tool_dependency_installation_error( self.app,
tool_dependency,
error_message,
remove_installation_path=False )
return tool_dependency, proceed_with_install, action_elem_tuples
def set_environment( self, elem, tool_shed_repository, attr_tups_of_dependencies_for_install ):
@@ -613,7 +603,7 @@ class SetEnvironment( RecipeTag ):
# <requirement type="set_environment">R_SCRIPT_PATH</requirement>).
env_var_action = env_var_elem.get( 'action', None )
if env_var_name and env_var_action:
# Tool dependencies of type "set_environmnet" always have the version attribute set to None.
# Tool dependencies of type "set_environment" always have the version attribute set to None.
attr_tup = ( env_var_name, None, 'set_environment' )
if attr_tup in attr_tups_of_dependencies_for_install:
install_dir = \
@@ -654,8 +644,7 @@ class SetEnvironment( RecipeTag ):
tool_dependency_util.set_tool_dependency_attributes( self.app,
tool_dependency=tool_dependency,
status=status,
error_message=error_message,
remove_from_disk=False )
error_message=error_message )
else:
if tool_dependency.status not in [ self.app.install_model.ToolDependency.installation_status.ERROR,
self.app.install_model.ToolDependency.installation_status.INSTALLED ]:
@@ -663,9 +652,7 @@ class SetEnvironment( RecipeTag ):
tool_dependency = \
tool_dependency_util.set_tool_dependency_attributes( self.app,
tool_dependency=tool_dependency,
status=status,
error_message=None,
remove_from_disk=False )
status=status )
log.debug( 'Environment variable %s set in %s for tool dependency %s.' %
( str( env_var_name ), str( install_dir ), str( tool_dependency.name ) ) )
else:
@@ -675,7 +662,6 @@ class SetEnvironment( RecipeTag ):
tool_dependency_util.set_tool_dependency_attributes( self.app,
tool_dependency=tool_dependency,
status=status,
error_message=error_message,
remove_from_disk=False )
error_message=error_message )
tool_dependencies.append( tool_dependency )
return tool_dependencies
+11 -44
View File
@@ -48,14 +48,7 @@ def create_or_update_tool_dependency( app, tool_shed_repository, name, version,
# In some cases we should not override the current status of an existing tool_dependency, so do so only
# if set_status is True.
if set_status:
if str( tool_dependency.status ) != str( status ):
debug_msg = 'Updating an existing record for version %s of tool dependency %s for revision %s of repository %s ' % \
( str( version ), str( name ), str( tool_shed_repository.changeset_revision ), str( tool_shed_repository.name ) )
debug_msg += 'by updating the status from %s to %s.' % ( str( tool_dependency.status ), str( status ) )
log.debug( debug_msg )
tool_dependency.status = status
context.add( tool_dependency )
context.flush()
set_tool_dependency_attributes(app, tool_dependency=tool_dependency, status=status)
else:
# Create a new tool_dependency record for the tool_shed_repository.
debug_msg = 'Creating a new record for version %s of tool dependency %s for revision %s of repository %s. ' % \
@@ -227,38 +220,6 @@ def get_tool_dependency_install_dir( app, repository_name, repository_owner, rep
repository_changeset_revision ) )
def handle_tool_dependency_installation_error( app, tool_dependency, error_message, remove_installation_path=False ):
# Since there was an installation error, remove the installation directory because the install_package method uses
# this: "if os.path.exists( install_dir ):". Setting remove_installation_path to True should rarely occur. It is
# currently set to True only to handle issues with installing tool dependencies into an Amazon S3 bucket.
sa_session = app.install_model.context
tool_shed_repository = tool_dependency.tool_shed_repository
install_dir = get_tool_dependency_install_dir( app=app,
repository_name=tool_shed_repository.name,
repository_owner=tool_shed_repository.owner,
repository_changeset_revision=tool_shed_repository.installed_changeset_revision,
tool_dependency_type=tool_dependency.type,
tool_dependency_name=tool_dependency.name,
tool_dependency_version=tool_dependency.version )
if remove_installation_path:
# This will be True only in the case where an exception was encountered during the installation process after
# the installation path was created but before any information was written to the installation log and the
# tool dependency status was not set to "Installed" or "Error".
if os.path.exists( install_dir ):
log.debug( 'Attempting to remove installation directory %s for version %s of tool dependency %s %s' %
( str( install_dir ), str( tool_dependency.version ), str( tool_dependency.type ), str( tool_dependency.name ) ) )
log.debug( 'due to the following installation error:\n%s' % str( error_message ) )
try:
shutil.rmtree( install_dir )
except Exception, e:
log.exception( 'Error removing existing installation directory %s: %s', (install_dir, str(e)) )
tool_dependency.status = app.install_model.ToolDependency.installation_status.ERROR
tool_dependency.error_message = error_message
sa_session.add( tool_dependency )
sa_session.flush()
return tool_dependency
def parse_package_elem( package_elem, platform_info_dict=None, include_after_install_actions=True ):
"""
Parse a <package> element within a tool dependency definition and return a list of action tuples.
@@ -405,19 +366,25 @@ def remove_tool_dependency_installation_directory( dependency_install_dir ):
except Exception, e:
removed = False
error_message = "Error removing tool dependency installation directory %s: %s" % ( str( dependency_install_dir ), str( e ) )
log.debug( error_message )
log.warn( error_message )
else:
removed = True
error_message = ''
return removed, error_message
def set_tool_dependency_attributes( app, tool_dependency, status, error_message=None, remove_from_disk=False ):
def set_tool_dependency_attributes( app, tool_dependency, status, error_message=None ):
sa_session = app.install_model.context
if remove_from_disk:
if status == app.install_model.ToolDependency.installation_status.UNINSTALLED:
installation_directory = tool_dependency.installation_directory( app )
removed, err_msg = remove_tool_dependency_installation_directory( installation_directory )
remove_tool_dependency_installation_directory( installation_directory )
tool_dependency.error_message = error_message
if str( tool_dependency.status ) != str( status ):
tool_shed_repository = tool_dependency.tool_shed_repository
debug_msg = 'Updating an existing record for version %s of tool dependency %s for revision %s of repository %s ' % \
( str( tool_dependency.version ), str( tool_dependency.name ), str( tool_shed_repository.changeset_revision ), str( tool_shed_repository.name ) )
debug_msg += 'by updating the status from %s to %s.' % ( str( tool_dependency.status ), str( status ) )
log.debug( debug_msg )
tool_dependency.status = status
sa_session.add( tool_dependency )
sa_session.flush()
+1
View File
@@ -267,6 +267,7 @@ def get_workflow_from_dict( trans, workflow_dict, tools_metadata, repository_id,
for step_dict in workflow_dict[ 'steps' ].itervalues():
# Create the model class for the step
step = trans.model.WorkflowStep()
step.label = step_dict.get('label', None)
step.name = step_dict[ 'name' ]
step.position = step_dict[ 'position' ]
module = module_factory.from_dict( trans, repository_id, changeset_revision, step_dict, tools_metadata=tools_metadata, secure=False )
+1 -1
View File
@@ -68,7 +68,7 @@ ensure_grunt() {
}
DOCKER_DEFAULT_IMAGE='galaxy/testing-base:15.10.2'
DOCKER_DEFAULT_IMAGE='galaxy/testing-base:15.10.3'
test_script="./scripts/functional_tests.py"
report_file="run_functional_tests.html"
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
{"version":3,"file":"citation-model.js","sources":["../../../src/mvc/citation/citation-model.js"],"names":["define","bibtex","baseMVC","logNamespace","Citation","Backbone","Model","extend","LoggableMixin","_logNamespace","initialize","this","attributes","content","entry","BibtexParser","entries","_fields","rawFields","Fields","key","value","lowerKey","toLowerCase","entryType","EntryType","fields","BaseCitationCollection","Collection","urlRoot","Galaxy","root","partial","model","HistoryCitationCollection","url","history_id","ToolCitationCollection","tool_id"],"mappings":"AAAAA,QACI,cACA,eACA,sBACD,SAAUC,EAAQC,GAGrB,GAAIC,GAAe,WAMfC,EAAWC,SAASC,MAAMC,OAAQL,EAAQM,eAAgBD,QAC1DE,cAAgBN,EAEhBO,WAAY,WACR,GAAIT,GAASU,KAAKC,WAAWC,QACzBC,EAAQ,GAAIb,GAAOc,aAAad,GAAQe,QAAQ,EACpDL,MAAKG,MAAQA,EACbH,KAAKM,UACL,IAAIC,GAAYJ,EAAMK,MACtB,KAAI,GAAIC,KAAOF,GAAW,CACtB,GAAIG,GAAQH,EAAWE,GACnBE,EAAWF,EAAIG,aACnBZ,MAAKM,QAASK,GAAaD,IAGnCG,UAAW,WACP,MAAOb,MAAKG,MAAMW,WAEtBC,OAAQ,WACJ,MAAOf,MAAKM,WAOhBU,EAAyBtB,SAASuB,WAAWrB,OAAQL,EAAQM,eAAgBD,QAC7EE,cAAgBN,EAGhB0B,QAAUC,OAAOC,KAAO,MACxBC,SAAU,EACVC,MAAQ7B,IAGR8B,EAA4BP,EAAuBpB,QAEnD4B,IAAM,WACF,MAAOxB,MAAKkB,QAAU,cAAgBlB,KAAKyB,WAAa,gBAI5DC,EAAyBV,EAAuBpB,QAEhD4B,IAAM,WACF,MAAOxB,MAAKkB,QAAU,UAAYlB,KAAK2B,QAAU,cAErDN,SAAU,GAId,QACI5B,SAAWA,EACX8B,0BAA6BA,EAC7BG,uBAAwBA"}
{"version":3,"file":"citation-model.js","sources":["../../../src/mvc/citation/citation-model.js"],"names":["define","BibtexParser","baseMVC","logNamespace","Citation","Backbone","Model","extend","LoggableMixin","_logNamespace","initialize","bibtex","this","get","entry","entries","_fields","rawFields","Fields","key","value","lowerKey","toLowerCase","entryType","EntryType","fields","BaseCitationCollection","Collection","urlRoot","Galaxy","root","partial","model","HistoryCitationCollection","url","history_id","ToolCitationCollection","tool_id"],"mappings":"AAAAA,QACI,cACA,eACA,sBACD,SAAUC,EAAcC,GAG3B,GAAIC,GAAe,WAMfC,EAAWC,SAASC,MAAMC,OAAQL,EAAQM,eAAgBD,QAC1DE,cAAgBN,EAEhBO,WAAY,WACR,GAAIC,GAASC,KAAKC,IAAK,WACnBC,EAAQb,EAAaU,GAAQI,QAAQ,EACzCH,MAAKE,MAAQA,EACbF,KAAKI,UACL,IAAIC,GAAYH,EAAMI,MACtB,KAAI,GAAIC,KAAOF,GAAW,CACtB,GAAIG,GAAQH,EAAWE,GACnBE,EAAWF,EAAIG,aACnBV,MAAKI,QAASK,GAAaD,IAGnCG,UAAW,WACP,MAAOX,MAAKE,MAAMU,WAEtBC,OAAQ,WACJ,MAAOb,MAAKI,WAOhBU,EAAyBrB,SAASsB,WAAWpB,OAAQL,EAAQM,eAAgBD,QAC7EE,cAAgBN,EAGhByB,QAAUC,OAAOC,KAAO,MACxBC,SAAU,EACVC,MAAQ5B,IAGR6B,EAA4BP,EAAuBnB,QAEnD2B,IAAM,WACF,MAAOtB,MAAKgB,QAAU,cAAgBhB,KAAKuB,WAAa,gBAI5DC,EAAyBV,EAAuBnB,QAEhD2B,IAAM,WACF,MAAOtB,MAAKgB,QAAU,UAAYhB,KAAKyB,QAAU,cAErDN,SAAU,GAKd,QACI3B,SAAWA,EACX6B,0BAA6BA,EAC7BG,uBAAwBA"}
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"ui-select-default.js","sources":["../../../src/mvc/ui/ui-select-default.js"],"names":["define","Utils","Buttons","View","Backbone","extend","optionsDefault","id","uid","cls","error_text","empty_text","visible","wait","multiple","searchable","optional","initialize","options","self","this","merge","setElement","_template","$select","$el","find","$icon_dropdown","minHeight","$","on","event","currentY","pageY","currentHeight","height","show","Math","max","hide","off","all_button","ButtonCheck","onclick","new_value","value","_availableOptions","trigger","prepend","addClass","prop","remove","update","data","undefined","onchange","exists","val","select2","current","_getValue","isArray","length","_size","first","text","unwait","removeClass","disabled","is","enable","disable","append","_templateOption","label","key","closeOnSelect","setOnChange","callback","validate","available","each","i","e","push","attr","_","escape"],"mappings":"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"}
{"version":3,"file":"ui-select-default.js","sources":["../../../src/mvc/ui/ui-select-default.js"],"names":["define","Utils","Buttons","View","Backbone","extend","optionsDefault","id","uid","cls","error_text","empty_text","visible","wait","multiple","searchable","optional","initialize","options","self","this","merge","setElement","_template","$select","$el","find","$icon_dropdown","on","select2","minHeight","$","event","currentY","pageY","currentHeight","height","show","Math","max","hide","off","all_button","ButtonCheck","onclick","new_value","value","_availableOptions","trigger","prepend","addClass","prop","remove","update","data","undefined","onchange","exists","val","current","_getValue","isArray","length","_size","first","text","unwait","removeClass","disabled","is","enable","disable","append","_templateOption","label","key","closeOnSelect","setOnChange","callback","validate","available","each","i","e","push","attr","_","escape"],"mappings":"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"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
{"version":3,"file":"workflow-view-node.js","sources":["../../../src/mvc/workflow/workflow-view-node.js"],"names":["define","TerminalViews","DataViews","Backbone","View","extend","initialize","options","this","node","output_width","Math","max","$el","width","tool_body","find","remove","newInputsDiv","appendTo","terminalViews","outputTerminlViews","render","renderToolErrors","css","min","tool_errors","addClass","removeClass","$","updateMaxWidth","newWidth","addRule","append","addDataInput","input","body","skipResize","terminalView","name","terminalViewClass","input_type","InputCollectionTerminalView","InputTerminalView","el","terminal","destroy","update","destroyInvalidConnections","terminalElement","inputView","DataInputView","nodeView","ib","prepend","terminalElements","addDataOutput","output","OutputCollectionTerminalView","OutputTerminalView","outputView","DataOutputView","updateDataOutput","outputTerminal","output_terminals"],"mappings":"AAAAA,QAAQ,uCAAwC,mCAAoC,SAAUC,EAAeC,GACzG,MAAOC,UAASC,KAAKC,QACjBC,WAAY,SAAUC,GAClBC,KAAKC,KAAOF,EAAQE,KACpBD,KAAKE,aAAeC,KAAKC,IAAI,IAAKJ,KAAKK,IAAIC,SAC3CN,KAAKO,UAAYP,KAAKK,IAAIG,KAAM,iBAChCR,KAAKO,UAAUC,KAAM,OAAQC,SAC7BT,KAAKU,eAAeC,SAAUX,KAAKO,WACnCP,KAAKY,iBACLZ,KAAKa,uBAGTC,OAAQ,WACJd,KAAKe,mBACLf,KAAKK,IAAIW,IAAK,QAASb,KAAKc,IAAI,IAAKd,KAAKC,IAAKJ,KAAKK,IAAIC,QAASN,KAAKE,iBAG1Ea,iBAAkB,WACTf,KAAKC,KAAKiB,YACXlB,KAAKK,IAAIc,SAAU,mBAEnBnB,KAAKK,IAAIe,YAAa,oBAI9BV,aAAc,WACV,MAAOW,GAAE,+BAGbC,eAAgB,SAAUC,GACtBvB,KAAKE,aAAeC,KAAKC,IAAKJ,KAAKE,aAAcqB,IAGrDC,QAAS,WACLxB,KAAKO,UAAUkB,OAAQJ,EAAG,8BAG9BK,aAAc,SAAUC,EAAOC,GAC3B,GAAIC,IAAa,CACXD,KACFA,EAAO5B,KAAKqB,EAAG,WAGfQ,GAAa,EAEjB,IAAIC,GAAe9B,KAAKY,cAAee,EAAMI,MACzCC,EAA0C,sBAApBL,EAAMM,WAAuCxC,EAAcyC,4BAA8BzC,EAAc0C,iBAKjI,KAJIL,GAAoBA,YAAwBE,KAC5CF,EAAaM,GAAGC,SAASC,UACzBR,EAAe,MAEbA,EAKC,CACH,GAAIO,GAAWP,EAAaM,GAAGC,QAC/BA,GAASE,OAAQZ,GACjBU,EAASG,gCAPTV,GAAe,GAAIE,IACf/B,KAAMD,KAAKC,KACX0B,MAAOA,GAOf3B,MAAKY,cAAee,EAAMI,MAASD,CACnC,IAAIW,GAAkBX,EAAaM,GAC/BM,EAAY,GAAIhD,GAAUiD,eAC1BF,gBAAiBA,EACjBd,MAAOA,EACPiB,SAAU5C,KACV6B,WAAYA,IAEZgB,EAAKH,EAAUrC,GAEnB,OADAuB,GAAKH,OAAQoB,EAAGC,QAAShB,EAAaiB,qBAC/BjB,GAGXkB,cAAe,SAAUC,GACrB,GAAIjB,GAAsBiB,EAAkB,WAAIxD,EAAcyD,6BAA+BzD,EAAc0D,mBACvGrB,EAAe,GAAIE,IACnB/B,KAAMD,KAAKC,KACXgD,OAAQA,IAERG,EAAa,GAAI1D,GAAU2D,gBAC3BJ,OAAUA,EACVR,gBAAmBX,EAAaM,GAChCQ,SAAY5C,MAEhBA,MAAKO,UAAUkB,OAAQ2B,EAAW/C,IAAIoB,OAAQK,EAAaiB,sBAG/DO,iBAAkB,SAAUL,GACxB,GAAIM,GAAiBvD,KAAKC,KAAKuD,iBAAkBP,EAAOlB,KACxDwB,GAAehB,OAAQU"}
{"version":3,"file":"workflow-view-node.js","sources":["../../../src/mvc/workflow/workflow-view-node.js"],"names":["define","TerminalViews","DataViews","Backbone","View","extend","initialize","options","this","node","output_width","Math","max","$el","width","tool_body","find","remove","newInputsDiv","appendTo","terminalViews","outputTerminlViews","render","title","label","name","text","renderToolErrors","css","min","tool_errors","addClass","removeClass","$","updateMaxWidth","newWidth","addRule","append","addDataInput","input","body","skipResize","terminalView","terminalViewClass","input_type","InputCollectionTerminalView","InputTerminalView","el","terminal","destroy","update","destroyInvalidConnections","terminalElement","inputView","DataInputView","nodeView","ib","prepend","terminalElements","addDataOutput","output","OutputCollectionTerminalView","OutputTerminalView","outputView","DataOutputView","updateDataOutput","outputTerminal","output_terminals"],"mappings":"AAAAA,QAAQ,uCAAwC,mCAAoC,SAAUC,EAAeC,GACzG,MAAOC,UAASC,KAAKC,QACjBC,WAAY,SAAUC,GAClBC,KAAKC,KAAOF,EAAQE,KACpBD,KAAKE,aAAeC,KAAKC,IAAI,IAAKJ,KAAKK,IAAIC,SAC3CN,KAAKO,UAAYP,KAAKK,IAAIG,KAAM,iBAChCR,KAAKO,UAAUC,KAAM,OAAQC,SAC7BT,KAAKU,eAAeC,SAAUX,KAAKO,WACnCP,KAAKY,iBACLZ,KAAKa,uBAGTC,OAAQ,WACJ,GACIC,GADAC,EAAQhB,KAAKC,KAAKe,KAGlBD,GADDC,EACSA,EAEAhB,KAAKC,KAAKgB,KAEtBjB,KAAKK,IAAIG,KAAK,cAAcU,KAAKH,GACjCf,KAAKmB,mBACLnB,KAAKK,IAAIe,IAAK,QAASjB,KAAKkB,IAAI,IAAKlB,KAAKC,IAAKJ,KAAKK,IAAIC,QAASN,KAAKE,iBAG1EiB,iBAAkB,WACTnB,KAAKC,KAAKqB,YACXtB,KAAKK,IAAIkB,SAAU,mBAEnBvB,KAAKK,IAAImB,YAAa,oBAI9Bd,aAAc,WACV,MAAOe,GAAE,+BAGbC,eAAgB,SAAUC,GACtB3B,KAAKE,aAAeC,KAAKC,IAAKJ,KAAKE,aAAcyB,IAGrDC,QAAS,WACL5B,KAAKO,UAAUsB,OAAQJ,EAAG,8BAG9BK,aAAc,SAAUC,EAAOC,GAC3B,GAAIC,IAAa,CACXD,KACFA,EAAOhC,KAAKyB,EAAG,WAGfQ,GAAa,EAEjB,IAAIC,GAAelC,KAAKY,cAAemB,EAAMd,MACzCkB,EAA0C,sBAApBJ,EAAMK,WAAuC3C,EAAc4C,4BAA8B5C,EAAc6C,iBAKjI,KAJIJ,GAAoBA,YAAwBC,KAC5CD,EAAaK,GAAGC,SAASC,UACzBP,EAAe,MAEbA,EAKC,CACH,GAAIM,GAAWN,EAAaK,GAAGC,QAC/BA,GAASE,OAAQX,GACjBS,EAASG,gCAPTT,GAAe,GAAIC,IACflC,KAAMD,KAAKC,KACX8B,MAAOA,GAOf/B,MAAKY,cAAemB,EAAMd,MAASiB,CACnC,IAAIU,GAAkBV,EAAaK,GAC/BM,EAAY,GAAInD,GAAUoD,eAC1BF,gBAAiBA,EACjBb,MAAOA,EACPgB,SAAU/C,KACViC,WAAYA,IAEZe,EAAKH,EAAUxC,GAEnB,OADA2B,GAAKH,OAAQmB,EAAGC,QAASf,EAAagB,qBAC/BhB,GAGXiB,cAAe,SAAUC,GACrB,GAAIjB,GAAsBiB,EAAkB,WAAI3D,EAAc4D,6BAA+B5D,EAAc6D,mBACvGpB,EAAe,GAAIC,IACnBlC,KAAMD,KAAKC,KACXmD,OAAQA,IAERG,EAAa,GAAI7D,GAAU8D,gBAC3BJ,OAAUA,EACVR,gBAAmBV,EAAaK,GAChCQ,SAAY/C,MAEhBA,MAAKO,UAAUsB,OAAQ0B,EAAWlD,IAAIwB,OAAQK,EAAagB,sBAG/DO,iBAAkB,SAAUL,GACxB,GAAIM,GAAiB1D,KAAKC,KAAK0D,iBAAkBP,EAAOnC,KACxDyC,GAAehB,OAAQU"}
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"polyfills.js","sources":["../src/polyfills.js"],"names":["window","console","log","debug","info","warn","error","assert","Object","assign","_","extend","lastTime","vendors","x","length","requestAnimationFrame","cancelRequestAnimationFrame","callback","currTime","Date","getTime","timeToCall","Math","max","id","setTimeout","cancelAnimationFrame","clearTimeout","incompatibilities","name","compatible","CanvasRenderingContext2D","Number","isInteger","sessionStorage","err","filter","feature","map","root","document","querySelectorAll","item","location","href","join"],"mappings":"CAKA,WAMI,YAKAA,QAAOC,QAAUD,OAAOC,UACpBC,IAAU,aACVC,MAAU,aACVC,KAAU,aACVC,KAAU,aACVC,MAAU,aACVC,OAAU,cAIdC,OAAOC,OAASD,OAAOC,QAAUC,EAAEC,MAKnC,KAAI,GAFAC,GAAW,EACXC,GAAW,KAAM,MAAO,SAAU,KAC9BC,EAAI,EAAGA,EAAID,EAAQE,SAAWf,OAAOgB,wBAAyBF,EAClEd,OAAOgB,sBAAwBhB,OAAOa,EAAQC,GAAG,yBACjDd,OAAOiB,4BAA8BjB,OAAOa,EAAQC,GAClD,8BAGDd,QAAOgB,wBACRhB,OAAOgB,sBAAwB,SAASE,GACpC,GAAIC,IAAW,GAAIC,OAAOC,UACtBC,EAAaC,KAAKC,IAAI,EAAG,IAAML,EAAWP,IAC1Ca,EAAKzB,OAAO0B,WAAW,WAAaR,EAASC,EAAWG,IAC1DA,EAEF,OADAV,GAAWO,EAAWG,EACfG,IAGVzB,OAAO2B,uBACR3B,OAAO2B,qBAAuB,SAASF,GACnCG,aAAaH,IAIrB,IAAII,KACEC,KAAM,SAAoBC,WAAY,WAAY,MAAO/B,QAAOgC,4BAChEF,KAAM,iBAAoBC,WAAY,WACpC,IACI,MAAOE,QAAOC,UAAWC,eAAepB,QAC1C,MAAOqB,IACT,OAAO,IASf,IALAP,EAAoBA,EACfQ,OAAQ,SAAUC,GAAW,OAAQA,EAAQP,eAC7CQ,IAAK,SAAUD,GAAW,MAAOA,GAAQR,OAGxCD,EAAkBd,OAAQ,CAC5B,GAAIyB,GAAOC,SAASC,iBAAkB,qBAAsBC,KAAM,EAC9DH,KACAxC,OAAO4C,SAASC,KAAOL,EAAKK,KAAO,oCAEvC5C,QAAQC,IAAK,0BAA4B2B,EAAkBiB,KAAM"}
{"version":3,"file":"polyfills.js","sources":["../src/polyfills.js"],"names":["window","console","log","debug","info","warn","error","assert","Object","assign","_","extend","lastTime","vendors","x","length","requestAnimationFrame","cancelRequestAnimationFrame","callback","currTime","Date","getTime","timeToCall","Math","max","id","setTimeout","cancelAnimationFrame","clearTimeout","features","name","compatible","CanvasRenderingContext2D","sessionStorage","err","incompatibilities","filter","feature","map","root","document","querySelectorAll","item","location","href","join"],"mappings":"CAKA,WAMI,YAKAA,QAAOC,QAAUD,OAAOC,UACpBC,IAAU,aACVC,MAAU,aACVC,KAAU,aACVC,KAAU,aACVC,MAAU,aACVC,OAAU,cAIdC,OAAOC,OAASD,OAAOC,QAAUC,EAAEC,MAKnC,KAAI,GAFAC,GAAW,EACXC,GAAW,KAAM,MAAO,SAAU,KAC9BC,EAAI,EAAGA,EAAID,EAAQE,SAAWf,OAAOgB,wBAAyBF,EAClEd,OAAOgB,sBAAwBhB,OAAOa,EAAQC,GAAG,yBACjDd,OAAOiB,4BAA8BjB,OAAOa,EAAQC,GAClD,8BAGDd,QAAOgB,wBACRhB,OAAOgB,sBAAwB,SAASE,GACpC,GAAIC,IAAW,GAAIC,OAAOC,UACtBC,EAAaC,KAAKC,IAAI,EAAG,IAAML,EAAWP,IAC1Ca,EAAKzB,OAAO0B,WAAW,WAAaR,EAASC,EAAWG,IAC1DA,EAEF,OADAV,GAAWO,EAAWG,EACfG,IAGVzB,OAAO2B,uBACR3B,OAAO2B,qBAAuB,SAASF,GACnCG,aAAaH,IAIrB,IAAII,KACEC,KAAM,SAAoBC,WAAY,WAAY,MAAO/B,QAAOgC,4BAChEF,KAAM,iBAAoBC,WAAY,WACpC,IACI,MAAO/B,QAAOiC,eAAelB,QAAU,EACzC,MAAOmB,IACT,OAAO,KAIXC,EAAoBN,EACnBO,OAAQ,SAAUC,GAAW,OAAQA,EAAQN,eAC7CO,IAAK,SAAUD,GAAW,MAAOA,GAAQP,MAG9C,IAAMK,EAAkBpB,OAAQ,CAC5B,GAAIwB,GAAOC,SAASC,iBAAkB,qBAAsBC,KAAM,EAC9DH,KACAvC,OAAO2C,SAAWJ,EAAKK,KAAO,oCAElC3C,QAAQC,IAAK,0BAA4BiC,EAAkBU,KAAM"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,2 +1,2 @@
define(["libs/bibtex","mvc/base-mvc","utils/localization"],function(a,b){var c="citation",d=Backbone.Model.extend(b.LoggableMixin).extend({_logNamespace:c,initialize:function(){var a=this.attributes.content,b=new a.BibtexParser(a).entries[0];this.entry=b,this._fields={};var c=b.Fields;for(var d in c){var e=c[d],f=d.toLowerCase();this._fields[f]=e}},entryType:function(){return this.entry.EntryType},fields:function(){return this._fields}}),e=Backbone.Collection.extend(b.LoggableMixin).extend({_logNamespace:c,urlRoot:Galaxy.root+"api",partial:!0,model:d}),f=e.extend({url:function(){return this.urlRoot+"/histories/"+this.history_id+"/citations"}}),g=e.extend({url:function(){return this.urlRoot+"/tools/"+this.tool_id+"/citations"},partial:!1});return{Citation:d,HistoryCitationCollection:f,ToolCitationCollection:g}});
define(["libs/bibtex","mvc/base-mvc","utils/localization"],function(a,b){var c="citation",d=Backbone.Model.extend(b.LoggableMixin).extend({_logNamespace:c,initialize:function(){var b=this.get("content"),c=a(b).entries[0];this.entry=c,this._fields={};var d=c.Fields;for(var e in d){var f=d[e],g=e.toLowerCase();this._fields[g]=f}},entryType:function(){return this.entry.EntryType},fields:function(){return this._fields}}),e=Backbone.Collection.extend(b.LoggableMixin).extend({_logNamespace:c,urlRoot:Galaxy.root+"api",partial:!0,model:d}),f=e.extend({url:function(){return this.urlRoot+"/histories/"+this.history_id+"/citations"}}),g=e.extend({url:function(){return this.urlRoot+"/tools/"+this.tool_id+"/citations"},partial:!1});return{Citation:d,HistoryCitationCollection:f,ToolCitationCollection:g}});
//# sourceMappingURL=../../../maps/mvc/citation/citation-model.js.map
+1 -1
View File
@@ -1,2 +1,2 @@
define(["utils/utils","mvc/ui/ui-buttons"],function(a,b){var c=Backbone.View.extend({optionsDefault:{id:a.uid(),cls:"ui-select",error_text:"No options available",empty_text:"Nothing selected",visible:!0,wait:!1,multiple:!1,searchable:!0,optional:!1},initialize:function(c){var d=this;this.options=a.merge(c,this.optionsDefault),this.setElement(this._template(this.options)),this.$select=this.$el.find(".select"),this.$icon_dropdown=this.$el.find(".icon-dropdown");var e=null;this.$(".icon-resize").on("mousedown",function(a){var b=a.pageY,c=d.$select.height();e=e||c,$("#dd-helper").show().on("mousemove",function(a){d.$select.height(Math.max(c+(a.pageY-b),e))}).on("mouseup mouseleave",function(){$("#dd-helper").hide().off()})}),this.options.multiple&&(this.options.searchable?(this.all_button=new b.ButtonCheck({onclick:function(){var a=[];0!==d.all_button.value()&&(a=d._availableOptions()),d.value(a),d.trigger("change")}}),this.$el.prepend(this.all_button.$el)):this.$el.addClass("ui-select-multiple"),this.$select.prop("multiple",!0),this.$icon_dropdown.remove()),this.update(this.options.data),void 0!==this.options.value&&this.value(this.options.value),this.options.visible||this.hide(),this.options.wait?this.wait():this.show(),this.$select.on("change",function(){d.trigger("change")}),this.on("change",function(){d.options.onchange&&d.options.onchange(this.value())})},value:function(a){void 0!==a&&(null===a&&(a="__null__"),(this.exists(a)||this.options.multiple)&&(this.$select.val(a),this.$select.select2&&this.$select.select2("val",a)));var b=this._getValue();return this.all_button&&this.all_button.value($.isArray(b)&&b.length||0,this._size()),b},first:function(){var a=this.$select.find("option").first();return a.length>0?a.val():null},text:function(){return this.$select.find("option:selected").text()},show:function(){this.unwait(),this.$select.show(),this.$el.show()},hide:function(){this.$el.hide()},wait:function(){this.$icon_dropdown.removeClass(),this.$icon_dropdown.addClass("icon-dropdown fa fa-spinner fa-spin")},unwait:function(){this.$icon_dropdown.removeClass(),this.$icon_dropdown.addClass("icon-dropdown fa fa-caret-down")},disabled:function(){return this.$select.is(":disabled")},enable:function(){this.$select.prop("disabled",!1)},disable:function(){this.$select.prop("disabled",!0)},update:function(a){var b=this._getValue();this.$select.find("option").remove(),!this.options.multiple&&this.options.optional&&this.$select.append(this._templateOption({value:"__null__",label:this.options.empty_text}));for(var c in a)this.$select.append(this._templateOption(a[c]));0==this._size()?(this.disable(),this.$select.append(this._templateOption({value:"__null__",label:this.options.error_text}))):this.enable(),this.options.searchable&&(this.$select.select2("destroy"),this.$select.select2({closeOnSelect:!this.options.multiple}),this.$(".select2-container .select2-search input").off("blur")),this.value(b),null!==this._getValue()||this.options.multiple&&this.options.optional||this.value(this.first())},setOnChange:function(a){this.options.onchange=a},exists:function(a){return this.$select.find('option[value="'+a+'"]').length>0},_getValue:function(){var b=this.$select.val();return a.validate(b)?b:null},_availableOptions:function(){var a=[];return this.$select.find("option").each(function(b,c){a.push($(c).attr("value"))}),a},_size:function(){return this.$select.find("option").length},_templateOption:function(a){return'<option value="'+a.value+'">'+_.escape(a.label)+"</option>"},_template:function(a){return'<div id="'+a.id+'" class="'+a.cls+'"><select id="'+a.id+'_select" class="select"/><div class="icon-dropdown"/><div class="icon-resize"><i class="fa fa-angle-double-right fa-rotate-45"/></div></div>'}});return{View:c}});
define(["utils/utils","mvc/ui/ui-buttons"],function(a,b){var c=Backbone.View.extend({optionsDefault:{id:a.uid(),cls:"ui-select",error_text:"No options available",empty_text:"Nothing selected",visible:!0,wait:!1,multiple:!1,searchable:!0,optional:!1},initialize:function(c){var d=this;this.options=a.merge(c,this.optionsDefault),this.setElement(this._template(this.options)),this.$select=this.$el.find(".select"),this.$icon_dropdown=this.$el.find(".icon-dropdown"),this.$icon_dropdown.on("click",function(){d.$select.select2&&d.$select.select2("open")});var e=null;this.$(".icon-resize").on("mousedown",function(a){var b=a.pageY,c=d.$select.height();e=e||c,$("#dd-helper").show().on("mousemove",function(a){d.$select.height(Math.max(c+(a.pageY-b),e))}).on("mouseup mouseleave",function(){$("#dd-helper").hide().off()})}),this.options.multiple&&(this.options.searchable?(this.all_button=new b.ButtonCheck({onclick:function(){var a=[];0!==d.all_button.value()&&(a=d._availableOptions()),d.value(a),d.trigger("change")}}),this.$el.prepend(this.all_button.$el)):this.$el.addClass("ui-select-multiple"),this.$select.prop("multiple",!0),this.$icon_dropdown.remove()),this.update(this.options.data),void 0!==this.options.value&&this.value(this.options.value),this.options.visible||this.hide(),this.options.wait?this.wait():this.show(),this.$select.on("change",function(){d.trigger("change")}),this.on("change",function(){d.options.onchange&&d.options.onchange(this.value())})},value:function(a){void 0!==a&&(null===a&&(a="__null__"),(this.exists(a)||this.options.multiple)&&(this.$select.val(a),this.$select.select2&&this.$select.select2("val",a)));var b=this._getValue();return this.all_button&&this.all_button.value($.isArray(b)&&b.length||0,this._size()),b},first:function(){var a=this.$select.find("option").first();return a.length>0?a.val():null},text:function(){return this.$select.find("option:selected").text()},show:function(){this.unwait(),this.$select.show(),this.$el.show()},hide:function(){this.$el.hide()},wait:function(){this.$icon_dropdown.removeClass(),this.$icon_dropdown.addClass("icon-dropdown fa fa-spinner fa-spin")},unwait:function(){this.$icon_dropdown.removeClass(),this.$icon_dropdown.addClass("icon-dropdown fa fa-caret-down")},disabled:function(){return this.$select.is(":disabled")},enable:function(){this.$select.prop("disabled",!1)},disable:function(){this.$select.prop("disabled",!0)},update:function(a){var b=this._getValue();this.$select.find("option").remove(),!this.options.multiple&&this.options.optional&&this.$select.append(this._templateOption({value:"__null__",label:this.options.empty_text}));for(var c in a)this.$select.append(this._templateOption(a[c]));0==this._size()?(this.disable(),this.$select.append(this._templateOption({value:"__null__",label:this.options.error_text}))):this.enable(),this.options.searchable&&(this.$select.select2("destroy"),this.$select.select2({closeOnSelect:!this.options.multiple}),this.$(".select2-container .select2-search input").off("blur")),this.value(b),null!==this._getValue()||this.options.multiple&&this.options.optional||this.value(this.first())},setOnChange:function(a){this.options.onchange=a},exists:function(a){return this.$select.find('option[value="'+a+'"]').length>0},_getValue:function(){var b=this.$select.val();return a.validate(b)?b:null},_availableOptions:function(){var a=[];return this.$select.find("option").each(function(b,c){a.push($(c).attr("value"))}),a},_size:function(){return this.$select.find("option").length},_templateOption:function(a){return'<option value="'+a.value+'">'+_.escape(a.label)+"</option>"},_template:function(a){return'<div id="'+a.id+'" class="'+a.cls+'"><select id="'+a.id+'_select" class="select"/><div class="icon-dropdown"/><div class="icon-resize"><i class="fa fa-angle-double-right fa-rotate-45"/></div></div>'}});return{View:c}});
//# sourceMappingURL=../../../maps/mvc/ui/ui-select-default.js.map
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,2 +1,2 @@
define(["mvc/workflow/workflow-view-node"],function(a){var b=Backbone.Model.extend({initialize:function(a,b){this.app=a,this.element=b.element,this.input_terminals={},this.output_terminals={},this.tool_errors={},this.workflow_outputs=[]},getWorkflowOutput:function(a){return _.findWhere(this.workflow_outputs,{output_name:a})},isWorkflowOutput:function(a){return void 0!=this.getWorkflowOutput(a)},removeWorkflowOutput:function(a){for(;this.isWorkflowOutput(a);)this.workflow_outputs.splice(this.getWorkflowOutput(a),1)},addWorkflowOutput:function(a){this.isWorkflowOutput(a)||this.workflow_outputs.push({output_name:a})},connectedOutputTerminals:function(){return this._connectedTerminals(this.output_terminals)},_connectedTerminals:function(a){var b=[];return $.each(a,function(a,c){c.connectors.length>0&&b.push(c)}),b},hasConnectedOutputTerminals:function(){var a=this.output_terminals;for(var b in a)if(a[b].connectors.length>0)return!0;return!1},connectedMappedInputTerminals:function(){return this._connectedMappedTerminals(this.input_terminals)},hasConnectedMappedInputTerminals:function(){var a=this.input_terminals;for(var b in a){var c=a[b];if(c.connectors.length>0&&c.isMappedOver())return!0}return!1},_connectedMappedTerminals:function(a){var b=[];return $.each(a,function(a,c){var d=c.mapOver();d.isCollection&&c.connectors.length>0&&b.push(c)}),b},mappedInputTerminals:function(){return this._mappedTerminals(this.input_terminals)},_mappedTerminals:function(a){var b=[];return $.each(a,function(a,c){var d=c.mapOver();d.isCollection&&b.push(c)}),b},hasMappedOverInputTerminals:function(){var a=!1;return _.each(this.input_terminals,function(b){var c=b.mapOver();c.isCollection&&(a=!0)}),a},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()}),$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()}),$.each(this.output_terminals,function(a,b){b.destroy()}),this.app.workflow.remove_node(this),$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);!function(b){b.removeChild(a),b.appendChild(a)}(a.parentNode),$(a).removeClass("toolForm-active")},init_field_data:function(b){b.type&&(this.type=b.type),this.name=b.name,this.form_html=b.form_html,this.tool_state=b.tool_state,this.tool_errors=b.tool_errors,this.tooltip=b.tooltip?b.tooltip:"",this.annotation=b.annotation,this.post_job_actions=b.post_job_actions?b.post_job_actions:{},this.label=b.label,this.uuid=b.uuid,this.workflow_outputs=b.workflow_outputs?b.workflow_outputs:[];var c=this,d=new a({el:this.element[0],node:c});c.nodeView=d,$.each(b.data_inputs,function(a,b){d.addDataInput(b)}),b.data_inputs.length>0&&b.data_outputs.length>0&&d.addRule(),$.each(b.data_outputs,function(a,b){d.addDataOutput(b)}),d.render(),this.app.workflow.node_changed(this,!0)},update_field_data:function(a){var b=this;if(nodeView=b.nodeView,this.tool_state=a.tool_state,this.form_html=a.form_html,this.tool_errors=a.tool_errors,this.annotation=a.annotation,"post_job_actions"in a){var c=$.parseJSON(a.post_job_actions);this.post_job_actions=c?c:{}}b.nodeView.renderToolErrors();var d=nodeView.$("div.inputs"),e=nodeView.newInputsDiv(),f={};_.each(a.data_inputs,function(a){var c=b.nodeView.addDataInput(a,e);f[a.name]=c}),_.each(_.difference(_.values(nodeView.terminalViews),_.values(f)),function(a){a.el.terminal.destroy()}),nodeView.terminalViews=f,1==a.data_outputs.length&&"collection_type"in a.data_outputs[0]&&nodeView.updateDataOutput(a.data_outputs[0]),d.replaceWith(e),this.markChanged(),this.redraw()},error:function(a){var b=$(this.element).find(".toolFormBody");b.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+a+"</div>";this.form_html=c,b.html(c),this.app.workflow.node_changed(this)},markChanged:function(){this.app.workflow.node_changed(this)}});return b});
define(["mvc/workflow/workflow-view-node"],function(a){var b=Backbone.Model.extend({initialize:function(a,b){this.app=a,this.element=b.element,this.input_terminals={},this.output_terminals={},this.tool_errors={},this.workflow_outputs=[]},getWorkflowOutput:function(a){return _.findWhere(this.workflow_outputs,{output_name:a})},isWorkflowOutput:function(a){return void 0!=this.getWorkflowOutput(a)},removeWorkflowOutput:function(a){for(;this.isWorkflowOutput(a);)this.workflow_outputs.splice(this.getWorkflowOutput(a),1)},addWorkflowOutput:function(a){this.isWorkflowOutput(a)||this.workflow_outputs.push({output_name:a})},connectedOutputTerminals:function(){return this._connectedTerminals(this.output_terminals)},_connectedTerminals:function(a){var b=[];return $.each(a,function(a,c){c.connectors.length>0&&b.push(c)}),b},hasConnectedOutputTerminals:function(){var a=this.output_terminals;for(var b in a)if(a[b].connectors.length>0)return!0;return!1},connectedMappedInputTerminals:function(){return this._connectedMappedTerminals(this.input_terminals)},hasConnectedMappedInputTerminals:function(){var a=this.input_terminals;for(var b in a){var c=a[b];if(c.connectors.length>0&&c.isMappedOver())return!0}return!1},_connectedMappedTerminals:function(a){var b=[];return $.each(a,function(a,c){var d=c.mapOver();d.isCollection&&c.connectors.length>0&&b.push(c)}),b},mappedInputTerminals:function(){return this._mappedTerminals(this.input_terminals)},_mappedTerminals:function(a){var b=[];return $.each(a,function(a,c){var d=c.mapOver();d.isCollection&&b.push(c)}),b},hasMappedOverInputTerminals:function(){var a=!1;return _.each(this.input_terminals,function(b){var c=b.mapOver();c.isCollection&&(a=!0)}),a},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()}),$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()}),$.each(this.output_terminals,function(a,b){b.destroy()}),this.app.workflow.remove_node(this),$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);!function(b){b.removeChild(a),b.appendChild(a)}(a.parentNode),$(a).removeClass("toolForm-active")},setLabel:function(a){this.app.workflow.updateNodeLabel(this.label,a),this.label=a||null},init_field_data:function(b){b.type&&(this.type=b.type),this.name=b.name,this.form_html=b.form_html,this.tool_state=b.tool_state,this.tool_errors=b.tool_errors,this.tooltip=b.tooltip?b.tooltip:"",this.annotation=b.annotation,this.post_job_actions=b.post_job_actions?b.post_job_actions:{},this.setLabel(b.label),this.uuid=b.uuid,this.workflow_outputs=b.workflow_outputs?b.workflow_outputs:[];var c=this,d=new a({el:this.element[0],node:c});c.nodeView=d,$.each(b.data_inputs,function(a,b){d.addDataInput(b)}),b.data_inputs.length>0&&b.data_outputs.length>0&&d.addRule(),$.each(b.data_outputs,function(a,b){d.addDataOutput(b)}),d.render(),this.app.workflow.node_changed(this,!0)},update_field_data:function(a){var b=this;if(nodeView=b.nodeView,this.tool_state=a.tool_state,this.form_html=a.form_html,this.tool_errors=a.tool_errors,this.annotation=a.annotation,this.setLabel(a.label),"post_job_actions"in a){var c=$.parseJSON(a.post_job_actions);this.post_job_actions=c?c:{}}b.nodeView.renderToolErrors();var d=nodeView.$("div.inputs"),e=nodeView.newInputsDiv(),f={};_.each(a.data_inputs,function(a){var c=b.nodeView.addDataInput(a,e);f[a.name]=c}),_.each(_.difference(_.values(nodeView.terminalViews),_.values(f)),function(a){a.el.terminal.destroy()}),nodeView.terminalViews=f,b.nodeView.render(),1==a.data_outputs.length&&"collection_type"in a.data_outputs[0]&&nodeView.updateDataOutput(a.data_outputs[0]),d.replaceWith(e),this.markChanged(),this.redraw()},error:function(a){var b=$(this.element).find(".toolFormBody");b.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+a+"</div>";this.form_html=c,b.html(c),this.app.workflow.node_changed(this)},markChanged:function(){this.app.workflow.node_changed(this)}});return b});
//# sourceMappingURL=../../../maps/mvc/workflow/workflow-node.js.map
@@ -1,2 +1,2 @@
define(["mvc/workflow/workflow-view-terminals","mvc/workflow/workflow-view-data"],function(a,b){return Backbone.View.extend({initialize:function(a){this.node=a.node,this.output_width=Math.max(150,this.$el.width()),this.tool_body=this.$el.find(".toolFormBody"),this.tool_body.find("div").remove(),this.newInputsDiv().appendTo(this.tool_body),this.terminalViews={},this.outputTerminlViews={}},render:function(){this.renderToolErrors(),this.$el.css("width",Math.min(250,Math.max(this.$el.width(),this.output_width)))},renderToolErrors:function(){this.node.tool_errors?this.$el.addClass("tool-node-error"):this.$el.removeClass("tool-node-error")},newInputsDiv:function(){return $("<div class='inputs'></div>")},updateMaxWidth:function(a){this.output_width=Math.max(this.output_width,a)},addRule:function(){this.tool_body.append($("<div class='rule'></div>"))},addDataInput:function(c,d){var e=!0;d||(d=this.$(".inputs"),e=!1);var f=this.terminalViews[c.name],g="dataset_collection"==c.input_type?a.InputCollectionTerminalView:a.InputTerminalView;if(!f||f instanceof g||(f.el.terminal.destroy(),f=null),f){var h=f.el.terminal;h.update(c),h.destroyInvalidConnections()}else f=new g({node:this.node,input:c});this.terminalViews[c.name]=f;var i=f.el,j=new b.DataInputView({terminalElement:i,input:c,nodeView:this,skipResize:e}),k=j.$el;return d.append(k.prepend(f.terminalElements())),f},addDataOutput:function(c){var d=c.collection?a.OutputCollectionTerminalView:a.OutputTerminalView,e=new d({node:this.node,output:c}),f=new b.DataOutputView({output:c,terminalElement:e.el,nodeView:this});this.tool_body.append(f.$el.append(e.terminalElements()))},updateDataOutput:function(a){var b=this.node.output_terminals[a.name];b.update(a)}})});
define(["mvc/workflow/workflow-view-terminals","mvc/workflow/workflow-view-data"],function(a,b){return Backbone.View.extend({initialize:function(a){this.node=a.node,this.output_width=Math.max(150,this.$el.width()),this.tool_body=this.$el.find(".toolFormBody"),this.tool_body.find("div").remove(),this.newInputsDiv().appendTo(this.tool_body),this.terminalViews={},this.outputTerminlViews={}},render:function(){var a,b=this.node.label;a=b?b:this.node.name,this.$el.find(".nodeTitle").text(a),this.renderToolErrors(),this.$el.css("width",Math.min(250,Math.max(this.$el.width(),this.output_width)))},renderToolErrors:function(){this.node.tool_errors?this.$el.addClass("tool-node-error"):this.$el.removeClass("tool-node-error")},newInputsDiv:function(){return $("<div class='inputs'></div>")},updateMaxWidth:function(a){this.output_width=Math.max(this.output_width,a)},addRule:function(){this.tool_body.append($("<div class='rule'></div>"))},addDataInput:function(c,d){var e=!0;d||(d=this.$(".inputs"),e=!1);var f=this.terminalViews[c.name],g="dataset_collection"==c.input_type?a.InputCollectionTerminalView:a.InputTerminalView;if(!f||f instanceof g||(f.el.terminal.destroy(),f=null),f){var h=f.el.terminal;h.update(c),h.destroyInvalidConnections()}else f=new g({node:this.node,input:c});this.terminalViews[c.name]=f;var i=f.el,j=new b.DataInputView({terminalElement:i,input:c,nodeView:this,skipResize:e}),k=j.$el;return d.append(k.prepend(f.terminalElements())),f},addDataOutput:function(c){var d=c.collection?a.OutputCollectionTerminalView:a.OutputTerminalView,e=new d({node:this.node,output:c}),f=new b.DataOutputView({output:c,terminalElement:e.el,nodeView:this});this.tool_body.append(f.$el.append(e.terminalElements()))},updateDataOutput:function(a){var b=this.node.output_terminals[a.name];b.update(a)}})});
//# sourceMappingURL=../../../maps/mvc/workflow/workflow-view-node.js.map
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,2 +1,2 @@
!function(){"use strict";window.console=window.console||{log:function(){},debug:function(){},info:function(){},warn:function(){},error:function(){},assert:function(){}},Object.assign=Object.assign||_.extend;for(var a=0,b=["ms","moz","webkit","o"],c=0;c<b.length&&!window.requestAnimationFrame;++c)window.requestAnimationFrame=window[b[c]+"RequestAnimationFrame"],window.cancelRequestAnimationFrame=window[b[c]+"CancelRequestAnimationFrame"];window.requestAnimationFrame||(window.requestAnimationFrame=function(b){var c=(new Date).getTime(),d=Math.max(0,16-(c-a)),e=window.setTimeout(function(){b(c+d)},d);return a=c+d,e}),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(a){clearTimeout(a)});var d=[{name:"canvas",compatible:function(){return window.CanvasRenderingContext2D}},{name:"sessionStorage",compatible:function(){try{return Number.isInteger(sessionStorage.length)}catch(a){}return!1}}];if(d=d.filter(function(a){return!a.compatible()}).map(function(a){return a.name}),d.length){var e=document.querySelectorAll('link[rel="index"]').item(0);e&&(window.location.href=e.href+"static/incompatible-browser.html"),console.log("incompatible browser:\n"+d.join("\n"))}}();
!function(){"use strict";window.console=window.console||{log:function(){},debug:function(){},info:function(){},warn:function(){},error:function(){},assert:function(){}},Object.assign=Object.assign||_.extend;for(var a=0,b=["ms","moz","webkit","o"],c=0;c<b.length&&!window.requestAnimationFrame;++c)window.requestAnimationFrame=window[b[c]+"RequestAnimationFrame"],window.cancelRequestAnimationFrame=window[b[c]+"CancelRequestAnimationFrame"];window.requestAnimationFrame||(window.requestAnimationFrame=function(b){var c=(new Date).getTime(),d=Math.max(0,16-(c-a)),e=window.setTimeout(function(){b(c+d)},d);return a=c+d,e}),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(a){clearTimeout(a)});var d=[{name:"canvas",compatible:function(){return window.CanvasRenderingContext2D}},{name:"sessionStorage",compatible:function(){try{return window.sessionStorage.length>=0}catch(a){}return!1}}],e=d.filter(function(a){return!a.compatible()}).map(function(a){return a.name});if(e.length){var f=document.querySelectorAll('link[rel="index"]').item(0);f&&(window.location=f.href+"static/incompatible-browser.html"),console.log("incompatible browser:\n"+e.join("\n"))}}();
//# sourceMappingURL=../maps/polyfills.js.map
File diff suppressed because one or more lines are too long
@@ -1,32 +0,0 @@
<% _=n_ %>
<%inherit file="/base.mako"/>
<%def name="title()">History options</%def>
<h2>${_('History Options')}</h2>
%if not user:
<div class="infomessage">
<div>${_('You must be ')}<a target="galaxy_main" href="${h.url_for( controller='user', action='login' )}">${_('logged in')}</a>${_(' to store or switch histories.')}</div>
</div>
%endif
<ul>
%if user:
<li><a href="${h.url_for( controller='history', action='list')}" target="galaxy_main">Previously</a> stored histories</li>
%if len( history.active_datasets ) > 0:
<li><a href="${h.url_for( controller='root', action='history_new' )}">Create</a> a new empty history</li>
<li><a href="${h.url_for( controller='workflow', action='build_from_current_history' )}">Construct workflow</a> from current history</li>
<li><a href="${h.url_for( controller='history', action='copy', id=trans.security.encode_id( history.id ) )}">Copy</a> current history</li>
%endif
<li><a href="${h.url_for( controller='history', action='share' )}" target="galaxy_main">Share</a> current history</div>
<li><a href="${h.url_for( controller='root', action='history_set_default_permissions' )}">Change default permissions</a> for current history</li>
%endif
%if len( history.activatable_datasets ) > 0:
<li><a href="${h.url_for( controller='root', action='history', show_deleted=True)}" target="galaxy_history">Show deleted</a> datasets in current history</li>
%endif
<li><a href="${h.url_for( controller='history', action='rename', id=trans.security.encode_id( history.id ) )}" target="galaxy_main">Rename</a> current history (stored as "${history.name}")</li>
<li><a href="${h.url_for( controller='history', action='delete_current' )}" confirm="Are you sure you want to delete the current history?">Delete</a> current history</div>
%if user and user.histories_shared_by_others:
<li><a href="${h.url_for( controller='history', action='list_shared')}" target="galaxy_main">Histories</a> shared with you by others</li>
%endif
</ul>
@@ -1,12 +1,31 @@
<form name="${form.name}" action="${h.url_for( controller='workflow', action='editor_form_post' )}" method="post">
<div class="toolForm">
<div class="toolFormTitle">${form.title}</div>
<div class="toolFormBody">
<%
from xml.sax.saxutils import escape
label = module.label
if label is not None:
title = label
else:
title = form.title
%>
<div class="ui-portlet-narrow">
<div class="portlet-header">
<div class="portlet-title">
<span class="portlet-title-text"><b>${title}</b></span>
</div>
</div>
<div class="portlet-content">
<div class="content">
<div class="ui-margin-top"></div>
<div>
<input type="hidden" name="type" value="${module.type}" />
<input type="hidden" name="label" value="${escape(label or '')}" />
<table class="ui-table-plain">
<thead></thead>
<tbody>
%if form.inputs:
%for input in form.inputs:
<%
cls = "form-row"
cls = "section-row"
if input.error:
cls += " form-row-error"
extra_attributes = ""
@@ -16,38 +35,37 @@
if input.type:
type_attribute = "type=\"input.type\""
%>
<div class="${cls}">
<label>
<tr class="${cls}"><td><div class="ui-table-form-element">
<div class="ui-table-form-title">
${input.label}:
</label>
<div style="float: left; width: 250px; margin-right: 10px;">
</div>
<div class="ui-table-form-field" style="display: block;">
<input ${type_attribute} name="${input.name | h}" value="${input.value | h}" size="30" ${extra_attributes}>
%if hasattr( input, "body_html" ):
${input.body_html()}
</input>
%endif
</div>
%if input.error:
<div style="float: left; color: red; font-weight: bold; padding-top: 1px; padding-bottom: 3px;">
<div style="width: 300px;"><img style="vertical-align: middle;" src="${h.url_for('/static/style/error_small.png')}">&nbsp;<span style="vertical-align: middle;">${input.error}</span></div>
</div>
%endif
%if input.error:
<div style="float: left; color: red; font-weight: bold; padding-top: 1px; padding-bottom: 3px;">
<div style="width: 300px;"><img style="vertical-align: middle;" src="${h.url_for('/static/style/error_small.png')}">&nbsp;<span style="vertical-align: middle;">${input.error}</span></div>
</div>
%endif
%if input.help:
<div class="toolParamHelp" style="clear: both;">
${input.help}
</div>
%endif
%if input.help:
<div class="ui-table-form-info">
${input.help}
</div>
%endif
</div><!-- ui-table-form-field -->
<div style="clear: both"></div>
</div>
</div></td></tr>
%endfor
%else:
<div class="form-row"><i>No options</i></div>
%endif
</tbody>
</table>
</div>
</div> <!-- content -->
</div><!-- portlet-content -->
</div>
</form>
-2
View File
@@ -245,8 +245,6 @@ class ToolsTestCase( api.ApiTestCase ):
'r2_0|text': "",
}
response = self._run( "validation_repeat", history_id, inputs )
import time
time.sleep(10)
self._assert_status_code_is( response, 400 )
@skip_without_tool( "multi_select" )
+24 -3
View File
@@ -128,7 +128,7 @@ class BaseWorkflowsApiTestCase( api.ApiTestCase, ImporterGalaxyInterface ):
assert source_type != "path"
jobs_descriptions = yaml.load( has_workflow )
test_data = jobs_descriptions["test_data"]
test_data = jobs_descriptions.get("test_data", {})
label_map = {}
inputs = {}
@@ -174,7 +174,8 @@ class BaseWorkflowsApiTestCase( api.ApiTestCase, ImporterGalaxyInterface ):
)
workflow_request[ "inputs" ] = dumps( label_map )
workflow_request[ "inputs_by" ] = 'name'
self.dataset_populator.wait_for_history( history_id, assert_ok=True )
if inputs:
self.dataset_populator.wait_for_history( history_id, assert_ok=True )
url = "workflows/%s/usage" % ( workflow_id )
invocation_response = self._post( url, data=workflow_request )
self._assert_status_code_is( invocation_response, 200 )
@@ -1039,13 +1040,33 @@ steps:
self.__assert_lines_hid_line_count_is( history_id, 3, 3 )
@skip_without_tool( "validation_default" )
def test_parameter_substitution_validation( self ):
def test_parameter_substitution_sanitization( self ):
substitions = dict( input1="\" ; echo \"moo" )
run_workflow_response, history_id = self._run_validation_workflow_with_substitions( substitions )
self.dataset_populator.wait_for_history( history_id, assert_ok=True )
self.assertEquals("__dq__ X echo __dq__moo\n", self.dataset_populator.get_history_dataset_content( history_id, hid=1 ) )
@skip_without_tool( "validation_repeat" )
def test_parameter_substitution_validation_value_errors_0( self ):
history_id = self.dataset_populator.new_history()
workflow_id = self._upload_yaml_workflow("""
class: GalaxyWorkflow
steps:
- tool_id: validation_repeat
state:
r2:
- text: "abd"
""")
workflow_request = dict(
history="hist_id=%s" % history_id,
parameters=dumps( dict( validation_repeat={"r2_0|text": ""} ) )
)
url = "workflows/%s/invocations" % workflow_id
invocation_response = self._post( url, data=workflow_request )
# Take a valid stat and make it invalid, assert workflow won't run.
self._assert_status_code_is( invocation_response, 400 )
@skip_without_tool( "validation_default" )
def test_parameter_substitution_validation_value_errors_1( self ):
substitions = dict( select_param="\" ; echo \"moo" )
+5 -14
View File
@@ -91,7 +91,7 @@ def _python_to_workflow(as_python, conversion_context):
as_python["steps"] = steps_as_dict
steps = steps_as_dict
for i, step in steps.iteritems():
for step in steps.itervalues():
step_type = step.get("type", None)
if "run" in step:
if step_type is not None:
@@ -113,7 +113,7 @@ def _python_to_workflow(as_python, conversion_context):
run_to_step_function(conversion_context, step, run_action)
del step["run"]
for i, step in steps.iteritems():
for step in steps.itervalues():
step_type = step.get("type", "tool")
step_type = STEP_TYPE_ALIASES.get(step_type, step_type)
if step_type not in STEP_TYPES:
@@ -148,14 +148,14 @@ def convert_inputs_to_steps(inputs, steps):
if "label" not in input_def and "id" not in input_def:
raise Exception("Input must define a label.")
raw_label = __rip_value(input_def, "label")
raw_id = __rip_value(input_def, "id")
raw_label = input_def.pop("label", None)
raw_id = input_def.pop("id", None)
label = raw_label or raw_id
if not label:
raise Exception("Input label must not be empty.")
input_type = __rip_value(input_def, "type", "data")
input_type = input_def.pop("type", "data")
if input_type in ["File", "data", "data_input"]:
step_type = "data_input"
elif input_type in ["collection", "data_collection", "data_collection_input"]:
@@ -380,15 +380,6 @@ def __join_prefix(prefix, key):
return new_key
def __rip_value(input_def, key, default=None):
if key in input_def:
value = input_def[key]
del input_def[key]
else:
value = default
return value
def __init_connect_dict(step):
if "connect" not in step:
step["connect"] = {}
+6
View File
@@ -280,6 +280,8 @@ class GalaxyInteractorApi( object ):
return wait
def __job_ready( self, job_id, history_id ):
if job_id is None:
raise ValueError("__job_ready passed empty job_id")
job_json = self._get( "jobs/%s" % job_id ).json()
state = job_json[ 'state' ]
try:
@@ -290,6 +292,8 @@ class GalaxyInteractorApi( object ):
raise
def __history_ready( self, history_id ):
if history_id is None:
raise ValueError("__history_ready passed empty history_id")
history_json = self._get( "histories/%s" % history_id ).json()
state = history_json[ 'state' ]
try:
@@ -300,6 +304,8 @@ class GalaxyInteractorApi( object ):
raise
def _summarize_history_errors( self, history_id ):
if history_id is None:
raise ValueError("_summarize_history_errors passed empty history_id")
print "History with id %s in error - summary of datasets in error below." % history_id
try:
history_contents = self.__contents( history_id )
@@ -67,10 +67,12 @@ spaceghost.test.begin( 'Test permissions for accessible, published, and inaccess
this.test.comment( 'show should work for history: ' + history.name );
this.test.assert( this.api.histories.show( history.id ).id === history.id,
'show worked' );
this.test.comment( 'copying should fail for history (multiple histories not allowed): ' + history.name );
this.api.assertRaises( function(){
this.api.histories.create({ history_id : history.id });
}, 403, 'API authentication required for this request', 'update authentication required' );
this.test.comment( 'copying should work for history (replacing the original history): ' + history.name );
var copiedHistory = this.api.histories.create({ history_id : history.id });
var historiesIndex = this.api.histories.index();
this.test.assert( historiesIndex.length === 1, 'only one history after copy' );
this.test.assert( historiesIndex[0].id === copiedHistory.id, 'original history with copy' );
// read functions for history contents
this.test.comment( 'index of history contents should work for history: ' + history.name );
@@ -99,7 +101,7 @@ spaceghost.test.begin( 'Test permissions for accessible, published, and inaccess
this.test.comment( 'copying should fail for history (implicit multiple histories): ' + history.name );
this.api.assertRaises( function(){
this.api.histories.create({ history_id : history.id });
}, 403, 'API authentication required for this request', 'copy failed with error' );
}, 403, 'History is not accessible by user', 'copy failed with error' );
// read functions for history contents
this.test.comment( 'index and show of history contents should fail for history: ' + history.name );
+3 -5
View File
@@ -23,6 +23,9 @@ spaceghost.test.begin( 'Test API functions for histories with an anonymous user'
this.test.assert( historyShow.id === index[0].id, 'Is the first history' );
this.test.assert( this.hasKeys( historyShow, [ 'id', 'name', 'user_id' ] ) );
this.test.comment( 'Calling create should work for an anonymous user' );
this.test.assert( this.api.histories.index().length === 1, 'Now has two histories' );
// ------------------------------------------------------------------------------------------- anon forbidden
//TODO: why not return the current history?
@@ -30,11 +33,6 @@ spaceghost.test.begin( 'Test API functions for histories with an anonymous user'
var recent = this.api.histories.show( 'most_recently_used' );
this.test.assert( recent.id === historyShow.id, 'most_recently_used returned current' );
this.test.comment( 'Calling create should fail for an anonymous user' );
this.api.assertRaises( function(){
this.api.histories.create({ name: 'new' });
}, 403, 'API authentication required for this request', 'create failed with error' );
this.test.comment( 'Calling delete should fail for an anonymous user' );
this.api.assertRaises( function(){
this.api.histories.delete_( historyShow.id );
+5 -5
View File
@@ -59,22 +59,22 @@ RUN mkdir /etc/galaxy && cd /tmp/ansible && mkdir roles && \
apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN cd $GALAXY_ROOT && \
echo "Prepopuating postgres database" && \
echo "Prepopulating postgres database" && \
su -c '/usr/lib/postgresql/9.3/bin/pg_ctl -o "-F" start -D /opt/galaxy/db' postgres && \
sleep 3 && \
GALAXY_CONFIG_DATABASE_CONNECTION="postgresql://root@localhost:5930/galaxy" sh create_db.sh && \
echo "Prepopuating sqlite database" && \
echo "Prepopulating sqlite database" && \
GALAXY_CONFIG_DATABASE_CONNECTION="sqlite:////opt/galaxy/galaxy.sqlite" sh create_db.sh && \
sh /opt/galaxy/start_mysql.sh && \
echo "Prepopuating mysql database" && \
echo "Prepopulating mysql database" && \
GALAXY_CONFIG_DATABASE_CONNECTION="mysql://galaxy:galaxy@localhost/galaxy?unix_socket=/var/run/mysqld/mysqld.sock" sh create_db.sh && \
echo "Prepopulating toolshed postgres database" && \
su -c '/usr/lib/postgresql/9.3/bin/pg_ctl -o "-F" start -D /opt/galaxy/db' postgres && \
GALAXY_CONFIG_DATABASE_CONNECTION="postgresql://root@localhost:5930/toolshed" sh create_db.sh tool_shed && \
echo "Prepopuating toolshed sqlite database" && \
echo "Prepopulating toolshed sqlite database" && \
GALAXY_CONFIG_DATABASE_CONNECTION="sqlite:////opt/galaxy/toolshed.sqlite" sh create_db.sh tool_shed && \
sh /opt/galaxy/start_mysql.sh && \
echo "Prepopuating toolshed mysql database" && \
echo "Prepopulating toolshed mysql database" && \
GALAXY_CONFIG_DATABASE_CONNECTION="mysql://galaxy:galaxy@localhost/toolshed?unix_socket=/var/run/mysqld/mysqld.sock" sh create_db.sh tool_shed
# bcftools for Galaxy.
+1 -1
View File
@@ -8,7 +8,7 @@ then
sleep 3
GALAXY_TEST_INSTALL_DB_MERGED="true"
GALAXY_TEST_DBURI="postgres://root@localhost:5930/galaxy?client_encoding=utf8"
TOOL_SHED_TEST_DBURI="postgres://root@localhost:5930/toolshed"
TOOL_SHED_TEST_DBURI="postgres://root@localhost:5930/toolshed?client_encoding=utf8"
elif [ "$GALAXY_TEST_DATABASE_TYPE" = "mysql" ];
then
sh /opt/galaxy/start_mysql.sh
+31 -8
View File
@@ -2,6 +2,7 @@
define([
"sinon-qunit",
"test-app",
'utils/utils',
"mvc/workflow/workflow-view",
"mvc/workflow/workflow-node",
"mvc/workflow/workflow-view-node",
@@ -11,6 +12,7 @@ define([
], function(
sinon,
testApp,
Utils,
App,
Node,
NodeView,
@@ -296,8 +298,8 @@ define([
setup: function() {
this.input_terminal = { destroy: sinon.spy(), redraw: sinon.spy() };
this.output_terminal = { destroy: sinon.spy(), redraw: sinon.spy() };
this.element = $("<div><div class='toolFormBody'></div></div>");
this.app = create_app();
this.element = this.app.$newNodeElement( "tool", "newnode" );
this.node = new Node( this.app, { element: this.element } );
this.node.input_terminals.i1 = this.input_terminal;
this.node.output_terminals.o1 = this.output_terminal;
@@ -311,22 +313,24 @@ define([
f();
ok( node_changed_spy.calledWith( node ) );
},
init_field_data_simple: function() {
var data = {
init_field_data_simple: function(option_overrides) {
var data = Utils.merge(option_overrides, {
data_inputs: [ {name: "input1", extensions: [ "data" ] } ],
data_outputs: [ {name: "output1", extensions: [ "data" ] } ],
};
label: null,
});
this.node.init_field_data( data );
},
update_field_data_with_new_input: function() {
var new_data = {
update_field_data_with_new_input: function(option_overrides) {
var new_data = Utils.merge(option_overrides, {
data_inputs: [
{ name: "input1", extensions: [ "data" ] },
{ name: "extra_0|input1", extensions: [ "data" ] },
],
data_outputs: [ {name: "output1", extensions: [ "data" ] } ],
post_job_actions: "{}"
};
post_job_actions: "{}",
label: "New Label"
});
this.node.update_field_data( new_data );
}
} );
@@ -368,6 +372,7 @@ define([
tooltip: "tool tooltip",
annotation: "tool annotation",
workflow_outputs: [ {"output_name": "out1"} ],
label: "Cat that data.",
};
node.init_field_data( data );
equal( node.type, "tool" );
@@ -376,6 +381,7 @@ define([
equal( node.tool_state, "ok" );
equal( node.tooltip, "tool tooltip" );
equal( node.annotation, "tool annotation" );
equal( node.label, "Cat that data." );
deepEqual( node.post_job_actions, {} );
deepEqual( node.workflow_outputs, [ {"output_name": "out1"} ] );
} );
@@ -394,9 +400,26 @@ define([
equal( test.$( ".input-terminal" ).length, 1 );
equal( test.$( ".rule" ).length, 1 );
equal( test.$( ".toolFormBody" ).children().length, 3 );
equal( test.$( ".nodeTitle" ).text(), "newnode" );
ok( test.$( ".toolFormTitle" ).find("i").hasClass("fa-wrench") );
} );
} );
test( "node title behavior", function() {
var test = this;
this.expect_workflow_node_changed( function( ) {
// Node created with name newnode
equal( test.$( ".nodeTitle" ).text(), "newnode" );
// init_field_data_simple doesn't change label, so it should
// remain original name.
test.init_field_data_simple();
equal( test.$( ".nodeTitle" ).text(), "newnode" );
// Despite awkward name, update does change the label...
test.update_field_data_with_new_input();
equal( test.$( ".nodeTitle" ).text(), "New Label" );
});
});
test( "update_field_data updated data inputs and outputs", function() {
var test = this;
this.expect_workflow_node_changed( function( ) {
@@ -60,7 +60,7 @@ class TestDataManagers( ShedTwillTestCase ):
owner=common.test_user_1_name,
category_id=self.security.encode_id( category.id ),
strings_displayed=[] )
# Upload the edited tool dependency definition to the package_lapack_3_4_1440 repository.
# Upload the data manager files to the repository.
self.upload_file( repository,
filename=data_manager_tar_file,
filepath=None,
+1 -1
View File
@@ -182,7 +182,7 @@ class UserSerializerTestCase( BaseTestCase ):
self.assertIsInstance( serialized[ 'nice_total_disk_usage' ], basestring )
self.assertIsInstance( serialized[ 'quota_percent' ], ( type( None ), float ) )
self.assertIsInstance( serialized[ 'tags_used' ], list )
self.assertIsInstance( serialized[ 'requests' ], list )
self.assertIsInstance( serialized[ 'has_requests' ], bool )
self.log( 'serialized should jsonify well' )
self.assertIsJsonifyable( serialized )
+2 -2
View File
@@ -19,7 +19,7 @@ def test_valid_new_tool_has_no_errors():
trans = MockTrans()
mock_tool = mock.Mock()
trans.app.toolbox.tools[ "cat1" ] = mock_tool
tool_module = modules.module_factory.new( trans, "tool", tool_id="cat1" )
tool_module = modules.module_factory.new( trans, "tool", content_id="cat1" )
assert not tool_module.get_errors()
@@ -194,7 +194,7 @@ def test_cannot_create_tool_modules_for_missing_tools():
trans = MockTrans()
exception = False
try:
modules.module_factory.new( trans, "tool", tool_id="cat1" )
modules.module_factory.new( trans, "tool", content_id="cat1" )
except Exception:
exception = True
assert exception