mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge branch 'dev' into feature/k8s_job_runner
This commit is contained in:
@@ -41,45 +41,82 @@ return Backbone.View.extend({
|
||||
}).on( 'show hide ', function() {
|
||||
self.buttonLoad.set( { 'toggle': this.visible, 'icon': this.visible && 'fa-eye' || 'fa-eye-slash' } );
|
||||
});
|
||||
this.history_cache = {};
|
||||
},
|
||||
|
||||
/** Add a dataset to the frames */
|
||||
addDataset: function( dataset_id ) {
|
||||
var self = this;
|
||||
var current_dataset = null;
|
||||
if ( Galaxy && Galaxy.currHistoryPanel ) {
|
||||
var history_id = Galaxy.currHistoryPanel.collection.historyId;
|
||||
this.history_cache[ history_id ] = { name: Galaxy.currHistoryPanel.model.get( 'name' ), dataset_ids: [] };
|
||||
Galaxy.currHistoryPanel.collection.each( function( model ) {
|
||||
!model.get( 'deleted' ) && model.get( 'visible' ) && self.history_cache[ history_id ].dataset_ids.push( model.get( 'id' ) );
|
||||
});
|
||||
}
|
||||
var _findDataset = function( dataset, offset ) {
|
||||
if ( dataset ) {
|
||||
var history_details = self.history_cache[ dataset.get( 'history_id' ) ];
|
||||
if ( history_details && history_details.dataset_ids ) {
|
||||
var dataset_list = history_details.dataset_ids;
|
||||
var pos = dataset_list.indexOf( dataset.get( 'id' ) );
|
||||
if ( pos !== -1 && pos + offset >= 0 && pos + offset < dataset_list.length ) {
|
||||
return dataset_list[ pos + offset ];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var _loadDatasetOffset = function( dataset, offset, frame ) {
|
||||
var new_dataset_id = _findDataset( dataset, offset );
|
||||
if ( new_dataset_id ) {
|
||||
self._loadDataset( new_dataset_id, function( new_dataset, config ) {
|
||||
current_dataset = new_dataset;
|
||||
frame.model.set( config );
|
||||
});
|
||||
} else {
|
||||
frame.model.trigger( 'change' );
|
||||
}
|
||||
}
|
||||
this._loadDataset( dataset_id, function( dataset, config ) {
|
||||
current_dataset = dataset;
|
||||
self.add( _.extend( { menu: [ { icon : 'fa fa-chevron-circle-left',
|
||||
tooltip : 'Previous in History',
|
||||
onclick : function( frame ) { _loadDatasetOffset( current_dataset, -1, frame ) },
|
||||
disabled : function() { return !_findDataset( current_dataset, -1 ) } },
|
||||
{ icon : 'fa fa-chevron-circle-right',
|
||||
tooltip : 'Next in History',
|
||||
onclick : function( frame ) { _loadDatasetOffset( current_dataset, 1, frame ) },
|
||||
disabled : function() { return !_findDataset( current_dataset, 1 ) } } ] }, config ) )
|
||||
});
|
||||
},
|
||||
|
||||
_loadDataset: function( dataset_id, callback ) {
|
||||
var self = this;
|
||||
require([ 'mvc/dataset/data' ], function( DATA ) {
|
||||
var dataset = new DATA.Dataset( { id : dataset_id } );
|
||||
$.when( dataset.fetch() ).then( function() {
|
||||
// Construct frame config based on dataset's type.
|
||||
var frame_config = {
|
||||
title: dataset.get('name')
|
||||
},
|
||||
// HACK: For now, assume 'tabular' and 'interval' are the only
|
||||
// modules that contain tabular files. This needs to be replaced
|
||||
// will a is_datatype() function.
|
||||
is_tabular = _.find( [ 'tabular', 'interval' ] , function( data_type ) {
|
||||
return dataset.get( 'data_type' ).indexOf( data_type ) !== -1;
|
||||
});
|
||||
|
||||
// Use tabular chunked display if dataset is tabular; otherwise load via URL.
|
||||
if ( is_tabular ) {
|
||||
var tabular_dataset = new DATA.TabularDataset( dataset.toJSON() );
|
||||
_.extend( frame_config, {
|
||||
content: function( parent_elt ) {
|
||||
DATA.createTabularDatasetChunkedView({
|
||||
model : tabular_dataset,
|
||||
parent_elt : parent_elt,
|
||||
embedded : true,
|
||||
height : '100%'
|
||||
});
|
||||
}
|
||||
});
|
||||
var is_tabular = _.find( [ 'tabular', 'interval' ] , function( data_type ) {
|
||||
return dataset.get( 'data_type' ).indexOf( data_type ) !== -1;
|
||||
});
|
||||
var title = dataset.get( 'name' );
|
||||
var history_details = self.history_cache[ dataset.get( 'history_id' ) ];
|
||||
if ( history_details ) {
|
||||
title = history_details.name + ': ' + title;
|
||||
}
|
||||
else {
|
||||
_.extend( frame_config, {
|
||||
url: Galaxy.root + 'datasets/' + dataset.id + '/display/?preview=True'
|
||||
});
|
||||
}
|
||||
self.add( frame_config );
|
||||
callback( dataset, is_tabular ? {
|
||||
title : title,
|
||||
url : null,
|
||||
content : DATA.createTabularDatasetChunkedView({
|
||||
model : new DATA.TabularDataset( dataset.toJSON() ),
|
||||
embedded : true,
|
||||
height : '100%'
|
||||
}).$el
|
||||
} : {
|
||||
title : title,
|
||||
url : Galaxy.root + 'datasets/' + dataset_id + '/display/?preview=True',
|
||||
content : null
|
||||
} );
|
||||
});
|
||||
});
|
||||
},
|
||||
@@ -136,15 +173,9 @@ return Backbone.View.extend({
|
||||
window.location = options.url;
|
||||
} else if ( !this.active ) {
|
||||
var $galaxy_main = $( window.parent.document ).find( '#galaxy_main' );
|
||||
if ( options.target == 'galaxy_main' || options.target == 'center' ){
|
||||
if ( $galaxy_main.length === 0 ){
|
||||
var href = options.url;
|
||||
if ( href.indexOf( '?' ) == -1 )
|
||||
href += '?';
|
||||
else
|
||||
href += '&';
|
||||
href += 'use_panels=True';
|
||||
window.location = href;
|
||||
if ( options.target == 'galaxy_main' || options.target == 'center' ) {
|
||||
if ( $galaxy_main.length === 0 ) {
|
||||
window.location = options.url + ( href.indexOf( '?' ) == -1 ? '?' : '&' ) + 'use_panels=True';
|
||||
} else {
|
||||
$galaxy_main.attr( 'src', options.url );
|
||||
}
|
||||
|
||||
@@ -435,6 +435,7 @@ var ControlledFetchMixin = {
|
||||
_.each( filters, function( v, k ){
|
||||
if( v === true ){ v = 'True'; }
|
||||
if( v === false ){ v = 'False'; }
|
||||
if( v === null ){ v = 'None'; }
|
||||
filterMap.q.push( k );
|
||||
filterMap.qv.push( v );
|
||||
});
|
||||
@@ -522,6 +523,11 @@ var HistoryCollection = Backbone.Collection
|
||||
deleted : false,
|
||||
purged : false,
|
||||
};
|
||||
} else {
|
||||
defaults.filters = {
|
||||
// TODO: for bypassing defaults on current API
|
||||
deleted : null,
|
||||
};
|
||||
}
|
||||
return defaults;
|
||||
},
|
||||
|
||||
@@ -1,46 +1,40 @@
|
||||
/**
|
||||
This is the run workflow tool form.
|
||||
*/
|
||||
define([ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-data', 'mvc/tool/tool-form-base' ],
|
||||
function( Utils, Ui, Form, FormData, ToolFormBase ) {
|
||||
/** This is the run workflow tool form view. */
|
||||
define([ 'utils/utils', 'utils/deferred', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-data', 'mvc/tool/tool-form-base' ],
|
||||
function( Utils, Deferred, Ui, Form, FormData, ToolFormBase ) {
|
||||
var View = Backbone.View.extend({
|
||||
initialize: function( options ) {
|
||||
this.model = options && options.model || new Backbone.Model( options );
|
||||
this.deferred = new Deferred();
|
||||
this.setElement( $( '<div/>' ).addClass( 'ui-form-composite' )
|
||||
.append( this.$message = $( '<div/>' ) )
|
||||
.append( this.$header = $( '<div/>' ) )
|
||||
.append( this.$parameters = $( '<div/>' ) )
|
||||
.append( this.$steps = $( '<div/>' ) )
|
||||
.append( this.$history = $( '<div/>' ) )
|
||||
.append( this.$execute = $( '<div/>' ) ) );
|
||||
$( 'body' ).append( this.$el );
|
||||
this._configure();
|
||||
this.render();
|
||||
},
|
||||
|
||||
/** Configures form/step options for each workflow step */
|
||||
_configure: function() {
|
||||
var self = this;
|
||||
this.workflow_id = options.id;
|
||||
this.forms = [];
|
||||
this.steps = [];
|
||||
this.links = [];
|
||||
|
||||
// initialize elements
|
||||
this.setElement( '<div class="ui-form-composite"/>' );
|
||||
this.$header = $( '<div/>' ).addClass( 'ui-form-header' );
|
||||
this.$header.append( new Ui.Label({
|
||||
title : 'Workflow: ' + options.name
|
||||
}).$el );
|
||||
this.$header.append( new Ui.Button({
|
||||
title : 'Collapse',
|
||||
icon : 'fa-angle-double-up',
|
||||
onclick : function() { _.each( self.forms, function( form ) { form.portlet.collapse() }) }
|
||||
}).$el );
|
||||
this.$header.append( new Ui.Button({
|
||||
title : 'Expand all',
|
||||
icon : 'fa-angle-double-down',
|
||||
onclick : function() { _.each( self.forms, function( form ) { form.portlet.expand() }) }
|
||||
}).$el );
|
||||
this.$el.append( this.$header );
|
||||
|
||||
// initialize steps and configure connections
|
||||
_.each( options.steps, function( step, i ) {
|
||||
this.parms = [];
|
||||
_.each( this.model.get( 'steps' ), function( step, i ) {
|
||||
Galaxy.emit.debug( 'tool-form-composite::initialize()', i + ' : Preparing workflow step.' );
|
||||
step = Utils.merge( {
|
||||
index : i,
|
||||
name : 'Step ' + ( parseInt( i ) + 1 ) + ': ' + step.name,
|
||||
icon : '',
|
||||
help : null,
|
||||
description : step.annotation && ' - ' + step.annotation || step.description,
|
||||
citations : null,
|
||||
needs_update : true,
|
||||
collapsible : true,
|
||||
collapsed : i > 0,
|
||||
collapsed : i > 0 && !self._isDataStep( step ),
|
||||
sustain_version : true,
|
||||
sustain_repeats : true,
|
||||
sustain_conditionals : true,
|
||||
@@ -48,155 +42,256 @@ define([ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-d
|
||||
text_enable : 'Edit',
|
||||
text_disable : 'Undo',
|
||||
cls_enable : 'fa fa-edit',
|
||||
cls_disable : 'fa fa-undo'
|
||||
cls_disable : 'fa fa-undo',
|
||||
errors : step.messages,
|
||||
initial_errors : true
|
||||
}, step );
|
||||
// convert all connected data inputs to hidden fields with proper labels
|
||||
_.each( options.steps, function( sub_step ) {
|
||||
self.steps[ i ] = step;
|
||||
self.links[ i ] = [];
|
||||
self.parms[ i ] = {}
|
||||
});
|
||||
|
||||
// build linear index of step input pairs
|
||||
_.each( this.steps, function( step, i ) {
|
||||
FormData.visitInputs( step.inputs, function( input, name ) {
|
||||
self.parms[ i ][ name ] = input;
|
||||
});
|
||||
});
|
||||
|
||||
// iterate through data input modules and collect linked sub steps
|
||||
_.each( this.steps, function( step, i ) {
|
||||
_.each( step.output_connections, function( output_connection ) {
|
||||
_.each( self.steps, function( sub_step, j ) {
|
||||
sub_step.step_id === output_connection.input_step_id && self.links[ i ].push( sub_step );
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// convert all connected data inputs to hidden fields with proper labels,
|
||||
// and track the linked source step
|
||||
_.each( this.steps, function( step, i ) {
|
||||
_.each( self.steps, function( sub_step, j ) {
|
||||
var connections_by_name = {};
|
||||
_.each( step.output_connections, function( connection ) {
|
||||
sub_step.step_id === connection.input_step_id && ( connections_by_name[ connection.input_name ] = connection );
|
||||
});
|
||||
FormData.matchIds( sub_step.inputs, connections_by_name, function( connection, input ) {
|
||||
if ( !input.linked ) {
|
||||
input.linked = step.step_type;
|
||||
_.each( self.parms[ j ], function( input, name ) {
|
||||
var connection = connections_by_name[ name ];
|
||||
if ( connection ) {
|
||||
input.type = 'hidden';
|
||||
input.help = '';
|
||||
} else {
|
||||
input.help += ', ';
|
||||
}
|
||||
input.help += 'Output dataset \'' + connection.output_name + '\' from step ' + ( parseInt( i ) + 1 );
|
||||
});
|
||||
});
|
||||
self.steps[ i ] = step;
|
||||
self.links[ i ] = [];
|
||||
});
|
||||
|
||||
// finalize configuration and build forms
|
||||
_.each( self.steps, function( step, i ) {
|
||||
var form = null;
|
||||
if ( String( step.step_type ).startsWith( 'data' ) ) {
|
||||
form = new Form( Utils.merge({
|
||||
title : '<b>' + step.name + '</b>',
|
||||
onchange: function() {
|
||||
var input_value = form.data.create().input;
|
||||
_.each( self.links[ i ], function( link ) {
|
||||
link.input.value ( input_value );
|
||||
link.form.trigger( 'change' );
|
||||
});
|
||||
}
|
||||
}, step ));
|
||||
} else if ( step.step_type == 'tool' ) {
|
||||
// select fields are shown for dynamic fields if all putative data inputs are available
|
||||
function visitInputs( inputs, data_resolved ) {
|
||||
data_resolved === undefined && ( data_resolved = true );
|
||||
_.each( inputs, function ( input ) {
|
||||
if ( _.isObject( input ) ) {
|
||||
if ( input.type ) {
|
||||
var is_data_input = [ 'data', 'data_collection' ].indexOf( input.type ) !== -1;
|
||||
var is_workflow_parameter = self._isWorkflowParameter( input.value );
|
||||
is_data_input && input.linked && !input.linked.startsWith( 'data' ) && ( data_resolved = false );
|
||||
input.options && ( ( input.options.length == 0 && !data_resolved ) || is_workflow_parameter ) && ( input.is_workflow = true );
|
||||
input.value && input.value.__class__ == 'RuntimeValue' && ( input.value = null );
|
||||
if ( !is_data_input && input.type !== 'hidden' && !is_workflow_parameter ) {
|
||||
if ( input.optional || ( !Utils.isEmpty( input.value ) && input.value !== '' ) ) {
|
||||
input.collapsible_value = input.value;
|
||||
input.collapsible_preview = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
visitInputs( input, data_resolved );
|
||||
}
|
||||
});
|
||||
};
|
||||
visitInputs( step.inputs );
|
||||
// or if a particular reference is specified and available
|
||||
FormData.matchContext( step.inputs, 'data_ref', function( input, reference ) {
|
||||
input.is_workflow = ( reference.linked && !reference.linked.startsWith( 'data' ) ) || self._isWorkflowParameter( input.value );
|
||||
});
|
||||
form = new ToolFormBase( step );
|
||||
}
|
||||
self.forms[ i ] = form;
|
||||
});
|
||||
|
||||
// create index of data output links
|
||||
_.each( this.steps, function( step, i ) {
|
||||
_.each( step.output_connections, function( output_connection ) {
|
||||
_.each( self.forms, function( form ) {
|
||||
if ( form.options.step_id === output_connection.input_step_id ) {
|
||||
var matched_input = form.field_list[ form.data.match( output_connection.input_name ) ];
|
||||
matched_input && self.links[ i ].push( { input: matched_input, form: form } );
|
||||
input.help = input.step_linked ? input.help + ', ' : '';
|
||||
input.help += 'Output dataset \'' + connection.output_name + '\' from step ' + ( parseInt( i ) + 1 );
|
||||
input.step_linked = input.step_linked || [];
|
||||
input.step_linked.push( step );
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// build workflow parameters
|
||||
var wp_fields = {};
|
||||
var wp_inputs = {};
|
||||
// identify and configure workflow parameters
|
||||
var wp_count = 0;
|
||||
var wp_style = function( wp_field, wp_color, wp_cls ) {
|
||||
var $wp_input = wp_field.$( 'input' );
|
||||
$wp_input.length === 0 && ( $wp_input = wp_field.$el );
|
||||
$wp_input.addClass( wp_cls ).css({ 'color': wp_color, 'border-color': wp_color });
|
||||
this.wp_inputs = {};
|
||||
function _handleWorkflowParameter( value, callback ) {
|
||||
var wp_name = self._isWorkflowParameter( value );
|
||||
wp_name && callback( self.wp_inputs[ wp_name ] = self.wp_inputs[ wp_name ] || {
|
||||
label : wp_name,
|
||||
name : wp_name,
|
||||
type : 'text',
|
||||
color : 'hsl( ' + ( ++wp_count * 100 ) + ', 70%, 30% )',
|
||||
style : 'ui-form-wp-source',
|
||||
links : []
|
||||
});
|
||||
}
|
||||
_.each( this.steps, function( step, i ) {
|
||||
_.each( step.inputs, function( input ) {
|
||||
var wp_name = self._isWorkflowParameter( input.value );
|
||||
if ( wp_name ) {
|
||||
var wp_field = self.forms[ i ].field_list[ input.id ];
|
||||
var wp_element = self.forms[ i ].element_list[ input.id ];
|
||||
wp_fields[ wp_name ] = wp_fields[ wp_name ] || [];
|
||||
wp_fields[ wp_name ].push( wp_field );
|
||||
wp_field.value( wp_name );
|
||||
wp_element.disable( true );
|
||||
wp_inputs[ wp_name ] = wp_inputs[ wp_name ] || {
|
||||
type : input.type,
|
||||
is_workflow : input.options,
|
||||
label : wp_name,
|
||||
name : wp_name,
|
||||
color : 'hsl( ' + ( ++wp_count * 100 ) + ', 70%, 30% )'
|
||||
};
|
||||
wp_style( wp_field, wp_inputs[ wp_name ].color, 'ui-form-wp-target' );
|
||||
}
|
||||
_.each( self.parms[ i ], function( input, name ) {
|
||||
_handleWorkflowParameter( input.value, function( wp_input ) {
|
||||
wp_input.links.push( step );
|
||||
input.wp_linked = wp_input.name;
|
||||
input.color = wp_input.color;
|
||||
input.type = 'text';
|
||||
input.value = null;
|
||||
input.backdrop = true;
|
||||
input.style = 'ui-form-wp-target';
|
||||
});
|
||||
});
|
||||
_.each( step.post_job_actions, function( pja ) {
|
||||
_.each( pja.action_arguments, function( arg ) {
|
||||
_handleWorkflowParameter( arg, function() {} );
|
||||
});
|
||||
});
|
||||
});
|
||||
if ( !_.isEmpty( wp_inputs ) ) {
|
||||
var wp_form = new Form({ title: '<b>Workflow Parameters</b>', inputs: wp_inputs, onchange: function() {
|
||||
_.each( wp_form.data.create(), function( wp_value, wp_name ) {
|
||||
_.each( wp_fields[ wp_name ], function( wp_field ) {
|
||||
wp_field.value( Utils.sanitize( wp_value ) || wp_name );
|
||||
|
||||
// select fields are shown for dynamic fields if all putative data inputs are available,
|
||||
// or if an explicit reference is specified as data_ref and available
|
||||
_.each( this.steps, function( step, i ) {
|
||||
if ( step.step_type == 'tool' ) {
|
||||
var data_resolved = true;
|
||||
FormData.visitInputs( step.inputs, function ( input, name, context ) {
|
||||
var is_data_input = ([ 'data', 'data_collection' ]).indexOf( input.type ) != -1;
|
||||
var data_ref = context[ input.data_ref ];
|
||||
input.step_linked && !self._isDataStep( input.step_linked ) && ( data_resolved = false );
|
||||
input.options && ( ( input.options.length == 0 && !data_resolved ) || input.wp_linked ) && ( input.is_workflow = true );
|
||||
data_ref && ( input.is_workflow = ( data_ref.step_linked && !self._isDataStep( data_ref.step_linked ) ) || input.wp_linked );
|
||||
( is_data_input || ( input.value && input.value.__class__ == 'RuntimeValue' && !input.step_linked ) ) && ( step.collapsed = false );
|
||||
input.value && input.value.__class__ == 'RuntimeValue' && ( input.value = null );
|
||||
input.flavor = 'workflow';
|
||||
if ( !is_data_input && input.type !== 'hidden' && !input.wp_linked ) {
|
||||
if ( input.optional || ( !Utils.isEmpty( input.value ) && input.value !== '' ) ) {
|
||||
input.collapsible_value = input.value;
|
||||
input.collapsible_preview = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
this.deferred.reset();
|
||||
this._renderHeader();
|
||||
this._renderMessage();
|
||||
this._renderParameters();
|
||||
this._renderHistory();
|
||||
_.each ( this.steps, function( step, i ) { self._renderStep( step, i ) } );
|
||||
this.deferred.execute( function() { self._renderExecute() } );
|
||||
},
|
||||
|
||||
/** Render header */
|
||||
_renderHeader: function() {
|
||||
var self = this;
|
||||
this.$header.addClass( 'ui-form-header' ).empty()
|
||||
.append( new Ui.Label({
|
||||
title : 'Workflow: ' + this.model.get( 'name' ) }).$el )
|
||||
.append( new Ui.Button({
|
||||
title : 'Collapse',
|
||||
icon : 'fa-angle-double-up',
|
||||
onclick : function() { _.each( self.forms, function( form ) { form.portlet.collapse() }) } }).$el )
|
||||
.append( new Ui.Button({
|
||||
title : 'Expand all',
|
||||
icon : 'fa-angle-double-down',
|
||||
onclick : function() { _.each( self.forms, function( form ) { form.portlet.expand() }) } }).$el );
|
||||
},
|
||||
|
||||
/** Render message */
|
||||
_renderMessage: function() {
|
||||
this.$message.empty();
|
||||
if ( this.model.get( 'has_upgrade_messages' ) ) {
|
||||
this.$message.append( new Ui.Message( {
|
||||
message : 'Some tools in this workflow may have changed since it was last saved or some errors were found. The workflow may still run, but any new options will have default values. Please review the messages below to make a decision about whether the changes will affect your analysis.',
|
||||
status : 'warning',
|
||||
persistent : true
|
||||
} ).$el );
|
||||
}
|
||||
},
|
||||
|
||||
/** Render workflow parameters */
|
||||
_renderParameters: function() {
|
||||
var self = this;
|
||||
this.wp_form = null;
|
||||
if ( !_.isEmpty( this.wp_inputs ) ) {
|
||||
this.wp_form = new Form({ title: '<b>Workflow Parameters</b>', inputs: this.wp_inputs, onchange: function() {
|
||||
_.each( self.wp_form.input_list, function( input_def, i ) {
|
||||
_.each( input_def.links, function( step ) {
|
||||
self._refreshStep( step );
|
||||
});
|
||||
});
|
||||
}});
|
||||
_.each( wp_form.field_list, function( wp_field, i ) {
|
||||
wp_style( wp_field, wp_form.input_list[ i ].color, 'ui-form-wp-source' );
|
||||
});
|
||||
this.$el.append( '<p/>' ).addClass( 'ui-margin-top' );
|
||||
this.$el.append( wp_form.$el );
|
||||
this._append( this.$parameters.empty(), this.wp_form.$el );
|
||||
}
|
||||
},
|
||||
|
||||
// append elements
|
||||
_.each( this.steps, function( step, i ) {
|
||||
var form = self.forms[ i ];
|
||||
self.$el.append( '<p/>' ).addClass( 'ui-margin-top' ).append( form.$el );
|
||||
if ( step.post_job_actions && step.post_job_actions.length ) {
|
||||
form.portlet.append( $( '<div/>' ).addClass( 'ui-form-footer-info fa fa-bolt' ).append(
|
||||
_.reduce( step.post_job_actions, function( memo, value ) {
|
||||
return memo + ' ' + value.short_str;
|
||||
}, '' ))
|
||||
);
|
||||
/** Render step */
|
||||
_renderStep: function( step, i ) {
|
||||
var self = this;
|
||||
var form = null;
|
||||
var current = null;
|
||||
this.deferred.execute( function( promise ) {
|
||||
current = promise;
|
||||
if ( self._isDataStep( step ) ) {
|
||||
_.each( step.inputs, function( input ) { input.flavor = 'module' } );
|
||||
form = new Form( Utils.merge({
|
||||
title : '<b>' + step.name + '</b>',
|
||||
onchange : function() { _.each( self.links[ i ], function( link ) { self._refreshStep( link ) } ) }
|
||||
}, step ) );
|
||||
self._append( self.$steps, form.$el );
|
||||
} else if ( step.step_type == 'tool' ) {
|
||||
form = new ToolFormBase( step );
|
||||
if ( step.post_job_actions && step.post_job_actions.length ) {
|
||||
form.portlet.append( $( '<div/>' ).addClass( 'ui-form-element-disabled' )
|
||||
.append( $( '<div/>' ).addClass( 'ui-form-title' ).html( 'Job Post Actions' ) )
|
||||
.append( $( '<div/>' ).addClass( 'ui-form-preview' ).html(
|
||||
_.reduce( step.post_job_actions, function( memo, value ) {
|
||||
return memo + ' ' + value.short_str;
|
||||
}, '' ) ) )
|
||||
);
|
||||
}
|
||||
self._append( self.$steps, form.$el );
|
||||
}
|
||||
self.forms[ i ] = form;
|
||||
self._refreshStep( step );
|
||||
Galaxy.emit.debug( 'tool-form-composite::initialize()', i + ' : Workflow step state ready.', step );
|
||||
});
|
||||
self._resolve( form.deferred, promise );
|
||||
} );
|
||||
},
|
||||
|
||||
// add history form
|
||||
/** This helps with rendering lazy loaded steps */
|
||||
_resolve: function( deferred, promise ) {
|
||||
var self = this;
|
||||
setTimeout( function() {
|
||||
if ( deferred && deferred.ready() || !deferred ) {
|
||||
promise.resolve();
|
||||
} else {
|
||||
self._resolve( deferred, promise );
|
||||
}
|
||||
}, 0 );
|
||||
},
|
||||
|
||||
/** Refreshes step values from source step values */
|
||||
_refreshStep: function( step ) {
|
||||
var self = this;
|
||||
var form = this.forms[ step.index ];
|
||||
if ( form ) {
|
||||
_.each( self.parms[ step.index ], function( input, name ) {
|
||||
if ( input.step_linked || input.wp_linked ) {
|
||||
var field = form.field_list[ form.data.match( name ) ];
|
||||
if ( field ) {
|
||||
var new_value = undefined;
|
||||
if ( input.step_linked ) {
|
||||
new_value = { values: [] };
|
||||
_.each( input.step_linked, function( source_step ) {
|
||||
if ( self._isDataStep( source_step ) ) {
|
||||
value = self.forms[ source_step.index ].data.create().input;
|
||||
value && _.each( value.values, function( v ) { new_value.values.push( v ) } );
|
||||
}
|
||||
});
|
||||
if ( !input.multiple && new_value.values.length > 0 ) {
|
||||
new_value = { values: [ new_value.values[ 0 ] ] };
|
||||
}
|
||||
} else if ( input.wp_linked ) {
|
||||
var wp_field = self.wp_form.field_list[ self.wp_form.data.match( input.wp_linked ) ];
|
||||
wp_field && ( new_value = wp_field.value() );
|
||||
}
|
||||
if ( new_value !== undefined ) {
|
||||
field.value( new_value );
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
form.trigger( 'change' );
|
||||
}
|
||||
},
|
||||
|
||||
/** Render history form */
|
||||
_renderHistory: function() {
|
||||
this.history_form = null;
|
||||
if ( !options.history_id ) {
|
||||
if ( !this.model.get( 'history_id' ) ) {
|
||||
this.history_form = new Form({
|
||||
inputs : [{
|
||||
type : 'conditional',
|
||||
name : 'new_history',
|
||||
test_param : {
|
||||
name : 'new_history',
|
||||
name : 'check',
|
||||
label : 'Send results to a new history',
|
||||
type : 'boolean',
|
||||
value : 'false',
|
||||
@@ -205,20 +300,21 @@ define([ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-d
|
||||
cases : [{
|
||||
value : 'true',
|
||||
inputs : [{
|
||||
name : 'new_history_name',
|
||||
name : 'name',
|
||||
label : 'History name',
|
||||
type : 'text',
|
||||
value : options.name
|
||||
value : this.model.get( 'name' )
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
});
|
||||
this.$el.append( '<p/>' ).addClass( 'ui-margin-top' );
|
||||
this.$el.append( this.history_form.$el );
|
||||
this._append( this.$history.empty(), this.history_form.$el );
|
||||
}
|
||||
},
|
||||
|
||||
// add execute button
|
||||
this.$el.append( '<p/>' ).addClass( 'ui-margin-top' );
|
||||
/** Render execute button */
|
||||
_renderExecute: function() {
|
||||
var self = this;
|
||||
this.execute_btn = new Ui.Button({
|
||||
icon : 'fa-check',
|
||||
title : 'Run workflow',
|
||||
@@ -226,81 +322,84 @@ define([ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-d
|
||||
floating : 'clear',
|
||||
onclick : function() { self._execute() }
|
||||
});
|
||||
this.$el.append( this.execute_btn.$el );
|
||||
$( 'body' ).append( this.$el );
|
||||
this._append( this.$execute.empty(), this.execute_btn.$el );
|
||||
},
|
||||
|
||||
/** Execute workflow
|
||||
*/
|
||||
/** Execute workflow */
|
||||
_execute: function() {
|
||||
var self = this;
|
||||
var job_def = {
|
||||
inputs : {},
|
||||
parameters : {}
|
||||
new_history_name : this.history_form.data.create()[ 'new_history|name' ],
|
||||
wf_parm : this.wp_form ? this.wp_form.data.create() : {},
|
||||
inputs : {}
|
||||
};
|
||||
var validated = true;
|
||||
_.each( this.forms, function( form, i ) {
|
||||
for ( var i in this.forms ) {
|
||||
var form = this.forms[ i ];
|
||||
var job_inputs = form.data.create();
|
||||
var step = self.steps[ i ];
|
||||
var step_id = step.step_id;
|
||||
var step_type = step.step_type;
|
||||
var order_index = step.order_index;
|
||||
job_def.parameters[ step_id ] = {};
|
||||
form.trigger( 'reset' );
|
||||
for ( var job_input_id in job_inputs ) {
|
||||
var input_value = job_inputs[ job_input_id ];
|
||||
var input_id = form.data.match( job_input_id );
|
||||
var input_field = form.field_list[ input_id ];
|
||||
var input_def = form.input_list[ input_id ];
|
||||
if ( String( step_type ).startsWith( 'data' ) ) {
|
||||
if ( input_value && input_value.values && input_value.values.length > 0 ) {
|
||||
job_def.inputs[ order_index ] = input_value.values[ 0 ];
|
||||
} else if ( validated ) {
|
||||
if ( !input_def.step_linked ) {
|
||||
if ( this._isDataStep( step ) ) {
|
||||
validated = input_value && input_value.values && input_value.values.length > 0;
|
||||
} else {
|
||||
validated = input_def.optional || ( input_def.is_workflow && input_value !== '' ) || ( !input_def.is_workflow && input_value !== null );
|
||||
}
|
||||
if ( !validated ) {
|
||||
form.highlight( input_id );
|
||||
validated = false;
|
||||
}
|
||||
} else {
|
||||
if ( !String( input_def.type ).startsWith( 'data' ) ) {
|
||||
if ( input_def.optional || input_def.is_workflow || input_value != null ) {
|
||||
job_def.parameters[ step_id ][ job_input_id ] = input_value;
|
||||
} else {
|
||||
form.highlight( input_id );
|
||||
validated = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
job_def.inputs[ step_id ] = job_def.inputs[ step_id ] || {};
|
||||
job_def.inputs[ step_id ][ job_input_id ] = job_inputs[ job_input_id ];
|
||||
}
|
||||
}
|
||||
});
|
||||
console.log( JSON.stringify( job_def ) );
|
||||
if ( !validated ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !validated ) {
|
||||
self._enabled( true );
|
||||
Galaxy.emit.debug( 'tool-form-composite::submit()', 'Validation failed.', job_def );
|
||||
} else {
|
||||
self._enabled( false );
|
||||
Galaxy.emit.debug( 'tools-form-composite::submit()', 'Validation complete.', job_def );
|
||||
Galaxy.emit.debug( 'tool-form-composite::submit()', 'Validation complete.', job_def );
|
||||
Utils.request({
|
||||
type : 'POST',
|
||||
url : Galaxy.root + 'api/workflows/' + this.workflow_id + '/invocations',
|
||||
data : job_def,
|
||||
success : function( response ) {
|
||||
Galaxy.emit.debug( 'tool-form-composite::submit', 'Submission successful.', response );
|
||||
self.$el.empty().append( self._templateSuccess( response ) );
|
||||
parent.Galaxy && parent.Galaxy.currHistoryPanel && parent.Galaxy.currHistoryPanel.refreshContents();
|
||||
console.log( response );
|
||||
},
|
||||
error : function( response ) {
|
||||
console.log( response );
|
||||
Galaxy.emit.debug( 'tool-form-composite::submit', 'Submission failed.', response );
|
||||
if ( response && response.err_data ) {
|
||||
var error_messages = form.data.matchResponse( response.err_data );
|
||||
for ( var input_id in error_messages ) {
|
||||
form.highlight( input_id, error_messages[ input_id ] );
|
||||
break;
|
||||
for ( var i in self.forms ) {
|
||||
var form = self.forms[ i ];
|
||||
var step_related_errors = response.err_data[ form.options.step_id ];
|
||||
if ( step_related_errors ) {
|
||||
var error_messages = form.data.matchResponse( step_related_errors );
|
||||
for ( var input_id in error_messages ) {
|
||||
form.highlight( input_id, error_messages[ input_id ] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Galaxy.modal && Galaxy.modal.show({
|
||||
var modal = parent.Galaxy.modal;
|
||||
modal && modal.show({
|
||||
title : 'Job submission failed',
|
||||
body : ( response && response.err_msg ) || ToolTemplate.error( options.job_def ),
|
||||
body : self._templateError( response && response.err_msg || job_def ),
|
||||
buttons : {
|
||||
'Close' : function() {
|
||||
Galaxy.modal.hide();
|
||||
modal.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -313,23 +412,69 @@ define([ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-d
|
||||
}
|
||||
},
|
||||
|
||||
/** Set enabled/disabled state
|
||||
*/
|
||||
/** Append new dom to body */
|
||||
_append: function( $container, $el ) {
|
||||
$container.append( '<p/>' ).addClass( 'ui-margin-top' ).append( $el );
|
||||
},
|
||||
|
||||
/** Set enabled/disabled state */
|
||||
_enabled: function( enabled ) {
|
||||
if ( enabled ) { this.execute_btn.unwait() } else { this.execute_btn.wait() }
|
||||
if ( enabled ) { this.history_form.portlet.enable() } else { this.history_form.portlet.disable() }
|
||||
_.each( this.forms, function( form ) { if ( enabled ) { form.portlet.enable() } else { form.portlet.disable() } });
|
||||
},
|
||||
|
||||
/** Handle workflow parameter
|
||||
*/
|
||||
/** Handle workflow parameter */
|
||||
_isWorkflowParameter: function( value ) {
|
||||
if ( String( value ).substring( 0, 1 ) === '$' ) {
|
||||
return Utils.sanitize( value.substring( 2, value.length - 1 ) )
|
||||
}
|
||||
},
|
||||
|
||||
/** Is data input module/step */
|
||||
_isDataStep: function( steps ) {
|
||||
lst = $.isArray( steps ) ? steps : [ steps ] ;
|
||||
for ( var i = 0; i < lst.length; i++ ) {
|
||||
var step = lst[ i ];
|
||||
if ( !step || !step.step_type || !step.step_type.startsWith( 'data' ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/** Templates */
|
||||
_templateSuccess: function( response ) {
|
||||
if ( response && response.length > 0 ) {
|
||||
var $message = $( '<div/>' ).addClass( 'donemessagelarge' )
|
||||
.append( $( '<p/>' ).text( 'Successfully ran workflow \'' + this.model.get( 'name' ) + '\'. The following datasets have been added to the queue:' ) );
|
||||
for ( var i in response ) {
|
||||
var invocation = response[ i ];
|
||||
var $invocation = $( '<div/>' ).addClass( 'workflow-invocation-complete' );
|
||||
invocation.history && $invocation.append( $( '<p/>' ).text( 'These datasets will appear in a new history: ' )
|
||||
.append( $( '<a/>' ).addClass( 'new-history-link' )
|
||||
.attr( 'data-history-id', invocation.history.id )
|
||||
.attr( 'target', '_top' )
|
||||
.attr( 'href', '/history/switch_to_history?hist_id=' + invocation.history.id )
|
||||
.text( invocation.history.name ) ) );
|
||||
_.each( invocation.outputs, function( output ) {
|
||||
$invocation.append( $( '<div/>' ).addClass( 'messagerow' ).html( '<b>' + output.hid + '</b>: ' + output.name ) );
|
||||
});
|
||||
$message.append( $invocation );
|
||||
}
|
||||
return $message;
|
||||
} else {
|
||||
return this._templateError( response );
|
||||
}
|
||||
},
|
||||
|
||||
_templateError: function( response ) {
|
||||
return $( '<div/>' ).addClass( 'errormessagelarge' )
|
||||
.append( $( '<p/>' ).text( 'The server could not complete the request. Please contact the Galaxy Team if this error persists.' ) )
|
||||
.append( $( '<pre/>' ).text( JSON.stringify( response, null, 4 ) ) );
|
||||
}
|
||||
});
|
||||
return {
|
||||
View: View
|
||||
};
|
||||
});
|
||||
});
|
||||
@@ -1,50 +1,91 @@
|
||||
/** Scratchbook viewer */
|
||||
define([], function() {
|
||||
|
||||
/** Frame view */
|
||||
var FrameView = Backbone.View.extend({
|
||||
initialize: function( options ) {
|
||||
var self = this;
|
||||
this.model = options && options.model || new Backbone.Model( options );
|
||||
this.setElement( $( '<div/>' ).addClass( 'corner frame' ) );
|
||||
this.$el.append( $( '<div/>' ).addClass( 'f-header corner' )
|
||||
.append( $( '<div/>' ).addClass( 'f-title' ) )
|
||||
.append( $( '<div/>' ).addClass( 'f-icon f-close fa fa-close' )
|
||||
.tooltip( { title: 'Close', placement: 'bottom' } ) ) )
|
||||
.append( $( '<div/>' ).addClass( 'f-content' ) )
|
||||
.append( $( '<div/>' ).addClass( 'f-resize f-icon corner fa fa-expand' ).tooltip( { title: 'Resize' } ) )
|
||||
.append( $( '<div/>' ).addClass( 'f-cover' ) );
|
||||
this.$header = this.$( '.f-header' );
|
||||
this.$title = this.$( '.f-title' );
|
||||
this.$content = this.$( '.f-content' );
|
||||
this.render();
|
||||
this.listenTo( this.model, 'change', this.render, this );
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
var options = this.model.attributes;
|
||||
this.$title.html( options.title || '' );
|
||||
this.$header.find( '.f-icon-left' ).remove();
|
||||
_.each( options.menu, function( option ) {
|
||||
var $option = $( '<div/>' ).addClass( 'f-icon-left' ).addClass( option.icon );
|
||||
if ( _.isFunction( option.disabled ) && option.disabled() ) {
|
||||
$option.attr( 'disabled', true );
|
||||
} else {
|
||||
$option.on( 'click', function() { option.onclick( self ) } )
|
||||
.tooltip( { title: option.tooltip, placement: 'bottom' } );
|
||||
}
|
||||
self.$header.append( $option );
|
||||
} );
|
||||
if ( options.url ) {
|
||||
this.$content.html( $ ( '<iframe/>' ).addClass( 'f-iframe' )
|
||||
.attr( 'scrolling', 'auto' )
|
||||
.attr( 'src', options.url + ( options.url.indexOf( '?' ) === -1 ? '?' : '&' ) + 'widget=True' ) );
|
||||
} else if ( options.content ) {
|
||||
_.isFunction( options.content ) ? options.content( self.$content ) : self.$content.html( options.content );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/** Scratchbook viewer */
|
||||
var View = Backbone.View.extend({
|
||||
defaultOptions: {
|
||||
frame: { // default frame size in cells
|
||||
frame: { // default frame size in cells
|
||||
cols : 6,
|
||||
rows : 3
|
||||
},
|
||||
rows : 1000, // maximum number of rows
|
||||
cell : 130, // cell size in px
|
||||
margin : 5,
|
||||
scroll : 5, // scroll speed
|
||||
top_min : 40, // top margin
|
||||
frame_max : 9, // maximum number of frames
|
||||
visible : true, // initial visibility
|
||||
rows : 1000, // maximum number of rows
|
||||
cell : 130, // cell size in px
|
||||
margin : 5, // margin between frames
|
||||
scroll : 5, // scroll speed
|
||||
top_min : 40, // top margin
|
||||
frame_max : 9, // maximum number of frames
|
||||
visible : true, // initial visibility
|
||||
},
|
||||
|
||||
cols : 0, // number of columns
|
||||
top : 0, // scroll/element top
|
||||
top_max : 0, // viewport scrolling state
|
||||
frame_z : 0, // frame z-index
|
||||
frame_counter : 0, // frame counter
|
||||
frame_uid : 0,
|
||||
frame_list : {}, // list of all frames
|
||||
frame_shadow : null,
|
||||
visible : false,
|
||||
event : {},
|
||||
cols : 0, // number of columns
|
||||
top : 0, // scroll/element top
|
||||
top_max : 0, // viewport scrolling state
|
||||
frame_z : 0, // frame z-index
|
||||
frame_counter : 0, // frame counter
|
||||
frame_uid : 0, // unique frame id counter
|
||||
frame_list : {}, // list of all frames
|
||||
frame_shadow : null, // frame shown as placeholder when moving active frames
|
||||
visible : false, // flag indicating if scratchbook viewer is visible or not
|
||||
event : {}, // dictionary keeping track of current event
|
||||
|
||||
initialize : function( options ) {
|
||||
var self = this;
|
||||
this.options = _.defaults( options || {}, this.defaultOptions );
|
||||
this.visible = this.options.visible;
|
||||
this.top = this.top_max = this.options.top_min;
|
||||
this.setElement( $( '<div/>' ).addClass( 'galaxy-frame' ) );
|
||||
this.$el.append( $( '<div/>' ).addClass( 'frame-background' ) );
|
||||
this.$el.append( $( '<div/>' ).addClass( 'frame-menu frame-scroll-up fa fa-chevron-up fa-2x' ) );
|
||||
this.$el.append( $( '<div/>' ).addClass( 'frame-menu frame-scroll-down fa fa-chevron-down fa-2x' ) );
|
||||
this.$el.append( $( '<div/>' ).addClass( 'frame-shadow corner' ).attr( 'id', 'frame-shadow' ) );
|
||||
this.setElement( $( '<div/>' ).addClass( 'galaxy-frame' )
|
||||
.append( $( '<div/>' ).addClass( 'frame-background' ) )
|
||||
.append( $( '<div/>' ).addClass( 'frame-menu frame-scroll-up fa fa-chevron-up fa-2x' ) )
|
||||
.append( $( '<div/>' ).addClass( 'frame-menu frame-scroll-down fa fa-chevron-down fa-2x' ) ) );
|
||||
|
||||
// initialize shadow to guiding drag/resize events
|
||||
this.frame_shadow = {
|
||||
id : '#frame-shadow',
|
||||
screen_location : {},
|
||||
grid_location : {},
|
||||
grid_rank : null,
|
||||
grid_lock : false
|
||||
};
|
||||
this.frame_shadow = new Backbone.View({ el: $( '<div/>' ).addClass( 'corner frame-shadow' ) } );
|
||||
this.$el.append( this.frame_shadow.$el );
|
||||
this._frameInit( this.frame_shadow, '#frame-shadow' );
|
||||
this._frameResize( this.frame_shadow, { width: 0, height: 0 } );
|
||||
this.frame_list[ '#frame-shadow' ] = this.frame_shadow;
|
||||
|
||||
@@ -87,38 +128,18 @@ var View = Backbone.View.extend({
|
||||
} else {
|
||||
// initialize new frame elements
|
||||
this.top = this.options.top_min;
|
||||
var $frame_el = $( this._frameTemplate( frame_id.substring( 1 ), options.title ) );
|
||||
var $frame_content = $frame_el.find( '.f-content' );
|
||||
this.$el.append( $frame_el );
|
||||
|
||||
// configure content
|
||||
if ( options.url ) {
|
||||
$frame_content.append(
|
||||
$ ( '<iframe/>' ).addClass( 'f-iframe' )
|
||||
.attr( 'scrolling', 'auto' )
|
||||
.attr( 'src', options.url + ( options.url.indexOf( '?' ) === -1 ? '?' : '&' ) + 'widget=True' )
|
||||
);
|
||||
} else if ( options.content ) {
|
||||
_.isFunction( options.content ) ? options.content( $frame_content ) : $frame_content.append( options.content );
|
||||
}
|
||||
|
||||
// construct a new frame
|
||||
var frame = {
|
||||
id : frame_id,
|
||||
screen_location : {},
|
||||
grid_location : {},
|
||||
grid_rank : null,
|
||||
grid_lock : false
|
||||
};
|
||||
var frame = new FrameView( options );
|
||||
this.$el.append( frame.$el );
|
||||
|
||||
// set dimensions
|
||||
options.width = this._toPixelCoord( 'width', this.options.frame.cols );
|
||||
options.height = this._toPixelCoord( 'height', this.options.frame.rows );
|
||||
|
||||
// set default z-index and add to ui and frame list
|
||||
this.frame_z = parseInt( $( frame.id ).css( 'z-index' ) );
|
||||
this.frame_z = parseInt( frame.$el.css( 'z-index' ) );
|
||||
this.frame_list[ frame_id ] = frame;
|
||||
this.frame_counter++;
|
||||
this._frameInit( frame, frame_id );
|
||||
this._frameResize( frame, { width: options.width, height: options.height } );
|
||||
this._frameInsert( frame, { top: 0, left: 0 }, true );
|
||||
!this.visible && this.show();
|
||||
@@ -128,12 +149,12 @@ var View = Backbone.View.extend({
|
||||
},
|
||||
|
||||
/** Remove a frame */
|
||||
del: function( frame_id ) {
|
||||
del: function( frame ) {
|
||||
var self = this;
|
||||
var $frame = this.$( frame_id );
|
||||
var $frame = frame.$el;
|
||||
$frame.fadeOut( 'fast', function() {
|
||||
$frame.remove();
|
||||
delete self.frame_list[ frame_id ];
|
||||
delete self.frame_list[ frame.id ];
|
||||
self.frame_counter--;
|
||||
self._panelRefresh( true );
|
||||
self._panelAnimationComplete();
|
||||
@@ -178,12 +199,12 @@ var View = Backbone.View.extend({
|
||||
'mousedown .frame-background' : '_eventHide',
|
||||
'mousedown .frame-scroll-up' : '_eventPanelScroll_up',
|
||||
'mousedown .frame-scroll-down' : '_eventPanelScroll_down',
|
||||
'mousedown .f-close' : '_eventFrameClose',
|
||||
'mousedown .f-pin' : '_eventFrameLock'
|
||||
'mousedown .f-close' : '_eventFrameClose'
|
||||
},
|
||||
|
||||
/** Start drag/resize event */
|
||||
_eventFrameMouseDown: function ( e ) {
|
||||
$( '.tooltip' ).hide();
|
||||
if ( !this.event.type ) {
|
||||
if ( $( e.target ).hasClass( 'f-header' ) || $( e.target ).hasClass( 'f-title' ) ) {
|
||||
this.event.type = 'drag';
|
||||
@@ -194,10 +215,6 @@ var View = Backbone.View.extend({
|
||||
if ( this.event.type ) {
|
||||
e.preventDefault();
|
||||
this.event.target = this._frameIdentify( e.target );
|
||||
if ( this.event.target.grid_lock ) {
|
||||
this.event.type = null;
|
||||
return;
|
||||
}
|
||||
this.event.xy = {
|
||||
x: e.originalEvent.pageX,
|
||||
y: e.originalEvent.pageY
|
||||
@@ -267,22 +284,7 @@ var View = Backbone.View.extend({
|
||||
_eventFrameClose: function ( e ) {
|
||||
if ( !this.event.type ) {
|
||||
e.preventDefault();
|
||||
this.del( this._frameIdentify( e.target ).id );
|
||||
}
|
||||
},
|
||||
|
||||
/** Lock/Unlock the frame location */
|
||||
_eventFrameLock: function ( e ) {
|
||||
if ( !this.event.type ) {
|
||||
e.preventDefault();
|
||||
var frame = this._frameIdentify( e.target );
|
||||
var locked = frame.grid_lock = !frame.grid_lock;
|
||||
var $el = $( frame.id );
|
||||
$el.find( '.f-pin' ) [ locked && 'addClass' || 'removeClass' ]( 'toggle' );
|
||||
$el.find( '.f-header' ) [ locked && 'removeClass' || 'addClass' ]( 'f-not-allowed' );
|
||||
$el.find( '.f-title' ) [ locked && 'removeClass' || 'addClass' ]( 'f-not-allowed' );
|
||||
$el.find( '.f-resize' ) [ locked && 'hide' || 'show' ]();
|
||||
$el.find( '.f-close' ) [ locked && 'hide' || 'show' ]();
|
||||
this.del( this._frameIdentify( e.target ) );
|
||||
}
|
||||
},
|
||||
|
||||
@@ -338,7 +340,7 @@ var View = Backbone.View.extend({
|
||||
this._frameResize( this.frame_shadow, p );
|
||||
this._frameGrid( this.frame_shadow, frame.grid_location );
|
||||
frame.grid_location = null;
|
||||
$( this.frame_shadow.id ).show();
|
||||
this.frame_shadow.$el.show();
|
||||
$( '.f-cover' ).show();
|
||||
},
|
||||
|
||||
@@ -349,7 +351,7 @@ var View = Backbone.View.extend({
|
||||
this._frameResize( frame, p );
|
||||
this._frameGrid( frame, this.frame_shadow.grid_location, true );
|
||||
this.frame_shadow.grid_location = null;
|
||||
$( this.frame_shadow.id ).hide();
|
||||
this.frame_shadow.$el.hide();
|
||||
$( '.f-cover' ).hide();
|
||||
this._panelAnimationComplete();
|
||||
},
|
||||
@@ -458,6 +460,15 @@ var View = Backbone.View.extend({
|
||||
FRAME FUNCTIONS
|
||||
*/
|
||||
|
||||
/** Initialize a new frame */
|
||||
_frameInit: function( frame, id ) {
|
||||
frame.id = id
|
||||
frame.screen_location = {};
|
||||
frame.grid_location = {};
|
||||
frame.grid_rank = null;
|
||||
frame.$el.attr( 'id', id.substring( 1 ) );
|
||||
},
|
||||
|
||||
/** Insert frame at given location */
|
||||
_frameInsert: function( frame, new_loc, animate ) {
|
||||
var self = this;
|
||||
@@ -467,7 +478,7 @@ var View = Backbone.View.extend({
|
||||
place_list.push( [ frame, this._locationRank( new_loc ) ] );
|
||||
}
|
||||
_.each( this.frame_list, function( f ) {
|
||||
if ( f.grid_location !== null && !f.grid_lock ) {
|
||||
if ( f.grid_location !== null ) {
|
||||
f.grid_location = null;
|
||||
place_list.push( [ f, f.grid_rank ] );
|
||||
}
|
||||
@@ -516,7 +527,7 @@ var View = Backbone.View.extend({
|
||||
|
||||
/** Handle frame focussing */
|
||||
_frameFocus: function( frame, has_focus ) {
|
||||
$( frame.id ).css( 'z-index', this.frame_z + ( has_focus ? 1 : 0 ) );
|
||||
frame.$el.css( 'z-index', this.frame_z + ( has_focus ? 1 : 0 ) );
|
||||
},
|
||||
|
||||
/** New left/top position frame */
|
||||
@@ -526,17 +537,17 @@ var View = Backbone.View.extend({
|
||||
if ( animate ) {
|
||||
this._frameFocus( frame, true );
|
||||
var self = this;
|
||||
$( frame.id ).animate({ top: p.top, left: p.left }, 'fast', function() {
|
||||
frame.$el.animate({ top: p.top, left: p.left }, 'fast', function() {
|
||||
self._frameFocus( frame, false );
|
||||
});
|
||||
} else {
|
||||
$( frame.id ).css( { top: p.top, left: p.left } );
|
||||
frame.$el.css( { top: p.top, left: p.left } );
|
||||
}
|
||||
},
|
||||
|
||||
/** Resize frame */
|
||||
_frameResize: function( frame, p ) {
|
||||
$( frame.id ).css( { width: p.width, height: p.height } );
|
||||
frame.$el.css( { width: p.width, height: p.height } );
|
||||
frame.screen_location.width = p.width;
|
||||
frame.screen_location.height = p.height;
|
||||
},
|
||||
@@ -552,21 +563,6 @@ var View = Backbone.View.extend({
|
||||
_frameScreen: function( frame ) {
|
||||
var p = frame.screen_location;
|
||||
return { top: p.top, left: p.left, width: p.width, height: p.height };
|
||||
},
|
||||
|
||||
/** Regular frame template */
|
||||
_frameTemplate: function( id, title ) {
|
||||
return '<div id="' + id + '" class="frame corner">' +
|
||||
'<div class="f-header corner">' +
|
||||
'<span class="f-title">' + ( title || '' ) + '</span>' +
|
||||
'<span class="f-icon f-close fa fa-close"/>' +
|
||||
'<span class="f-icon f-pin fa fa-thumb-tack"/>' +
|
||||
'</div>' +
|
||||
'<div class="f-content">' +
|
||||
'<div class="f-cover"/>' +
|
||||
'</div>' +
|
||||
'<span class="f-resize f-icon corner fa fa-expand"/>' +
|
||||
'</div>';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -97,13 +97,22 @@
|
||||
border : 1px solid @black;
|
||||
background : @base-color-1;
|
||||
color : @white;
|
||||
.f-icon-left{
|
||||
cursor : pointer;
|
||||
font-size : 15px;
|
||||
margin-left : 3px;
|
||||
float : left;
|
||||
&[disabled] {
|
||||
opacity : 0.25;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.f-title {
|
||||
position : absolute;
|
||||
top : 2px;
|
||||
left : 16px;
|
||||
right : 16px;
|
||||
left : 32px;
|
||||
right : 32px;
|
||||
font-size : 12px;
|
||||
font-family : @font-family-sans-serif;
|
||||
text-align : center;
|
||||
@@ -113,27 +122,22 @@
|
||||
frame icons
|
||||
*/
|
||||
|
||||
.f-icon{
|
||||
position : absolute;
|
||||
cursor : pointer;
|
||||
font-size : 14px;
|
||||
}
|
||||
|
||||
.f-not-allowed{
|
||||
cursor : not-allowed;
|
||||
}
|
||||
|
||||
.f-close{
|
||||
cursor : pointer;
|
||||
position : absolute;
|
||||
font-size : 15px;
|
||||
right : 5px;
|
||||
top : 3px;
|
||||
}
|
||||
|
||||
.f-pin{
|
||||
left : 6px;
|
||||
top : 3px;
|
||||
top : 2px;
|
||||
}
|
||||
|
||||
.f-resize{
|
||||
cursor : pointer;
|
||||
position : absolute;
|
||||
font-size : 15px;
|
||||
right : 0px;
|
||||
bottom : 0px;
|
||||
background : @white;
|
||||
|
||||
@@ -4,7 +4,7 @@ How Do I...
|
||||
This section contains a number of smaller topics with links and examples meant
|
||||
to provide relatively concrete answers for specific Galaxy development scenarios.
|
||||
|
||||
... interact with the Galaxy codebase interactively?
|
||||
... interact with the Galaxy database interactively?
|
||||
----------------------------------------------------
|
||||
|
||||
This can be done with either IPython/Jupyter or a plain python console, depending on your preferences::
|
||||
@@ -14,12 +14,15 @@ This can be done with either IPython/Jupyter or a plain python console, dependin
|
||||
... 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::
|
||||
We've added a makefile which will let you do this. You can simple run::
|
||||
|
||||
make grunt
|
||||
make client
|
||||
|
||||
If you prefer docker and aren't a JS developer primarily, you can run
|
||||
|
||||
make grunt-docker
|
||||
|
||||
Please see the ``Makefile`` itself for details and other options. There is also a readme at
|
||||
``client/README.md``.
|
||||
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ class LDAP(AuthProvider):
|
||||
|
||||
# parse results
|
||||
if suser is None or len(suser) == 0:
|
||||
log.warn('LDAP authenticate: search returned no results')
|
||||
log.warning('LDAP authenticate: search returned no results')
|
||||
return (failure_mode, '', '')
|
||||
dn, attrs = suser[0]
|
||||
log.debug(("LDAP authenticate: dn is %s" % dn))
|
||||
@@ -169,7 +169,7 @@ class LDAP(AuthProvider):
|
||||
if whoami is None:
|
||||
raise RuntimeError('LDAP authenticate: anonymous bind')
|
||||
except Exception:
|
||||
log.warn('LDAP authenticate: bind exception', exc_info=True)
|
||||
log.warning('LDAP authenticate: bind exception', exc_info=True)
|
||||
return (failure_mode, '', '')
|
||||
|
||||
log.debug('LDAP authentication successful')
|
||||
|
||||
@@ -19,7 +19,8 @@ log = logging.getLogger(__name__)
|
||||
|
||||
class Amos( data.Text ):
|
||||
"""Class describing the AMOS assembly file """
|
||||
edam_format = "format_2561"
|
||||
edam_data = "data_0925"
|
||||
edam_format = "format_3582"
|
||||
file_ext = 'afg'
|
||||
|
||||
def sniff( self, filename ):
|
||||
@@ -68,11 +69,12 @@ class Amos( data.Text ):
|
||||
|
||||
class Sequences( sequence.Fasta ):
|
||||
"""Class describing the Sequences file generated by velveth """
|
||||
edam_data = "data_0925"
|
||||
|
||||
def sniff( self, filename ):
|
||||
"""
|
||||
Determines whether the file is a velveth produced fasta format
|
||||
The id line has 3 fields separated by tabs: sequence_name sequence_index cataegory::
|
||||
The id line has 3 fields separated by tabs: sequence_name sequence_index category::
|
||||
|
||||
>SEQUENCE_0_length_35 1 1
|
||||
GGATATAGGGCCAACCCAACTCAACGGCCTGTCTT
|
||||
|
||||
@@ -87,6 +87,8 @@ class Binary( data.Data ):
|
||||
class Ab1( Binary ):
|
||||
"""Class describing an ab1 binary sequence file"""
|
||||
file_ext = "ab1"
|
||||
edam_format = "format_3000"
|
||||
edam_data = "data_0924"
|
||||
|
||||
def set_peek( self, dataset, is_multi_byte=False ):
|
||||
if not dataset.dataset.purged:
|
||||
@@ -108,6 +110,8 @@ Binary.register_unsniffable_binary_ext("ab1")
|
||||
class Idat( Binary ):
|
||||
"""Binary data in idat format"""
|
||||
file_ext = "idat"
|
||||
edam_format = "format_2058"
|
||||
edam_data = "data_2603"
|
||||
|
||||
def sniff( self, filename ):
|
||||
try:
|
||||
@@ -174,6 +178,8 @@ Binary.register_unsniffable_binary_ext("zip")
|
||||
class GenericAsn1Binary( Binary ):
|
||||
"""Class for generic ASN.1 binary format"""
|
||||
file_ext = "asn1-binary"
|
||||
edam_format = "format_1966"
|
||||
edam_data = "data_0849"
|
||||
|
||||
Binary.register_unsniffable_binary_ext("asn1-binary")
|
||||
|
||||
@@ -182,6 +188,7 @@ Binary.register_unsniffable_binary_ext("asn1-binary")
|
||||
class Bam( Binary ):
|
||||
"""Class describing a BAM binary file"""
|
||||
edam_format = "format_2572"
|
||||
edam_data = "data_0863"
|
||||
file_ext = "bam"
|
||||
track_type = "ReadTrack"
|
||||
data_sources = { "data": "bai", "index": "bigwig" }
|
||||
@@ -489,6 +496,7 @@ Binary.register_sniffable_binary_format("bam", "bam", Bam)
|
||||
class CRAM( Binary ):
|
||||
file_ext = "cram"
|
||||
edam_format = "format_3462"
|
||||
edam_data = "format_0863"
|
||||
|
||||
MetadataElement( name="cram_version", default=None, desc="CRAM Version", param=MetadataParameter, readonly=True, visible=False, optional=False, no_value=None )
|
||||
MetadataElement( name="cram_index", desc="CRAM Index File", param=metadata.FileParameter, file_ext="crai", readonly=True, no_value=None, visible=False, optional=True )
|
||||
@@ -509,7 +517,7 @@ class CRAM( Binary ):
|
||||
header = fh.read(6)
|
||||
return ord( header[4] ), ord( header[5] )
|
||||
except Exception as exc:
|
||||
log.warn( '%s, get_cram_version Exception: %s', self, exc )
|
||||
log.warning( '%s, get_cram_version Exception: %s', self, exc )
|
||||
return -1, -1
|
||||
|
||||
def set_index_file(self, dataset, index_file):
|
||||
@@ -530,10 +538,10 @@ class CRAM( Binary ):
|
||||
return index_file.file_name
|
||||
else:
|
||||
os.unlink( dataset_symlink )
|
||||
log.warn( '%s, expected crai index not created for: %s', self, dataset.file_name )
|
||||
log.warning( '%s, expected crai index not created for: %s', self, dataset.file_name )
|
||||
return False
|
||||
except Exception as exc:
|
||||
log.warn( '%s, set_index_file Exception: %s', self, exc )
|
||||
log.warning( '%s, set_index_file Exception: %s', self, exc )
|
||||
return False
|
||||
|
||||
def set_peek( self, dataset, is_multi_byte=False ):
|
||||
@@ -559,6 +567,7 @@ Binary.register_sniffable_binary_format('cram', 'cram', CRAM)
|
||||
class Bcf( Binary):
|
||||
"""Class describing a BCF file"""
|
||||
edam_format = "format_3020"
|
||||
edam_data = "data_3498"
|
||||
file_ext = "bcf"
|
||||
|
||||
MetadataElement( name="bcf_index", desc="BCF Index File", param=metadata.FileParameter, file_ext="csi", readonly=True, no_value=None, visible=False, optional=True )
|
||||
@@ -618,6 +627,7 @@ class H5( Binary ):
|
||||
False
|
||||
"""
|
||||
file_ext = "h5"
|
||||
edam_format = "format_3590"
|
||||
|
||||
def __init__( self, **kwd ):
|
||||
Binary.__init__( self, **kwd )
|
||||
@@ -653,6 +663,7 @@ Binary.register_sniffable_binary_format("h5", "h5", H5)
|
||||
class Scf( Binary ):
|
||||
"""Class describing an scf binary sequence file"""
|
||||
edam_format = "format_1632"
|
||||
edam_data = "data_0924"
|
||||
file_ext = "scf"
|
||||
|
||||
def set_peek( self, dataset, is_multi_byte=False ):
|
||||
@@ -675,6 +686,7 @@ Binary.register_unsniffable_binary_ext("scf")
|
||||
class Sff( Binary ):
|
||||
""" Standard Flowgram Format (SFF) """
|
||||
edam_format = "format_3284"
|
||||
edam_data = "data_0924"
|
||||
file_ext = "sff"
|
||||
|
||||
def sniff( self, filename ):
|
||||
@@ -712,6 +724,7 @@ class BigWig(Binary):
|
||||
http://bioinformatics.oxfordjournals.org/cgi/content/abstract/btq351v1
|
||||
"""
|
||||
edam_format = "format_3006"
|
||||
edam_data = "data_3002"
|
||||
track_type = "LineTrack"
|
||||
data_sources = { "data_standalone": "bigwig" }
|
||||
|
||||
@@ -750,6 +763,7 @@ Binary.register_sniffable_binary_format("bigwig", "bigwig", BigWig)
|
||||
class BigBed(BigWig):
|
||||
"""BigBed support from UCSC."""
|
||||
edam_format = "format_3004"
|
||||
edam_data = "data_3002"
|
||||
data_sources = { "data_standalone": "bigbed" }
|
||||
|
||||
def __init__( self, **kwd ):
|
||||
@@ -763,6 +777,7 @@ Binary.register_sniffable_binary_format("bigbed", "bigbed", BigBed)
|
||||
class TwoBit (Binary):
|
||||
"""Class describing a TwoBit format nucleotide file"""
|
||||
edam_format = "format_3009"
|
||||
edam_data = "data_0848"
|
||||
file_ext = "twobit"
|
||||
|
||||
def sniff(self, filename):
|
||||
@@ -800,6 +815,7 @@ class SQlite ( Binary ):
|
||||
MetadataElement( name="table_columns", default={}, param=DictParameter, desc="Database Table Columns", readonly=True, visible=True, no_value={} )
|
||||
MetadataElement( name="table_row_count", default={}, param=DictParameter, desc="Database Table Row Count", readonly=True, visible=True, no_value={} )
|
||||
file_ext = "sqlite"
|
||||
edam_format = "format_3621"
|
||||
|
||||
def init_meta( self, dataset, copy_from=None ):
|
||||
Binary.init_meta( self, dataset, copy_from=copy_from )
|
||||
@@ -821,18 +837,18 @@ class SQlite ( Binary ):
|
||||
cols = [col[0] for col in cur.description]
|
||||
columns[table] = cols
|
||||
except Exception as exc:
|
||||
log.warn( '%s, set_meta Exception: %s', self, exc )
|
||||
log.warning( '%s, set_meta Exception: %s', self, exc )
|
||||
for table in tables:
|
||||
try:
|
||||
row_query = "SELECT count(*) FROM %s" % table
|
||||
rowcounts[table] = c.execute(row_query).fetchone()[0]
|
||||
except Exception as exc:
|
||||
log.warn( '%s, set_meta Exception: %s', self, exc )
|
||||
log.warning( '%s, set_meta Exception: %s', self, exc )
|
||||
dataset.metadata.tables = tables
|
||||
dataset.metadata.table_columns = columns
|
||||
dataset.metadata.table_row_count = rowcounts
|
||||
except Exception as exc:
|
||||
log.warn( '%s, set_meta Exception: %s', self, exc )
|
||||
log.warning( '%s, set_meta Exception: %s', self, exc )
|
||||
|
||||
def sniff( self, filename ):
|
||||
# The first 16 bytes of any SQLite3 database file is 'SQLite format 3\0', and the file is binary. For details
|
||||
@@ -891,6 +907,8 @@ class GeminiSQLite( SQlite ):
|
||||
MetadataElement( name="gemini_version", default='0.10.0', param=MetadataParameter, desc="Gemini Version",
|
||||
readonly=True, visible=True, no_value='0.10.0' )
|
||||
file_ext = "gemini.sqlite"
|
||||
edam_format = "format_3622"
|
||||
edam_data = "data_3498"
|
||||
|
||||
def set_meta( self, dataset, overwrite=True, **kwd ):
|
||||
super( GeminiSQLite, self ).set_meta( dataset, overwrite=overwrite, **kwd )
|
||||
@@ -903,7 +921,7 @@ class GeminiSQLite( SQlite ):
|
||||
dataset.metadata.gemini_version = version
|
||||
# TODO: Can/should we detect even more attributes, such as use of PED file, what was input annotation type, etc.
|
||||
except Exception as e:
|
||||
log.warn( '%s, set_meta Exception: %s', self, e )
|
||||
log.warning( '%s, set_meta Exception: %s', self, e )
|
||||
|
||||
def sniff( self, filename ):
|
||||
if super( GeminiSQLite, self ).sniff( filename ):
|
||||
@@ -920,7 +938,7 @@ class GeminiSQLite( SQlite ):
|
||||
return False
|
||||
return True
|
||||
except Exception as e:
|
||||
log.warn( '%s, sniff Exception: %s', self, e )
|
||||
log.warning( '%s, sniff Exception: %s', self, e )
|
||||
return False
|
||||
|
||||
def set_peek( self, dataset, is_multi_byte=False ):
|
||||
@@ -959,7 +977,7 @@ class MzSQlite( SQlite ):
|
||||
return False
|
||||
return True
|
||||
except Exception as e:
|
||||
log.warn( '%s, sniff Exception: %s', self, e )
|
||||
log.warning( '%s, sniff Exception: %s', self, e )
|
||||
return False
|
||||
|
||||
|
||||
@@ -994,7 +1012,7 @@ class IdpDB( SQlite ):
|
||||
return False
|
||||
return True
|
||||
except Exception as e:
|
||||
log.warn( '%s, sniff Exception: %s', self, e )
|
||||
log.warning( '%s, sniff Exception: %s', self, e )
|
||||
return False
|
||||
|
||||
def set_peek( self, dataset, is_multi_byte=False ):
|
||||
@@ -1274,7 +1292,7 @@ class SearchGuiArchive ( CompressedArchive ):
|
||||
fh.close()
|
||||
tempzip.close()
|
||||
except Exception as e:
|
||||
log.warn( '%s, set_meta Exception: %s', self, e )
|
||||
log.warning( '%s, set_meta Exception: %s', self, e )
|
||||
|
||||
def sniff( self, filename ):
|
||||
try:
|
||||
@@ -1284,7 +1302,7 @@ class SearchGuiArchive ( CompressedArchive ):
|
||||
tempzip.close()
|
||||
return is_searchgui
|
||||
except Exception as e:
|
||||
log.warn( '%s, sniff Exception: %s', self, e )
|
||||
log.warning( '%s, sniff Exception: %s', self, e )
|
||||
return False
|
||||
|
||||
def set_peek( self, dataset, is_multi_byte=False ):
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
"""Module proxies :module:`galaxy.util.checkers` for backward compatibility.
|
||||
|
||||
External datatypes may make use of these functions.
|
||||
"""
|
||||
from galaxy.util.checkers import (
|
||||
check_binary,
|
||||
check_bz2,
|
||||
check_gzip,
|
||||
check_html,
|
||||
check_image,
|
||||
check_zip,
|
||||
is_gzip,
|
||||
is_bz2,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
'check_binary',
|
||||
'check_bz2',
|
||||
'check_gzip',
|
||||
'check_html',
|
||||
'check_image',
|
||||
'check_zip',
|
||||
'is_gzip',
|
||||
'is_bz2',
|
||||
]
|
||||
@@ -64,6 +64,7 @@ class Data( object ):
|
||||
<class 'galaxy.model.metadata.MetadataParameter'>
|
||||
|
||||
"""
|
||||
edam_data = "data_0006"
|
||||
edam_format = "format_1915"
|
||||
# Data is not chunkable by default.
|
||||
CHUNKABLE = False
|
||||
@@ -867,6 +868,8 @@ class Text( Data ):
|
||||
|
||||
class GenericAsn1( Text ):
|
||||
"""Class for generic ASN.1 text format"""
|
||||
edam_data = "data_0849"
|
||||
edam_format = "format_1966"
|
||||
file_ext = 'asn1'
|
||||
|
||||
|
||||
@@ -880,6 +883,7 @@ class LineCount( Text ):
|
||||
|
||||
class Newick( Text ):
|
||||
"""New Hampshire/Newick Format"""
|
||||
edam_data = "data_0872"
|
||||
edam_format = "format_1910"
|
||||
file_ext = "nhx"
|
||||
|
||||
@@ -904,6 +908,7 @@ class Newick( Text ):
|
||||
|
||||
class Nexus( Text ):
|
||||
"""Nexus format as used By Paup, Mr Bayes, etc"""
|
||||
edam_data = "data_0872"
|
||||
edam_format = "format_1912"
|
||||
file_ext = "nex"
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ log = logging.getLogger(__name__)
|
||||
|
||||
class Image( data.Data ):
|
||||
"""Class describing an image"""
|
||||
edam_data = 'data_2968'
|
||||
edam_format = "format_3547"
|
||||
|
||||
def set_peek( self, dataset, is_multi_byte=False ):
|
||||
@@ -64,6 +65,7 @@ class Image( data.Data ):
|
||||
|
||||
|
||||
class Jpg( Image ):
|
||||
edam_format = "format_3579"
|
||||
file_ext = "jpg"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
@@ -72,6 +74,7 @@ class Jpg( Image ):
|
||||
|
||||
|
||||
class Png( Image ):
|
||||
edam_format = "format_3603"
|
||||
file_ext = "png"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
@@ -80,6 +83,7 @@ class Png( Image ):
|
||||
|
||||
|
||||
class Tiff( Image ):
|
||||
edam_format = "format_3591"
|
||||
file_ext = "tiff"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
@@ -88,6 +92,7 @@ class Tiff( Image ):
|
||||
|
||||
|
||||
class Bmp( Image ):
|
||||
edam_format = "format_3592"
|
||||
file_ext = "bmp"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
@@ -105,6 +110,7 @@ class Gif( Image ):
|
||||
|
||||
|
||||
class Im( Image ):
|
||||
edam_format = "format_3593"
|
||||
file_ext = "im"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
@@ -113,6 +119,7 @@ class Im( Image ):
|
||||
|
||||
|
||||
class Pcd( Image ):
|
||||
edam_format = "format_3594"
|
||||
file_ext = "pcd"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
@@ -121,6 +128,7 @@ class Pcd( Image ):
|
||||
|
||||
|
||||
class Pcx( Image ):
|
||||
edam_format = "format_3595"
|
||||
file_ext = "pcx"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
@@ -129,6 +137,7 @@ class Pcx( Image ):
|
||||
|
||||
|
||||
class Ppm( Image ):
|
||||
edam_format = "format_3596"
|
||||
file_ext = "ppm"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
@@ -137,6 +146,7 @@ class Ppm( Image ):
|
||||
|
||||
|
||||
class Psd( Image ):
|
||||
edam_format = "format_3597"
|
||||
file_ext = "psd"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
@@ -145,6 +155,7 @@ class Psd( Image ):
|
||||
|
||||
|
||||
class Xbm( Image ):
|
||||
edam_format = "format_3598"
|
||||
file_ext = "xbm"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
@@ -153,6 +164,7 @@ class Xbm( Image ):
|
||||
|
||||
|
||||
class Xpm( Image ):
|
||||
edam_format = "format_3599"
|
||||
file_ext = "xpm"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
@@ -161,6 +173,7 @@ class Xpm( Image ):
|
||||
|
||||
|
||||
class Rgb( Image ):
|
||||
edam_format = "format_3600"
|
||||
file_ext = "rgb"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
@@ -169,6 +182,7 @@ class Rgb( Image ):
|
||||
|
||||
|
||||
class Pbm( Image ):
|
||||
edam_format = "format_3601"
|
||||
file_ext = "pbm"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
@@ -177,6 +191,7 @@ class Pbm( Image ):
|
||||
|
||||
|
||||
class Pgm( Image ):
|
||||
edam_format = "format_3602"
|
||||
file_ext = "pgm"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
@@ -194,6 +209,7 @@ class Eps( Image ):
|
||||
|
||||
|
||||
class Rast( Image ):
|
||||
edam_format = "format_3605"
|
||||
file_ext = "rast"
|
||||
|
||||
def sniff(self, filename, image=None):
|
||||
|
||||
@@ -50,6 +50,7 @@ VIEWPORT_MAX_READS_PER_LINE = 10
|
||||
@dataproviders.decorators.has_dataproviders
|
||||
class Interval( Tabular ):
|
||||
"""Tab delimited data containing interval information"""
|
||||
edam_data = "data_3002"
|
||||
edam_format = "format_3475"
|
||||
file_ext = "interval"
|
||||
line_class = "region"
|
||||
@@ -375,7 +376,7 @@ class Interval( Tabular ):
|
||||
|
||||
class BedGraph( Interval ):
|
||||
"""Tab delimited chrom/start/end/datavalue dataset"""
|
||||
|
||||
edam_format = "format_3583"
|
||||
file_ext = "bedgraph"
|
||||
track_type = "LineTrack"
|
||||
data_sources = { "data": "bigwig", "index": "bigwig" }
|
||||
@@ -582,7 +583,7 @@ class Bed( Interval ):
|
||||
|
||||
class BedStrict( Bed ):
|
||||
"""Tab delimited data in strict BED format - no non-standard columns allowed"""
|
||||
|
||||
edam_format = "format_3584"
|
||||
file_ext = "bedstrict"
|
||||
|
||||
# no user change of datatype allowed
|
||||
@@ -613,13 +614,13 @@ class BedStrict( Bed ):
|
||||
|
||||
class Bed6( BedStrict ):
|
||||
"""Tab delimited data in strict BED format - no non-standard columns allowed; column count forced to 6"""
|
||||
|
||||
edam_format = "format_3585"
|
||||
file_ext = "bed6"
|
||||
|
||||
|
||||
class Bed12( BedStrict ):
|
||||
"""Tab delimited data in strict BED format - no non-standard columns allowed; column count forced to 12"""
|
||||
|
||||
edam_format = "format_3586"
|
||||
file_ext = "bed12"
|
||||
|
||||
|
||||
@@ -641,6 +642,7 @@ class _RemoteCallMixin:
|
||||
@dataproviders.decorators.has_dataproviders
|
||||
class Gff( Tabular, _RemoteCallMixin ):
|
||||
"""Tab delimited data in Gff format"""
|
||||
edam_data = "data_1255"
|
||||
edam_format = "format_2305"
|
||||
file_ext = "gff"
|
||||
column_names = [ 'Seqname', 'Source', 'Feature', 'Start', 'End', 'Score', 'Strand', 'Frame', 'Group' ]
|
||||
@@ -1288,6 +1290,7 @@ class Wiggle( Tabular, _RemoteCallMixin ):
|
||||
|
||||
class CustomTrack ( Tabular ):
|
||||
"""UCSC CustomTrack"""
|
||||
edam_format = "format_3588"
|
||||
file_ext = "customtrack"
|
||||
|
||||
def __init__(self, **kwd):
|
||||
@@ -1440,7 +1443,7 @@ class ENCODEPeak( Interval ):
|
||||
This format is used to provide called peaks of signal enrichment based on
|
||||
pooled, normalized (interpreted) data. It is a BED6+4 format.
|
||||
'''
|
||||
|
||||
edam_format = "format_3612"
|
||||
file_ext = "encodepeak"
|
||||
column_names = [ 'Chrom', 'Start', 'End', 'Name', 'Score', 'Strand', 'SignalValue', 'pValue', 'qValue', 'Peak' ]
|
||||
data_sources = { "data": "tabix", "index": "bigwig" }
|
||||
@@ -1460,11 +1463,9 @@ class ChromatinInteractions( Interval ):
|
||||
'''
|
||||
Chromatin interactions obtained from 3C/5C/Hi-C experiments.
|
||||
'''
|
||||
|
||||
file_ext = "chrint"
|
||||
track_type = "DiagonalHeatmapTrack"
|
||||
data_sources = { "data": "tabix", "index": "bigwig" }
|
||||
|
||||
column_names = [ 'Chrom1', 'Start1', 'End1', 'Chrom2', 'Start2', 'End2', 'Value' ]
|
||||
|
||||
"""Add metadata elements"""
|
||||
|
||||
@@ -301,7 +301,7 @@ class DistanceMatrix(Text):
|
||||
dataset.metadata.sequence_count = int(''.join(line)) # seq count sometimes preceded by tab
|
||||
break
|
||||
except Exception as e:
|
||||
log.warn("DistanceMatrix set_meta %s" % e)
|
||||
log.warning("DistanceMatrix set_meta %s" % e)
|
||||
|
||||
|
||||
class LowerTriangleDistanceMatrix(DistanceMatrix):
|
||||
@@ -902,7 +902,7 @@ class SffFlow(Tabular):
|
||||
flow_values = int(headers[0][0])
|
||||
dataset.metadata.flow_values = flow_values
|
||||
except Exception as e:
|
||||
log.warn("SffFlow set_meta %s" % e)
|
||||
log.warning("SffFlow set_meta %s" % e)
|
||||
|
||||
def make_html_table(self, dataset, skipchars=[]):
|
||||
"""Create HTML table, used for displaying peek"""
|
||||
|
||||
@@ -11,6 +11,8 @@ log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Hmmer( Text ):
|
||||
edam_data = "data_1364"
|
||||
edam_format = "format_1370"
|
||||
file_ext = "hmm"
|
||||
|
||||
def set_peek(self, dataset, is_multi_byte=False):
|
||||
@@ -29,6 +31,7 @@ class Hmmer( Text ):
|
||||
|
||||
|
||||
class Hmmer2( Hmmer ):
|
||||
edam_format = "format_3328"
|
||||
|
||||
def sniff(self, filename):
|
||||
"""HMMER2 files start with HMMER2.0
|
||||
@@ -39,6 +42,7 @@ class Hmmer2( Hmmer ):
|
||||
|
||||
|
||||
class Hmmer3( Hmmer ):
|
||||
edam_format = "format_3329"
|
||||
|
||||
def sniff(self, filename):
|
||||
"""HMMER3 files start with HMMER3/f
|
||||
@@ -85,6 +89,8 @@ Binary.register_unsniffable_binary_ext("hmmpress")
|
||||
|
||||
|
||||
class Stockholm_1_0( Text ):
|
||||
edam_data = "data_0863"
|
||||
edam_format = "format_1961"
|
||||
file_ext = "stockholm"
|
||||
|
||||
MetadataElement( name="number_of_models", default=0, desc="Number of multiple alignments", readonly=True, visible=True, optional=True, no_value=0 )
|
||||
|
||||
@@ -18,6 +18,8 @@ log = logging.getLogger(__name__)
|
||||
|
||||
class Wiff(Binary):
|
||||
"""Class for wiff files."""
|
||||
edam_data = "data_2536"
|
||||
edam_format = "format_3710"
|
||||
file_ext = 'wiff'
|
||||
allow_datatype_change = False
|
||||
composite_type = 'auto_primary_file'
|
||||
@@ -55,6 +57,7 @@ Binary.register_sniffable_binary_format("wiff", "wiff", Wiff )
|
||||
|
||||
class PepXmlReport(Tabular):
|
||||
"""pepxml converted to tabular report"""
|
||||
edam_data = "data_2536"
|
||||
file_ext = "tsv"
|
||||
|
||||
def __init__(self, **kwd):
|
||||
@@ -68,6 +71,7 @@ class PepXmlReport(Tabular):
|
||||
|
||||
class ProtXmlReport(Tabular):
|
||||
"""protxml converted to tabular report"""
|
||||
edam_data = "data_2536"
|
||||
file_ext = "tsv"
|
||||
comment_lines = 1
|
||||
|
||||
@@ -93,6 +97,8 @@ class ProtXmlReport(Tabular):
|
||||
class ProteomicsXml(GenericXml):
|
||||
""" An enhanced XML datatype used to reuse code across several
|
||||
proteomic/mass-spec datatypes. """
|
||||
edam_data = "data_2536"
|
||||
edam_format = "format_2032"
|
||||
|
||||
def sniff(self, filename):
|
||||
""" Determines whether the file is the correct XML type. """
|
||||
@@ -117,6 +123,7 @@ class ProteomicsXml(GenericXml):
|
||||
|
||||
class PepXml(ProteomicsXml):
|
||||
"""pepXML data"""
|
||||
edam_format = "format_3655"
|
||||
file_ext = "pepxml"
|
||||
blurb = 'pepXML data'
|
||||
root = "msms_pipeline_analysis"
|
||||
@@ -124,8 +131,8 @@ class PepXml(ProteomicsXml):
|
||||
|
||||
class MzML(ProteomicsXml):
|
||||
"""mzML data"""
|
||||
file_ext = "mzml"
|
||||
edam_format = "format_3244"
|
||||
file_ext = "mzml"
|
||||
blurb = 'mzML Mass Spectrometry data'
|
||||
root = "(mzML|indexedmzML)"
|
||||
|
||||
@@ -139,28 +146,29 @@ class ProtXML(ProteomicsXml):
|
||||
|
||||
class MzXML(ProteomicsXml):
|
||||
"""mzXML data"""
|
||||
edam_format = "format_3654"
|
||||
file_ext = "mzxml"
|
||||
blurb = "mzXML Mass Spectrometry data"
|
||||
root = "mzXML"
|
||||
|
||||
|
||||
class MzIdentML(ProteomicsXml):
|
||||
file_ext = "mzid"
|
||||
edam_format = "format_3247"
|
||||
file_ext = "mzid"
|
||||
blurb = "XML identified peptides and proteins."
|
||||
root = "MzIdentML"
|
||||
|
||||
|
||||
class TraML(ProteomicsXml):
|
||||
file_ext = "traml"
|
||||
edam_format = "format_3246"
|
||||
file_ext = "traml"
|
||||
blurb = "TraML transition list"
|
||||
root = "TraML"
|
||||
|
||||
|
||||
class MzQuantML(ProteomicsXml):
|
||||
file_ext = "mzq"
|
||||
edam_format = "format_3248"
|
||||
file_ext = "mzq"
|
||||
blurb = "XML quantification data"
|
||||
root = "MzQuantML"
|
||||
|
||||
@@ -184,6 +192,7 @@ class IdXML(ProteomicsXml):
|
||||
|
||||
|
||||
class TandemXML(ProteomicsXml):
|
||||
edam_format = "format_3711"
|
||||
file_ext = "tandem"
|
||||
blurb = "X!Tandem search results file"
|
||||
root = "bioml"
|
||||
@@ -197,6 +206,8 @@ class UniProtXML(ProteomicsXml):
|
||||
|
||||
class Mgf(Text):
|
||||
"""Mascot Generic Format data"""
|
||||
edam_data = "data_2536"
|
||||
edam_format = "format_3651"
|
||||
file_ext = "mgf"
|
||||
|
||||
def set_peek(self, dataset, is_multi_byte=False):
|
||||
@@ -223,6 +234,8 @@ class Mgf(Text):
|
||||
|
||||
class MascotDat(Text):
|
||||
"""Mascot search results """
|
||||
edam_data = "data_2536"
|
||||
edam_format = "format_3713"
|
||||
file_ext = "mascotdat"
|
||||
|
||||
def set_peek(self, dataset, is_multi_byte=False):
|
||||
@@ -249,6 +262,8 @@ class MascotDat(Text):
|
||||
|
||||
class ThermoRAW(Binary):
|
||||
"""Class describing a Thermo Finnigan binary RAW file"""
|
||||
edam_data = "data_2536"
|
||||
edam_format = "format_3712"
|
||||
file_ext = "raw"
|
||||
|
||||
def sniff(self, filename):
|
||||
|
||||
@@ -11,6 +11,8 @@ class QualityScore ( data.Text ):
|
||||
"""
|
||||
until we know more about quality score formats
|
||||
"""
|
||||
edam_data = "data_2048"
|
||||
edam_format = "format_3606"
|
||||
file_ext = "qual"
|
||||
|
||||
|
||||
@@ -18,6 +20,7 @@ class QualityScoreSOLiD ( QualityScore ):
|
||||
"""
|
||||
until we know more about quality score formats
|
||||
"""
|
||||
edam_format = "format_3610"
|
||||
file_ext = "qualsolid"
|
||||
|
||||
def sniff( self, filename ):
|
||||
@@ -75,6 +78,7 @@ class QualityScore454 ( QualityScore ):
|
||||
"""
|
||||
until we know more about quality score formats
|
||||
"""
|
||||
edam_format = "format_3611"
|
||||
file_ext = "qual454"
|
||||
|
||||
def sniff( self, filename ):
|
||||
@@ -116,6 +120,7 @@ class QualityScoreSolexa ( QualityScore ):
|
||||
"""
|
||||
until we know more about quality score formats
|
||||
"""
|
||||
edam_format = "format_3608"
|
||||
file_ext = "qualsolexa"
|
||||
|
||||
|
||||
@@ -123,4 +128,5 @@ class QualityScoreIllumina ( QualityScore ):
|
||||
"""
|
||||
until we know more about quality score formats
|
||||
"""
|
||||
edam_format = "format_3609"
|
||||
file_ext = "qualillumina"
|
||||
|
||||
@@ -129,7 +129,11 @@ class Registry( object ):
|
||||
make_subclass = galaxy.util.string_as_bool( elem.get( 'subclass', False ) )
|
||||
edam_format = elem.get( 'edam_format', None )
|
||||
if edam_format and not make_subclass:
|
||||
self.log.warn("Cannot specify edam_format without setting subclass to True, skipping datatype.")
|
||||
self.log.warning("Cannot specify edam_format without setting subclass to True, skipping datatype.")
|
||||
continue
|
||||
edam_data = elem.get( 'edam_data', None )
|
||||
if edam_data and not make_subclass:
|
||||
self.log.warning("Cannot specify edam_data without setting subclass to True, skipping datatype.")
|
||||
continue
|
||||
# Proprietary datatypes included in installed tool shed repositories will include two special attributes
|
||||
# (proprietary_path and proprietary_datatype_module) if they depend on proprietary datatypes classes.
|
||||
@@ -230,6 +234,8 @@ class Registry( object ):
|
||||
datatype_class = type( datatype_class_name, ( datatype_class, ), {} )
|
||||
if edam_format:
|
||||
datatype_class.edam_format = edam_format
|
||||
if edam_data:
|
||||
datatype_class.edam_data = edam_data
|
||||
self.datatypes_by_extension[ extension ] = datatype_class()
|
||||
if mimetype is None:
|
||||
# Use default mimetype per datatype specification.
|
||||
@@ -816,9 +822,14 @@ class Registry( object ):
|
||||
def edam_formats( self ):
|
||||
"""
|
||||
"""
|
||||
mapping = {}
|
||||
for k, v in self.datatypes_by_extension.iteritems():
|
||||
mapping[k] = v.edam_format
|
||||
mapping = dict((k, v.edam_format) for k, v in self.datatypes_by_extension.items())
|
||||
return mapping
|
||||
|
||||
@property
|
||||
def edam_data( self ):
|
||||
"""
|
||||
"""
|
||||
mapping = dict((k, v.edam_data) for k, v in self.datatypes_by_extension.items())
|
||||
return mapping
|
||||
|
||||
@property
|
||||
|
||||
@@ -38,6 +38,8 @@ class SequenceSplitLocations( data.Text ):
|
||||
]}
|
||||
|
||||
"""
|
||||
file_ext = "fqtoc"
|
||||
|
||||
def set_peek( self, dataset, is_multi_byte=False ):
|
||||
if not dataset.dataset.purged:
|
||||
try:
|
||||
@@ -52,8 +54,6 @@ class SequenceSplitLocations( data.Text ):
|
||||
dataset.peek = 'file does not exist'
|
||||
dataset.blurb = 'file purged from disk'
|
||||
|
||||
file_ext = "fqtoc"
|
||||
|
||||
def sniff( self, filename ):
|
||||
if os.path.getsize(filename) < 50000:
|
||||
try:
|
||||
@@ -70,6 +70,7 @@ class SequenceSplitLocations( data.Text ):
|
||||
|
||||
class Sequence( data.Text ):
|
||||
"""Class describing a sequence"""
|
||||
edam_data = "data_2044"
|
||||
|
||||
"""Add metadata elements"""
|
||||
MetadataElement( name="sequences", default=0, desc="Number of sequences", readonly=True, visible=False, optional=True, no_value=0 )
|
||||
@@ -294,6 +295,7 @@ class Sequence( data.Text ):
|
||||
|
||||
class Alignment( data.Text ):
|
||||
"""Class describing an alignment"""
|
||||
edam_data = "data_0863"
|
||||
|
||||
"""Add metadata elements"""
|
||||
MetadataElement( name="species", desc="Species", default=[], param=metadata.SelectParameter, multiple=True, readonly=True, no_value=None )
|
||||
@@ -498,7 +500,7 @@ class Fasta( Sequence ):
|
||||
|
||||
class csFasta( Sequence ):
|
||||
""" Class representing the SOLID Color-Space sequence ( csfasta ) """
|
||||
edam_format = "format_1929"
|
||||
edam_format = "format_3589"
|
||||
file_ext = "csfasta"
|
||||
|
||||
def sniff( self, filename ):
|
||||
@@ -841,11 +843,12 @@ class MafCustomTrack( data.Text ):
|
||||
|
||||
class Axt( data.Text ):
|
||||
"""Class describing an axt alignment"""
|
||||
|
||||
# gvk- 11/19/09 - This is really an alignment, but we no longer have tools that use this data type, and it is
|
||||
# here simply for backward compatibility ( although it is still in the datatypes registry ). Subclassing
|
||||
# from data.Text eliminates managing metadata elements inherited from the Alignemnt class.
|
||||
|
||||
edam_data = "data_0863"
|
||||
edam_format = "format_3013"
|
||||
file_ext = "axt"
|
||||
|
||||
def sniff( self, filename ):
|
||||
@@ -895,13 +898,14 @@ class Axt( data.Text ):
|
||||
|
||||
class Lav( data.Text ):
|
||||
"""Class describing a LAV alignment"""
|
||||
edam_format = "format_3014"
|
||||
file_ext = "lav"
|
||||
|
||||
# gvk- 11/19/09 - This is really an alignment, but we no longer have tools that use this data type, and it is
|
||||
# here simply for backward compatibility ( although it is still in the datatypes registry ). Subclassing
|
||||
# from data.Text eliminates managing metadata elements inherited from the Alignemnt class.
|
||||
|
||||
edam_data = "data_0863"
|
||||
edam_format = "format_3014"
|
||||
file_ext = "lav"
|
||||
|
||||
def sniff( self, filename ):
|
||||
"""
|
||||
Determines whether the file is in lav format
|
||||
@@ -963,6 +967,7 @@ class RNADotPlotMatrix( data.Data ):
|
||||
|
||||
|
||||
class DotBracket ( Sequence ):
|
||||
edam_data = "data_0880"
|
||||
edam_format = "format_1457"
|
||||
file_ext = "dbn"
|
||||
|
||||
|
||||
@@ -408,6 +408,7 @@ class Taxonomy( Tabular ):
|
||||
@dataproviders.decorators.has_dataproviders
|
||||
class Sam( Tabular ):
|
||||
edam_format = "format_2573"
|
||||
edam_data = "data_0863"
|
||||
file_ext = 'sam'
|
||||
track_type = "ReadTrack"
|
||||
data_sources = { "data": "bam", "index": "bigwig" }
|
||||
|
||||
@@ -260,6 +260,7 @@ class Obo( Text ):
|
||||
OBO file format description
|
||||
http://www.geneontology.org/GO.format.obo-1_2.shtml
|
||||
"""
|
||||
edam_data = "data_0582"
|
||||
edam_format = "format_2549"
|
||||
file_ext = "obo"
|
||||
|
||||
@@ -295,6 +296,7 @@ class Arff( Text ):
|
||||
An ARFF (Attribute-Relation File Format) file is an ASCII text file that describes a list of instances sharing a set of attributes.
|
||||
http://weka.wikispaces.com/ARFF
|
||||
"""
|
||||
edam_format = "format_3581"
|
||||
file_ext = "arff"
|
||||
|
||||
"""Add metadata elements"""
|
||||
@@ -393,6 +395,7 @@ class Arff( Text ):
|
||||
|
||||
class SnpEffDb( Text ):
|
||||
"""Class describing a SnpEff genome build"""
|
||||
edam_format = "format_3624"
|
||||
file_ext = "snpeffdb"
|
||||
MetadataElement( name="genome_version", default=None, desc="Genome Version", readonly=True, visible=True, no_value=None )
|
||||
MetadataElement( name="snpeff_version", default="SnpEff4.0", desc="SnpEff Version", readonly=True, visible=True, no_value=None )
|
||||
@@ -525,14 +528,14 @@ class SnpSiftDbNSFP( Text ):
|
||||
headers = lines[0].split('\t')
|
||||
dataset.metadata.annotation = headers[4:]
|
||||
except Exception as e:
|
||||
log.warn("set_meta fname: %s %s" % (fname, str(e)))
|
||||
log.warning("set_meta fname: %s %s" % (fname, str(e)))
|
||||
finally:
|
||||
fh.close()
|
||||
if fname.endswith('.tbi'):
|
||||
dataset.metadata.index = fname
|
||||
self.regenerate_primary_file(dataset)
|
||||
except Exception as e:
|
||||
log.warn("set_meta fname: %s %s" % (dataset.file_name if dataset and dataset.file_name else 'Unkwown', str(e)))
|
||||
log.warning("set_meta fname: %s %s" % (dataset.file_name if dataset and dataset.file_name else 'Unkwown', str(e)))
|
||||
|
||||
def set_peek( self, dataset, is_multi_byte=False ):
|
||||
if not dataset.dataset.purged:
|
||||
|
||||
@@ -12,6 +12,7 @@ log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GeneTrack( binary.Binary ):
|
||||
edam_data = "data_3002"
|
||||
edam_format = "format_2919"
|
||||
file_ext = "genetrack"
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ class Triples( data.Text ):
|
||||
"""
|
||||
The abstract base class for the file format that can contain triples
|
||||
"""
|
||||
edam_data = "data_0582"
|
||||
edam_format = "format_2376"
|
||||
file_ext = "triples"
|
||||
|
||||
|
||||
@@ -94,6 +94,8 @@ class CisML( GenericXml ):
|
||||
|
||||
class Phyloxml( GenericXml ):
|
||||
"""Format for defining phyloxml data http://www.phyloxml.org/"""
|
||||
edam_data = "data_0872"
|
||||
edam_format = "format_3159"
|
||||
file_ext = "phyloxml"
|
||||
|
||||
def set_peek( self, dataset, is_multi_byte=False ):
|
||||
|
||||
@@ -80,7 +80,7 @@ class ExternalServiceAction( object ):
|
||||
return handled_results
|
||||
|
||||
def perform_action( self, param_dict ):
|
||||
raise 'Abstract Method'
|
||||
raise Exception( 'Abstract Method' )
|
||||
|
||||
|
||||
class ExternalServiceResult( object ):
|
||||
@@ -90,7 +90,7 @@ class ExternalServiceResult( object ):
|
||||
|
||||
@property
|
||||
def content( self ):
|
||||
raise 'Abstract Method'
|
||||
raise Exception( 'Abstract Method' )
|
||||
|
||||
|
||||
class ExternalServiceWebAPIActionResult( ExternalServiceResult ):
|
||||
|
||||
@@ -21,7 +21,7 @@ class ExternalServiceParameter( object ):
|
||||
self.parent = parent
|
||||
|
||||
def get_value( self, param_dict ):
|
||||
raise 'Abstract Method'
|
||||
raise Exception( 'Abstract Method' )
|
||||
|
||||
|
||||
class ExternalServiceTemplateParameter( ExternalServiceParameter ):
|
||||
|
||||
@@ -218,7 +218,7 @@ class PopulatedExternalService( object ):
|
||||
elif isinstance( item, ExternalServiceActionsGroup ):
|
||||
item.prepare_actions( param_dict, param_dict, action_list )
|
||||
else:
|
||||
raise 'unknown item type found'
|
||||
raise Exception( 'unknown item type found' )
|
||||
self.param_dict = param_dict
|
||||
self.actions = action_list
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ class FormDefinitionFieldFactory( object ):
|
||||
type = None
|
||||
|
||||
def __get_stored_field_type( self, **kwds ):
|
||||
raise 'not implemented'
|
||||
raise Exception( 'not implemented' )
|
||||
|
||||
def new( self, name=None, label=None, required=False, helptext=None, default=None, visible=True, layout=None ):
|
||||
"""
|
||||
|
||||
@@ -1133,12 +1133,21 @@ class JobWrapper( object ):
|
||||
self.app.config, key, default
|
||||
)
|
||||
|
||||
def finish( self, stdout, stderr, tool_exit_code=None, remote_working_directory=None ):
|
||||
def finish(
|
||||
self,
|
||||
stdout,
|
||||
stderr,
|
||||
tool_exit_code=None,
|
||||
remote_working_directory=None,
|
||||
remote_metadata_directory=None,
|
||||
):
|
||||
"""
|
||||
Called to indicate that the associated command has been run. Updates
|
||||
the output datasets based on stderr and stdout from the command, and
|
||||
the contents of the output files.
|
||||
"""
|
||||
# remote_working_directory not used with updated (7.0+ pulsar and 16.04+
|
||||
# originated Galaxy job - keep for a few releases for older jobs)
|
||||
finish_timer = util.ExecutionTimer()
|
||||
|
||||
# default post job setup
|
||||
@@ -1266,12 +1275,15 @@ class JobWrapper( object ):
|
||||
output_filename = self.external_output_metadata.get_output_filenames_by_dataset( dataset, self.sa_session ).filename_out
|
||||
|
||||
def path_rewriter( path ):
|
||||
if not remote_working_directory or not path:
|
||||
if not path:
|
||||
return path
|
||||
normalized_remote_working_directory = os.path.normpath( remote_working_directory )
|
||||
normalized_remote_working_directory = remote_working_directory and os.path.normpath( remote_working_directory )
|
||||
normalized_remote_metadata_directory = remote_metadata_directory and os.path.normpath( remote_metadata_directory )
|
||||
normalized_path = os.path.normpath( path )
|
||||
if normalized_path.startswith( normalized_remote_working_directory ):
|
||||
if remote_working_directory and normalized_path.startswith( normalized_remote_working_directory ):
|
||||
return normalized_path.replace( normalized_remote_working_directory, self.working_directory, 1 )
|
||||
if remote_metadata_directory and normalized_path.startswith( normalized_remote_metadata_directory ):
|
||||
return normalized_path.replace( normalized_remote_metadata_directory, self.working_directory, 1 )
|
||||
return path
|
||||
|
||||
dataset.metadata.from_JSON_dict( output_filename, path_rewriter=path_rewriter )
|
||||
|
||||
@@ -185,7 +185,7 @@ class CollectlProcessSummarizer( object ):
|
||||
if column == "AccumT":
|
||||
# Only thing that makes sense is sum
|
||||
if statistic_type != "max":
|
||||
log.warn( "Only statistic max makes sense for AccumT" )
|
||||
log.warning( "Only statistic max makes sense for AccumT" )
|
||||
continue
|
||||
|
||||
value = sum( [ v.max for v in self.process_accum_statistics.itervalues() ] )
|
||||
|
||||
@@ -58,8 +58,8 @@ class CondorJobRunner( AsynchronousJobRunner ):
|
||||
# get destination params
|
||||
query_params = submission_params(prefix="", **job_destination.params)
|
||||
container = None
|
||||
universe = query_params.get('universe', False)
|
||||
if universe.strip().lower() == 'docker':
|
||||
universe = query_params.get('universe', None)
|
||||
if universe and universe.strip().lower() == 'docker':
|
||||
container = self.find_container( job_wrapper )
|
||||
if container:
|
||||
# HTCondor needs the image as 'docker_image'
|
||||
|
||||
@@ -107,7 +107,7 @@ class LocalJobRunner( BaseJobRunner ):
|
||||
try:
|
||||
exit_code = int( open( exit_code_path, 'r' ).read() )
|
||||
except Exception:
|
||||
log.warn( "Failed to read exit code from path %s" % exit_code_path )
|
||||
log.warning( "Failed to read exit code from path %s" % exit_code_path )
|
||||
pass
|
||||
stdout_file.seek( 0 )
|
||||
stderr_file.seek( 0 )
|
||||
|
||||
@@ -377,7 +377,7 @@ class PulsarJobRunner( AsynchronousJobRunner ):
|
||||
for key, value in self.destination_defaults.iteritems():
|
||||
if key in params:
|
||||
if value is PARAMETER_SPECIFICATION_IGNORED:
|
||||
log.warn( "Pulsar runner in selected configuration ignores parameter %s" % key )
|
||||
log.warning( "Pulsar runner in selected configuration ignores parameter %s" % key )
|
||||
continue
|
||||
# if self.runner_params.get( key, None ):
|
||||
# # Let plugin define defaults for some parameters -
|
||||
@@ -451,6 +451,7 @@ class PulsarJobRunner( AsynchronousJobRunner ):
|
||||
client = self.get_client_from_state(job_state)
|
||||
run_results = client.full_status()
|
||||
remote_working_directory = run_results.get("working_directory", None)
|
||||
remote_metadata_directory = run_results.get("metadata_directory", None)
|
||||
stdout = run_results.get('stdout', '')
|
||||
stderr = run_results.get('stderr', '')
|
||||
exit_code = run_results.get('returncode', None)
|
||||
@@ -482,7 +483,8 @@ class PulsarJobRunner( AsynchronousJobRunner ):
|
||||
stdout,
|
||||
stderr,
|
||||
exit_code,
|
||||
remote_working_directory=remote_working_directory
|
||||
remote_working_directory=remote_working_directory,
|
||||
remote_metadata_directory=remote_metadata_directory,
|
||||
)
|
||||
except Exception:
|
||||
log.exception("Job wrapper finish method failed")
|
||||
@@ -666,7 +668,7 @@ class PulsarJobRunner( AsynchronousJobRunner ):
|
||||
if PulsarJobRunner.__use_remote_datatypes_conf( client ):
|
||||
remote_datatypes_config = remote_system_properties.get('galaxy_datatypes_config_file', None)
|
||||
if not remote_datatypes_config:
|
||||
log.warn(NO_REMOTE_DATATYPES_CONFIG)
|
||||
log.warning(NO_REMOTE_DATATYPES_CONFIG)
|
||||
remote_datatypes_config = os.path.join(remote_galaxy_home, 'datatypes_conf.xml')
|
||||
metadata_kwds['datatypes_config'] = remote_datatypes_config
|
||||
else:
|
||||
|
||||
@@ -39,8 +39,8 @@ class SlurmJobRunner( DRMAAJobRunner ):
|
||||
return dict( JobState='NOT_FOUND' )
|
||||
raise Exception( '`%s` returned %s, stderr: %s' % ( ' '.join( cmd ), p.returncode, stderr ) )
|
||||
return dict( [ out_param.split( '=', 1 ) for out_param in stdout.split() ] )
|
||||
if drmaa_state == self.drmaa_job_states.FAILED:
|
||||
try:
|
||||
try:
|
||||
if drmaa_state == self.drmaa_job_states.FAILED:
|
||||
job_info = __get_jobinfo()
|
||||
sleep = 1
|
||||
while job_info['JobState'] == 'COMPLETING':
|
||||
@@ -86,22 +86,21 @@ class SlurmJobRunner( DRMAAJobRunner ):
|
||||
ajs.stop_job = False
|
||||
self.work_queue.put( ( self.fail_job, ajs ) )
|
||||
return
|
||||
except Exception as e:
|
||||
log.exception( '(%s/%s) Unable to inspect failed slurm job using scontrol, job will be unconditionally failed: %s', ajs.job_wrapper.get_id_tag(), ajs.job_id, e )
|
||||
return super( SlurmJobRunner, self )._complete_terminal_job( ajs, drmaa_state=drmaa_state )
|
||||
if drmaa_state == self.drmaa_job_states.DONE:
|
||||
with open(ajs.error_file, 'r+') as f:
|
||||
lines = f.readlines()
|
||||
f.seek(0)
|
||||
for line in lines:
|
||||
stripped_line = line.strip()
|
||||
if any([_ in stripped_line for _ in SLURM_MEMORY_LIMIT_EXCEEDED_PARTIAL_WARNINGS]):
|
||||
log.debug( '(%s/%s) Job completed, removing SLURM exceeded memory warning: "%s"', ajs.job_wrapper.get_id_tag(), ajs.job_id, stripped_line )
|
||||
else:
|
||||
f.write(line)
|
||||
f.truncate()
|
||||
# by default, finish as if the job was successful.
|
||||
super( SlurmJobRunner, self )._complete_terminal_job( ajs, drmaa_state=drmaa_state )
|
||||
if drmaa_state == self.drmaa_job_states.DONE:
|
||||
with open(ajs.error_file, 'r+') as f:
|
||||
lines = f.readlines()
|
||||
f.seek(0)
|
||||
for line in lines:
|
||||
stripped_line = line.strip()
|
||||
if any([_ in stripped_line for _ in SLURM_MEMORY_LIMIT_EXCEEDED_PARTIAL_WARNINGS]):
|
||||
log.debug( '(%s/%s) Job completed, removing SLURM exceeded memory warning: "%s"', ajs.job_wrapper.get_id_tag(), ajs.job_id, stripped_line )
|
||||
else:
|
||||
f.write(line)
|
||||
f.truncate()
|
||||
except Exception:
|
||||
log.exception( '(%s/%s) Failure in SLURM _complete_terminal_job(), job final state will be: %s', ajs.job_wrapper.get_id_tag(), ajs.job_id, drmaa_state )
|
||||
# by default, finish the job with the state from drmaa
|
||||
return super( SlurmJobRunner, self )._complete_terminal_job( ajs, drmaa_state=drmaa_state )
|
||||
|
||||
def __check_memory_limit( self, efile_path ):
|
||||
"""
|
||||
|
||||
@@ -65,7 +65,7 @@ def parse_citation( elem, directory, citation_manager ):
|
||||
citation_type = elem.attrib.get( 'type', None )
|
||||
citation_class = CITATION_CLASSES.get( citation_type, None )
|
||||
if not citation_class:
|
||||
log.warn("Unknown or unspecified citation type: %s" % citation_type)
|
||||
log.warning("Unknown or unspecified citation type: %s" % citation_type)
|
||||
return None
|
||||
return citation_class( elem, directory, citation_manager )
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ class HistoryManager( sharable.SharableModelManager, deletable.PurgableManagerMi
|
||||
"""
|
||||
if self.user_manager.is_anonymous( user ):
|
||||
return None if ( not current_history or current_history.deleted ) else current_history
|
||||
desc_update_time = self.model_class.table.c.update_time
|
||||
desc_update_time = desc( self.model_class.table.c.update_time )
|
||||
filters = self._munge_filters( filters, self.model_class.user_id == user.id )
|
||||
# TODO: normalize this return value
|
||||
return self.query( filters=filters, order_by=desc_update_time, limit=1, **kwargs ).first()
|
||||
|
||||
@@ -136,7 +136,7 @@ class TagManager( object ):
|
||||
# Create tag; if None, skip the tag (and log error).
|
||||
tag = self._get_or_create_tag( lc_name )
|
||||
if not tag:
|
||||
log.warn( "Failed to create tag with name %s" % lc_name )
|
||||
log.warning( "Failed to create tag with name %s" % lc_name )
|
||||
return
|
||||
# Create tag association based on item class.
|
||||
item_tag_assoc_class = self.get_tag_assoc_class( item.__class__ )
|
||||
|
||||
@@ -1572,7 +1572,7 @@ class LibraryPermissions( object ):
|
||||
if isinstance( library_item, Library ):
|
||||
self.library = library_item
|
||||
else:
|
||||
raise "Invalid Library specified: %s" % library_item.__class__.__name__
|
||||
raise Exception( "Invalid Library specified: %s" % library_item.__class__.__name__ )
|
||||
self.role = role
|
||||
|
||||
|
||||
@@ -1582,7 +1582,7 @@ class LibraryFolderPermissions( object ):
|
||||
if isinstance( library_item, LibraryFolder ):
|
||||
self.folder = library_item
|
||||
else:
|
||||
raise "Invalid LibraryFolder specified: %s" % library_item.__class__.__name__
|
||||
raise Exception( "Invalid LibraryFolder specified: %s" % library_item.__class__.__name__ )
|
||||
self.role = role
|
||||
|
||||
|
||||
@@ -1592,7 +1592,7 @@ class LibraryDatasetPermissions( object ):
|
||||
if isinstance( library_item, LibraryDataset ):
|
||||
self.library_dataset = library_item
|
||||
else:
|
||||
raise "Invalid LibraryDataset specified: %s" % library_item.__class__.__name__
|
||||
raise Exception( "Invalid LibraryDataset specified: %s" % library_item.__class__.__name__ )
|
||||
self.role = role
|
||||
|
||||
|
||||
@@ -1602,7 +1602,7 @@ class LibraryDatasetDatasetAssociationPermissions( object ):
|
||||
if isinstance( library_item, LibraryDatasetDatasetAssociation ):
|
||||
self.library_dataset_dataset_association = library_item
|
||||
else:
|
||||
raise "Invalid LibraryDatasetDatasetAssociation specified: %s" % library_item.__class__.__name__
|
||||
raise Exception( "Invalid LibraryDatasetDatasetAssociation specified: %s" % library_item.__class__.__name__ )
|
||||
self.role = role
|
||||
|
||||
|
||||
@@ -2079,7 +2079,7 @@ class DatasetInstance( object ):
|
||||
return fake_hda
|
||||
|
||||
def clear_associated_files( self, metadata_safe=False, purge=False ):
|
||||
raise 'Unimplemented'
|
||||
raise Exception( "Unimplemented" )
|
||||
|
||||
def get_child_by_designation(self, designation):
|
||||
for child in self.children:
|
||||
|
||||
@@ -274,7 +274,7 @@ class DatasetInstance( object ):
|
||||
return valid
|
||||
|
||||
def clear_associated_files( self, metadata_safe=False, purge=False ):
|
||||
raise 'Unimplemented'
|
||||
raise Exception( 'Unimplemented' )
|
||||
|
||||
def get_child_by_designation(self, designation):
|
||||
for child in self.children:
|
||||
|
||||
@@ -37,7 +37,7 @@ def upgrade(migrate_engine):
|
||||
try:
|
||||
table.create()
|
||||
except:
|
||||
log.warn( "Failed to create table '%s', ignoring (might result in wrong schema)" % table.name )
|
||||
log.warning( "Failed to create table '%s', ignoring (might result in wrong schema)" % table.name )
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
|
||||
@@ -37,7 +37,7 @@ def upgrade(migrate_engine):
|
||||
try:
|
||||
table.create()
|
||||
except:
|
||||
log.warn( "Failed to create table '%s', ignoring (might result in wrong schema)" % table.name )
|
||||
log.warning( "Failed to create table '%s', ignoring (might result in wrong schema)" % table.name )
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
|
||||
@@ -26,7 +26,7 @@ def upgrade(migrate_engine):
|
||||
try:
|
||||
table.create()
|
||||
except:
|
||||
log.warn( "Failed to create table '%s', ignoring (might result in wrong schema)" % table.name )
|
||||
log.warning( "Failed to create table '%s', ignoring (might result in wrong schema)" % table.name )
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
|
||||
@@ -38,7 +38,7 @@ def upgrade(migrate_engine):
|
||||
try:
|
||||
table.create()
|
||||
except:
|
||||
log.warn( "Failed to create table '%s', ignoring (might result in wrong schema)" % table.name )
|
||||
log.warning( "Failed to create table '%s', ignoring (might result in wrong schema)" % table.name )
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
|
||||
@@ -48,97 +48,97 @@ class RBACAgent:
|
||||
return self.permitted_actions.__dict__.values()
|
||||
|
||||
def get_item_actions( self, action, item ):
|
||||
raise 'No valid method of retrieving action (%s) for item %s.' % ( action, item )
|
||||
raise Exception( 'No valid method of retrieving action (%s) for item %s.' % ( action, item ) )
|
||||
|
||||
def guess_derived_permissions_for_datasets( self, datasets=[] ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def can_access_dataset( self, roles, dataset ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def can_manage_dataset( self, roles, dataset ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def can_access_library( self, roles, library ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def can_add_library_item( self, roles, item ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def can_modify_library_item( self, roles, item ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def can_manage_library_item( self, roles, item ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def associate_components( self, **kwd ):
|
||||
raise 'No valid method of associating provided components: %s' % kwd
|
||||
raise Exception( 'No valid method of associating provided components: %s' % kwd )
|
||||
|
||||
def create_private_user_role( self, user ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def get_private_user_role( self, user ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def get_accessible_request_types( self, trans, user ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def user_set_default_permissions( self, user, permissions={}, history=False, dataset=False ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def history_set_default_permissions( self, history, permissions=None, dataset=False, bypass_manage_permission=False ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def set_all_dataset_permissions( self, dataset, permissions, new=False ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def set_dataset_permission( self, dataset, permission ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def set_all_library_permissions( self, trans, dataset, permissions ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def set_library_item_permission( self, library_item, permission ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def library_is_public( self, library ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def make_library_public( self, library ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def get_accessible_libraries( self, trans, user ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def get_permitted_libraries( self, trans, user, actions ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def folder_is_public( self, library ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def make_folder_public( self, folder, count=0 ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def dataset_is_public( self, dataset ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def make_dataset_public( self, dataset ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def get_permissions( self, library_dataset ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def get_all_roles( self, trans, cntrller ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def get_legitimate_roles( self, trans, item, cntrller ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def derive_roles_from_access( self, trans, item_id, cntrller, library=False, **kwd ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def get_component_associations( self, **kwd ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def components_are_associated( self, **kwd ):
|
||||
return bool( self.get_component_associations( **kwd ) )
|
||||
@@ -736,7 +736,7 @@ class GalaxyRBACAgent( RBACAgent ):
|
||||
if 'action' in kwd:
|
||||
if 'dataset' in kwd and 'role' in kwd:
|
||||
return self.associate_action_dataset_role( kwd['action'], kwd['dataset'], kwd['role'] )
|
||||
raise 'No valid method of associating provided components: %s' % kwd
|
||||
raise Exception( 'No valid method of associating provided components: %s' % kwd )
|
||||
|
||||
def associate_user_group( self, user, group ):
|
||||
assoc = self.model.UserGroupAssociation( user, group )
|
||||
@@ -1300,8 +1300,8 @@ class GalaxyRBACAgent( RBACAgent ):
|
||||
self.sa_session.add( lp )
|
||||
self.sa_session.flush()
|
||||
else:
|
||||
raise 'Invalid class (%s) specified for target_library_item (%s)' % \
|
||||
( target_library_item.__class__, target_library_item.__class__.__name__ )
|
||||
raise Exception( 'Invalid class (%s) specified for target_library_item (%s)' %
|
||||
( target_library_item.__class__, target_library_item.__class__.__name__ ) )
|
||||
|
||||
def get_permitted_libraries( self, trans, user, actions ):
|
||||
"""
|
||||
@@ -1435,7 +1435,7 @@ class GalaxyRBACAgent( RBACAgent ):
|
||||
elif 'group' in kwd:
|
||||
if 'role' in kwd:
|
||||
return self.sa_session.query( self.model.GroupRoleAssociation ).filter_by( role_id=kwd['role'].id, group_id=kwd['group'].id ).first()
|
||||
raise 'No valid method of associating provided components: %s' % kwd
|
||||
raise Exception( 'No valid method of associating provided components: %s' % kwd )
|
||||
|
||||
def check_folder_contents( self, user, roles, folder, hidden_folder_ids='' ):
|
||||
"""
|
||||
@@ -1567,7 +1567,7 @@ class HostAgent( RBACAgent ):
|
||||
log.debug( 'Allowing access to private dataset with hda: %i. Remote server is: %s.' % ( hda.id, server ) )
|
||||
return True
|
||||
else:
|
||||
raise 'The dataset access permission is the only valid permission in the host security agent.'
|
||||
raise Exception( 'The dataset access permission is the only valid permission in the host security agent.' )
|
||||
|
||||
def set_dataset_permissions( self, hda, user, site ):
|
||||
hdadaa = self.sa_session.query( self.model.HistoryDatasetAssociationDisplayAtAuthorization ) \
|
||||
|
||||
@@ -428,7 +428,7 @@ class Tool( object, Dictifiable ):
|
||||
if self.profile >= 16.04 and VERSION_MAJOR < self.profile:
|
||||
template = "The tool %s targets version %s of Galaxy, you should upgrade Galaxy to ensure proper functioning of this tool."
|
||||
message = template % (self.id, self.profile)
|
||||
log.warn(message)
|
||||
log.warning(message)
|
||||
|
||||
# Get the (user visible) name of the tool
|
||||
self.name = tool_source.parse_name()
|
||||
@@ -443,6 +443,9 @@ class Tool( object, Dictifiable ):
|
||||
else:
|
||||
raise Exception( "Missing tool 'version' for tool with id '%s' at '%s'" % (self.id, tool_source) )
|
||||
|
||||
self.edam_operations = tool_source.parse_edam_operations()
|
||||
self.edam_topics = tool_source.parse_edam_topics()
|
||||
|
||||
# Support multi-byte tools
|
||||
self.is_multi_byte = tool_source.parse_is_multi_byte()
|
||||
# Legacy feature, ignored by UI.
|
||||
@@ -1240,9 +1243,10 @@ class Tool( object, Dictifiable ):
|
||||
if error:
|
||||
if update_values:
|
||||
try:
|
||||
previous_value = value
|
||||
value = input.get_initial_value( request_context, context )
|
||||
if not prefixed_name.startswith( '__' ):
|
||||
messages[ prefixed_name ] = '%s Using default: \'%s\'.' % ( error, value )
|
||||
messages[ prefixed_name ] = error if previous_value == value else '%s Using default: \'%s\'.' % ( error, value )
|
||||
parent[ input.name ] = value
|
||||
except:
|
||||
messages[ prefixed_name ] = 'Attempt to replace invalid value for \'%s\' failed.' % ( prefixed_label )
|
||||
@@ -1538,6 +1542,9 @@ class Tool( object, Dictifiable ):
|
||||
# Basic information
|
||||
tool_dict = super( Tool, self ).to_dict()
|
||||
|
||||
tool_dict["edam_operations"] = self.edam_operations
|
||||
tool_dict["edam_topics"] = self.edam_topics
|
||||
|
||||
# Fill in ToolShedRepository info
|
||||
if hasattr(self, 'tool_shed') and self.tool_shed:
|
||||
tool_dict['tool_shed_repository'] = {
|
||||
@@ -1573,7 +1580,7 @@ class Tool( object, Dictifiable ):
|
||||
|
||||
return tool_dict
|
||||
|
||||
def to_json( self, trans, kwd={}, job=None, workflow_mode=False ):
|
||||
def to_json( self, trans, kwd={}, job=None, workflow_building_mode=False ):
|
||||
"""
|
||||
Recursively creates a tool dictionary containing repeats, dynamic options and updated states.
|
||||
"""
|
||||
@@ -1590,7 +1597,7 @@ class Tool( object, Dictifiable ):
|
||||
raise exceptions.MessageException( '[history_id=%s] Failed to retrieve history. %s.' % ( history_id, str( e ) ) )
|
||||
|
||||
# build request context
|
||||
request_context = WorkRequestContext( app=trans.app, user=trans.user, history=history, workflow_building_mode=workflow_mode )
|
||||
request_context = WorkRequestContext( app=trans.app, user=trans.user, history=history, workflow_building_mode=workflow_building_mode )
|
||||
|
||||
# load job parameters into incoming
|
||||
tool_message = ''
|
||||
|
||||
@@ -78,7 +78,7 @@ class DefaultToolAction( object ):
|
||||
data = new_data
|
||||
|
||||
if not trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ):
|
||||
raise "User does not have permission to use a dataset (%s) provided for input." % data.id
|
||||
raise Exception( "User does not have permission to use a dataset (%s) provided for input." % data.id )
|
||||
return data
|
||||
if isinstance( input, DataToolParameter ):
|
||||
if isinstance( value, list ):
|
||||
|
||||
@@ -340,7 +340,7 @@ class TabularToolDataTable( ToolDataTable, Dictifiable ):
|
||||
self._update_version()
|
||||
else:
|
||||
self.missing_index_file = filename
|
||||
log.warn( "Cannot find index file '%s' for tool data table '%s'" % ( filename, self.name ) )
|
||||
log.warning( "Cannot find index file '%s' for tool data table '%s'" % ( filename, self.name ) )
|
||||
|
||||
if filename not in self.filenames or not self.filenames[ filename ][ 'found' ]:
|
||||
self.filenames[ filename ] = dict( found=found, filename=filename, from_shed_config=from_shed_config, tool_data_path=tool_data_path,
|
||||
@@ -461,7 +461,7 @@ class TabularToolDataTable( ToolDataTable, Dictifiable ):
|
||||
line_error = "Line %i in tool data table '%s' is invalid (HINT: '%s' characters must be used to separate fields):\n%s" % ( ( i + 1 ), self.name, separator_char, line )
|
||||
if errors is not None:
|
||||
errors.append( line_error )
|
||||
log.warn( line_error )
|
||||
log.warning( line_error )
|
||||
return rval
|
||||
|
||||
def get_column_name_list( self ):
|
||||
@@ -590,7 +590,7 @@ class TabularToolDataTable( ToolDataTable, Dictifiable ):
|
||||
values = self._replace_field_separators( values )
|
||||
self.filter_file_fields( filename, values )
|
||||
else:
|
||||
log.warn( "Cannot find index file '%s' for tool data table '%s'" % ( filename, self.name ) )
|
||||
log.warning( "Cannot find index file '%s' for tool data table '%s'" % ( filename, self.name ) )
|
||||
|
||||
self.reload_from_files()
|
||||
|
||||
|
||||
@@ -78,9 +78,9 @@ class DependencyManager( object ):
|
||||
in `base_paths`. The default base path is app.config.tool_dependency_dir.
|
||||
"""
|
||||
if not os.path.exists( default_base_path ):
|
||||
log.warn( "Path '%s' does not exist, ignoring", default_base_path )
|
||||
log.warning( "Path '%s' does not exist, ignoring", default_base_path )
|
||||
if not os.path.isdir( default_base_path ):
|
||||
log.warn( "Path '%s' is not directory, ignoring", default_base_path )
|
||||
log.warning( "Path '%s' is not directory, ignoring", default_base_path )
|
||||
self.extra_config = extra_config
|
||||
self.default_base_path = os.path.abspath( default_base_path )
|
||||
self.resolver_classes = self.__resolvers_dict()
|
||||
@@ -98,7 +98,7 @@ class DependencyManager( object ):
|
||||
**kwds )
|
||||
dependency_commands = dependency.shell_commands( requirement )
|
||||
if not dependency_commands:
|
||||
log.warn( "Failed to resolve dependency on '%s', ignoring", requirement.name )
|
||||
log.warning( "Failed to resolve dependency on '%s', ignoring", requirement.name )
|
||||
else:
|
||||
commands.append( dependency_commands )
|
||||
return commands
|
||||
|
||||
@@ -7,6 +7,11 @@ from galaxy.util import which
|
||||
|
||||
STDOUT_INDICATOR = "-"
|
||||
|
||||
try:
|
||||
from shlex import quote as shell_quote
|
||||
except ImportError:
|
||||
from pipes import quote as shell_quote
|
||||
|
||||
|
||||
def redirecting_io(sys=_sys):
|
||||
"""Predicate to determine if we are redicting I/O in process."""
|
||||
@@ -70,14 +75,27 @@ def execute(cmds):
|
||||
|
||||
Return the standard output if the commands are successful
|
||||
"""
|
||||
return _wait(cmds, shell=False)
|
||||
return _wait(cmds, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
|
||||
|
||||
def argv_to_str(command_argv, quote=True):
|
||||
"""Convert an argv command list to a string for shell subprocess.
|
||||
|
||||
If None appears in the command list it is simply excluded.
|
||||
|
||||
Arguments are quoted with shlex.quote. That said, this method is not meant to be
|
||||
used in security critical paths of code and should not be used to sanitize
|
||||
code.
|
||||
"""
|
||||
map_func = shell_quote if quote else lambda x: x
|
||||
return " ".join([map_func(c) for c in command_argv if c is not None])
|
||||
|
||||
|
||||
def _wait(cmds, **popen_kwds):
|
||||
p = subprocess.Popen(cmds, **popen_kwds)
|
||||
stdout, stderr = p.communicate()
|
||||
if p.returncode != 0:
|
||||
raise CommandLineException(" ".join(cmds), stdout, stderr)
|
||||
raise CommandLineException(argv_to_str(cmds), stdout, stderr)
|
||||
return stdout
|
||||
|
||||
|
||||
@@ -127,6 +145,7 @@ class CommandLineException(Exception):
|
||||
|
||||
|
||||
__all__ = [
|
||||
'argv_to_str',
|
||||
'CommandLineException',
|
||||
'download_command',
|
||||
'execute',
|
||||
@@ -134,5 +153,6 @@ __all__ = [
|
||||
'redirecting_io',
|
||||
'shell',
|
||||
'shell_process',
|
||||
'shell_quote',
|
||||
'which',
|
||||
]
|
||||
|
||||
@@ -23,6 +23,7 @@ CONDA_LICENSE = "http://docs.continuum.io/anaconda/eula"
|
||||
VERSIONED_ENV_DIR_NAME = re.compile(r"__package__(.*)@__version__(.*)")
|
||||
UNVERSIONED_ENV_DIR_NAME = re.compile(r"__package__(.*)@__unversioned__")
|
||||
USE_PATH_EXEC_DEFAULT = False
|
||||
CONDA_VERSION = "3.19.3"
|
||||
|
||||
|
||||
def conda_link():
|
||||
@@ -264,7 +265,8 @@ def install_conda(conda_context=None):
|
||||
os.close(f)
|
||||
download_cmd = " ".join(commands.download_command(conda_link(), to=script_path, quote_url=True))
|
||||
install_cmd = "bash '%s' -b -p '%s'" % (script_path, conda_context.conda_prefix)
|
||||
full_command = "%s; %s" % (download_cmd, install_cmd)
|
||||
fix_version_cmd = "%s install -y -q conda=%s " % (os.path.join(conda_context.conda_prefix, 'bin/conda'), CONDA_VERSION)
|
||||
full_command = "%s && %s && %s" % (download_cmd, install_cmd, fix_version_cmd)
|
||||
try:
|
||||
return conda_context.shell_exec(full_command)
|
||||
finally:
|
||||
@@ -284,6 +286,27 @@ def install_conda_target(conda_target, conda_context=None):
|
||||
conda_context.exec_create(create_args)
|
||||
|
||||
|
||||
def is_target_available(conda_target, conda_context=None):
|
||||
""" Checks if a specified target is available for installation.
|
||||
If the package name exists return "True". If in addition the version matches exactly return "exact".
|
||||
Otherwise return False.
|
||||
"""
|
||||
conda_context = _ensure_conda_context(conda_context)
|
||||
conda_context.ensure_channels_configured()
|
||||
search_cmd = [conda_context.conda_exec, "search", "--full-name", "--json", conda_target.package]
|
||||
res = commands.execute(search_cmd)
|
||||
hits = json.loads(res).get(conda_target.package, [])
|
||||
|
||||
if len(hits) > 0:
|
||||
if conda_target.version:
|
||||
for hit in hits:
|
||||
if hit['version'] == conda_target.version:
|
||||
return 'exact'
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def is_conda_target_installed(conda_target, conda_context=None):
|
||||
conda_context = _ensure_conda_context(conda_context)
|
||||
return conda_context.has_env(conda_target.install_environment)
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
"""Utilities for building up Docker commands...
|
||||
|
||||
...using common defaults and configuration mechanisms.
|
||||
"""
|
||||
import os
|
||||
from .commands import argv_to_str, shell_quote
|
||||
|
||||
DEFAULT_DOCKER_COMMAND = "docker"
|
||||
DEFAULT_SUDO = True
|
||||
@@ -54,6 +59,22 @@ class DockerVolume(object):
|
||||
return ":".join([self.from_path, self.to_path, self.how])
|
||||
|
||||
|
||||
def kill_command(
|
||||
container,
|
||||
signal=None,
|
||||
**kwds
|
||||
):
|
||||
args = (["-s", signal] if signal else []) + [container]
|
||||
return command_list("kill", args, **kwds)
|
||||
|
||||
|
||||
def logs_command(
|
||||
container,
|
||||
**kwds
|
||||
):
|
||||
return command_list("logs", **kwds)
|
||||
|
||||
|
||||
def build_command(
|
||||
image,
|
||||
docker_build_path,
|
||||
@@ -61,9 +82,7 @@ def build_command(
|
||||
):
|
||||
if os.path.isfile(docker_build_path):
|
||||
docker_build_path = os.path.dirname(os.path.abspath(docker_build_path))
|
||||
build_command_parts = __docker_prefix(**kwds)
|
||||
build_command_parts.extend(["build", "-t", image, docker_build_path])
|
||||
return build_command_parts
|
||||
return command_list("build", ["-t", image, docker_build_path], **kwds)
|
||||
|
||||
|
||||
def build_save_image_command(
|
||||
@@ -71,47 +90,33 @@ def build_save_image_command(
|
||||
destination,
|
||||
**kwds
|
||||
):
|
||||
build_command_parts = __docker_prefix(**kwds)
|
||||
build_command_parts.extend(["save", "-o", destination, image])
|
||||
return build_command_parts
|
||||
return command_list("save", ["-o", destination, image], **kwds)
|
||||
|
||||
|
||||
def build_pull_command(
|
||||
tag,
|
||||
**kwds
|
||||
):
|
||||
build_command_parts = __docker_prefix(**kwds)
|
||||
build_command_parts.extend(["pull", tag])
|
||||
return build_command_parts
|
||||
return command_list("pull", [tag], **kwds)
|
||||
|
||||
|
||||
def build_docker_cache_command(
|
||||
image,
|
||||
**kwds
|
||||
):
|
||||
inspect_command_parts = __docker_prefix(**kwds)
|
||||
inspect_command_parts.extend(["inspect", image])
|
||||
inspect_image_command = " ".join(inspect_command_parts)
|
||||
|
||||
pull_command_parts = __docker_prefix(**kwds)
|
||||
pull_command_parts.extend(["pull", image])
|
||||
pull_image_command = " ".join(pull_command_parts)
|
||||
inspect_image_command = command_shell("inspect", [image], **kwds)
|
||||
pull_image_command = command_shell("pull", [image], **kwds)
|
||||
cache_command = "%s > /dev/null 2>&1\n[ $? -ne 0 ] && %s > /dev/null 2>&1\n" % (inspect_image_command, pull_image_command)
|
||||
return cache_command
|
||||
|
||||
|
||||
def build_docker_images_command(truncate=True, **kwds):
|
||||
images_command_parts = __docker_prefix(**kwds)
|
||||
images_command_parts.append("images")
|
||||
if not truncate:
|
||||
images_command_parts.append("--no-trunc")
|
||||
return " ".join(images_command_parts)
|
||||
args = ["--no-trunc"] if not truncate else[]
|
||||
return command_shell("images", args, **kwds)
|
||||
|
||||
|
||||
def build_docker_load_command(**kwds):
|
||||
load_command_parts = __docker_prefix(**kwds)
|
||||
load_command_parts.append("load")
|
||||
return " ".join(load_command_parts)
|
||||
return command_shell("load", [])
|
||||
|
||||
|
||||
def build_docker_run_command(
|
||||
@@ -135,7 +140,7 @@ def build_docker_run_command(
|
||||
set_user=DEFAULT_SET_USER,
|
||||
host=DEFAULT_HOST,
|
||||
):
|
||||
command_parts = __docker_prefix(
|
||||
command_parts = _docker_prefix(
|
||||
docker_cmd=docker_cmd,
|
||||
sudo=sudo,
|
||||
sudo_cmd=sudo_cmd,
|
||||
@@ -147,19 +152,19 @@ def build_docker_run_command(
|
||||
if terminal:
|
||||
command_parts.append("-t")
|
||||
for env_directive in env_directives:
|
||||
command_parts.extend(["-e", env_directive])
|
||||
command_parts.extend(["-e", shell_quote(env_directive)])
|
||||
for volume in volumes:
|
||||
command_parts.extend(["-v", str(volume)])
|
||||
command_parts.extend(["-v", shell_quote(str(volume))])
|
||||
if volumes_from:
|
||||
command_parts.extend(["--volumes-from", str(volumes_from)])
|
||||
command_parts.extend(["--volumes-from", shell_quote(str(volumes_from))])
|
||||
if memory:
|
||||
command_parts.extend(["-m", memory])
|
||||
command_parts.extend(["-m", shell_quote(memory)])
|
||||
if name:
|
||||
command_parts.extend(["-name", name])
|
||||
command_parts.extend(["--name", shell_quote(name)])
|
||||
if working_directory:
|
||||
command_parts.extend(["-w", working_directory])
|
||||
command_parts.extend(["-w", shell_quote(working_directory)])
|
||||
if net:
|
||||
command_parts.extend(["--net", net])
|
||||
command_parts.extend(["--net", shell_quote(net)])
|
||||
if auto_rm:
|
||||
command_parts.append("--rm")
|
||||
if run_extra_arguments:
|
||||
@@ -172,20 +177,31 @@ def build_docker_run_command(
|
||||
full_image = image
|
||||
if tag:
|
||||
full_image = "%s:%s" % (full_image, tag)
|
||||
command_parts.append(full_image)
|
||||
command_parts.append(shell_quote(full_image))
|
||||
command_parts.append(container_command)
|
||||
return " ".join(command_parts)
|
||||
|
||||
|
||||
def __docker_prefix(
|
||||
def command_list(command, command_args=[], **kwds):
|
||||
"""Return Docker command as an argv list."""
|
||||
command_parts = _docker_prefix(**kwds)
|
||||
command_parts.extend(command_parts)
|
||||
return command_parts
|
||||
|
||||
|
||||
def command_shell(command, command_args=[], **kwds):
|
||||
"""Return Docker command as a string for a shell."""
|
||||
return argv_to_str(command_list(command, command_args, **kwds))
|
||||
|
||||
|
||||
def _docker_prefix(
|
||||
docker_cmd=DEFAULT_DOCKER_COMMAND,
|
||||
sudo=DEFAULT_SUDO,
|
||||
sudo_cmd=DEFAULT_SUDO_COMMAND,
|
||||
host=DEFAULT_HOST,
|
||||
**kwds
|
||||
):
|
||||
""" Prefix to issue a docker command.
|
||||
"""
|
||||
"""Prefix to issue a docker command."""
|
||||
command_parts = []
|
||||
if sudo:
|
||||
command_parts.append(sudo_cmd)
|
||||
|
||||
@@ -102,7 +102,7 @@ class CondaDependencyResolver(DependencyResolver, ListableDependencyResolver, In
|
||||
|
||||
job_directory = kwds.get("job_directory", None)
|
||||
if job_directory is None:
|
||||
log.warn("Conda dependency resolver not sent job directory.")
|
||||
log.warning("Conda dependency resolver not sent job directory.")
|
||||
return INDETERMINATE_DEPENDENCY
|
||||
|
||||
exact = not self.versionless or version is None
|
||||
|
||||
@@ -97,7 +97,7 @@ class GalaxyPackageDependency(Dependency):
|
||||
def shell_commands( self, requirement ):
|
||||
base_path = self.path
|
||||
if self.script is None and base_path is None:
|
||||
log.warn( "Failed to resolve dependency on '%s', ignoring", requirement.name )
|
||||
log.warning( "Failed to resolve dependency on '%s', ignoring", requirement.name )
|
||||
commands = None
|
||||
elif requirement.type == 'package' and self.script is None:
|
||||
commands = 'PACKAGE_BASE=%s; export PACKAGE_BASE; PATH="%s/bin:$PATH"; export PATH' % ( base_path, base_path )
|
||||
|
||||
@@ -74,7 +74,7 @@ class DirectoryModuleChecker(object):
|
||||
self.module_dependency_resolver = module_dependency_resolver
|
||||
self.directories = modulepath.split(pathsep)
|
||||
if prefetch:
|
||||
log.warn("Created module dependency resolver with prefetch enabled, but directory module checker does not support this.")
|
||||
log.warning("Created module dependency resolver with prefetch enabled, but directory module checker does not support this.")
|
||||
|
||||
def has_module(self, module, version):
|
||||
has_module = False
|
||||
|
||||
@@ -109,7 +109,7 @@ class ToolExecutionTracker( object ):
|
||||
def record_error( self, error ):
|
||||
self.failed_jobs += 1
|
||||
message = "There was a failure executing a job for tool [%s] - %s"
|
||||
log.warn(message, self.tool.id, error)
|
||||
log.warning(message, self.tool.id, error)
|
||||
self.execution_errors.append( error )
|
||||
|
||||
def create_output_collections( self, trans, history, params ):
|
||||
@@ -137,7 +137,7 @@ class ToolExecutionTracker( object ):
|
||||
if not len( structure ) == len( outputs ):
|
||||
# Output does not have the same structure, if all jobs were
|
||||
# successfully submitted this shouldn't have happened.
|
||||
log.warn( "Problem matching up datasets while attempting to create implicit dataset collections")
|
||||
log.warning( "Problem matching up datasets while attempting to create implicit dataset collections")
|
||||
continue
|
||||
output = self.tool.outputs[ output_name ]
|
||||
element_identifiers = structure.element_identifiers_for_outputs( trans, outputs )
|
||||
|
||||
@@ -26,7 +26,7 @@ CWL_EXTENSIONS = YAML_EXTENSIONS + [".cwl"]
|
||||
|
||||
def load_exception_handler(path, exc_info):
|
||||
"""Default exception handler for use by load_tool_elements_from_path."""
|
||||
log.warn(LOAD_FAILURE_ERROR % path, exc_info=exc_info)
|
||||
log.warning(LOAD_FAILURE_ERROR % path, exc_info=exc_info)
|
||||
|
||||
|
||||
def find_possible_tools_from_path(
|
||||
|
||||
@@ -25,9 +25,12 @@ from .dataset_matcher import DatasetCollectionMatcher
|
||||
from galaxy.web import url_for
|
||||
from galaxy.util.dictifiable import Dictifiable
|
||||
import galaxy.model
|
||||
from galaxy.util.bunch import Bunch
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
workflow_building_modes = Bunch( DISABLED=False, ENABLED=True, USE_HISTORY=1 )
|
||||
|
||||
WORKFLOW_PARAMETER_REGULAR_EXPRESSION = re.compile( '''\$\{.+?\}''' )
|
||||
|
||||
|
||||
@@ -171,7 +174,9 @@ class ToolParameter( object, Dictifiable ):
|
||||
Convert a value to a text representation suitable for displaying to
|
||||
the user
|
||||
"""
|
||||
return unicodify( value )
|
||||
if value:
|
||||
return unicodify( value )
|
||||
return "Not available."
|
||||
|
||||
def to_param_dict_string( self, value, other_values={} ):
|
||||
"""Called via __str__ when used in the Cheetah template"""
|
||||
@@ -264,7 +269,7 @@ class TextToolParameter( ToolParameter ):
|
||||
|
||||
def validate( self, value, trans=None ):
|
||||
search = self.type == "text"
|
||||
if not ( trans and trans.workflow_building_mode and contains_workflow_parameter(value, search=search) ):
|
||||
if not ( trans and trans.workflow_building_mode is workflow_building_modes.ENABLED and contains_workflow_parameter(value, search=search) ):
|
||||
return super( TextToolParameter, self ).validate( value, trans )
|
||||
|
||||
def get_initial_value( self, trans, other_values ):
|
||||
@@ -331,11 +336,11 @@ class IntegerToolParameter( TextToolParameter ):
|
||||
try:
|
||||
return int( value )
|
||||
except:
|
||||
if contains_workflow_parameter( value ) and trans.workflow_building_mode:
|
||||
if contains_workflow_parameter( value ) and trans.workflow_building_mode is workflow_building_modes.ENABLED:
|
||||
return value
|
||||
if not value and self.optional:
|
||||
return ""
|
||||
if trans.workflow_building_mode:
|
||||
if trans.workflow_building_mode is workflow_building_modes.ENABLED:
|
||||
raise ValueError( "An integer or workflow parameter e.g. ${name} is required" )
|
||||
else:
|
||||
raise ValueError( "An integer is required" )
|
||||
@@ -411,11 +416,11 @@ class FloatToolParameter( TextToolParameter ):
|
||||
try:
|
||||
return float( value )
|
||||
except:
|
||||
if contains_workflow_parameter( value ) and trans.workflow_building_mode:
|
||||
if contains_workflow_parameter( value ) and trans.workflow_building_mode is workflow_building_modes.ENABLED:
|
||||
return value
|
||||
if not value and self.optional:
|
||||
return ""
|
||||
if trans and trans.workflow_building_mode:
|
||||
if trans and trans.workflow_building_mode is workflow_building_modes.ENABLED:
|
||||
raise ValueError( "A real number or workflow parameter e.g. ${name} is required" )
|
||||
else:
|
||||
raise ValueError( "A real number is required" )
|
||||
@@ -986,7 +991,9 @@ class SelectToolParameter( ToolParameter ):
|
||||
for t, v, s in options:
|
||||
if v in value:
|
||||
rval.append( t )
|
||||
return "\n".join( rval )
|
||||
if rval:
|
||||
return "\n".join( rval )
|
||||
return "Nothing selected."
|
||||
|
||||
def get_dependencies( self ):
|
||||
"""
|
||||
@@ -1001,15 +1008,7 @@ class SelectToolParameter( ToolParameter ):
|
||||
d = super( SelectToolParameter, self ).to_dict( trans )
|
||||
|
||||
# Get options, value.
|
||||
options = []
|
||||
try:
|
||||
options = self.get_options( trans, other_values )
|
||||
except AssertionError:
|
||||
# we dont/cant set other_values (the {} above), so params that require other params to be filled will error:
|
||||
# required dependency in filter_options
|
||||
# associated DataToolParam in get_column_list
|
||||
pass
|
||||
|
||||
options = self.get_options( trans, other_values )
|
||||
d[ 'options' ] = options
|
||||
if options:
|
||||
value = options[0][1]
|
||||
@@ -1191,10 +1190,8 @@ class ColumnListParameter( SelectToolParameter ):
|
||||
Generate a select list containing the columns of the associated
|
||||
dataset (if found).
|
||||
"""
|
||||
# No value indicates a configuration error
|
||||
assert self.data_ref in other_values, "Value for associated data reference not found (data_ref)."
|
||||
# Get the value of the associated data reference (a dataset)
|
||||
dataset = other_values[ self.data_ref ]
|
||||
dataset = other_values.get( self.data_ref, None )
|
||||
# Check if a dataset is selected
|
||||
if not dataset:
|
||||
return []
|
||||
@@ -1228,8 +1225,7 @@ class ColumnListParameter( SelectToolParameter ):
|
||||
"""
|
||||
options = []
|
||||
if self.usecolnames: # read first row - assume is a header with metadata useful for making good choices
|
||||
assert self.data_ref in other_values, "Value for associated data reference not found (data_ref)."
|
||||
dataset = other_values[ self.data_ref ]
|
||||
dataset = other_values.get( self.data_ref, None )
|
||||
try:
|
||||
head = open( dataset.get_file_name(), 'r' ).readline()
|
||||
cnames = head.rstrip().split( '\t' )
|
||||
@@ -1256,6 +1252,8 @@ class ColumnListParameter( SelectToolParameter ):
|
||||
return SelectToolParameter.get_initial_value( self, trans, other_values )
|
||||
|
||||
def get_legal_values( self, trans, other_values ):
|
||||
if self.data_ref not in other_values:
|
||||
raise ValueError( "Value for associated data reference not found (data_ref)." )
|
||||
return set( self.get_column_list( trans, other_values ) )
|
||||
|
||||
def get_dependencies( self ):
|
||||
@@ -1484,15 +1482,16 @@ class DrillDownSelectToolParameter( SelectToolParameter ):
|
||||
value = value.split( "\n" )
|
||||
return value
|
||||
if not value and not self.optional:
|
||||
raise ValueError( "An invalid option was selected for %s, 'None', please verify" % (self.name) )
|
||||
raise ValueError( "An invalid option was selected for %s, please verify." % (self.name) )
|
||||
if not value:
|
||||
return None
|
||||
if not isinstance( value, list ):
|
||||
value = [ value ]
|
||||
if not( self.repeat ) and len( value ) > 1:
|
||||
assert self.multiple, "Multiple values provided but parameter %s is not expecting multiple values" % self.name
|
||||
if not self.repeat and len( value ) > 1 and not self.multiple:
|
||||
raise ValueError( "Multiple values provided but parameter %s is not expecting multiple values." % self.name )
|
||||
rval = []
|
||||
assert legal_values, "Parameter %s requires a value, but has no legal values defined" % self.name
|
||||
if not legal_values:
|
||||
raise ValueError( "Parameter %s requires a value, but has no legal values defined." % self.name )
|
||||
for val in value:
|
||||
if val not in legal_values:
|
||||
raise ValueError( "An invalid option was selected for %s, %r, please verify" % ( self.name, val ) )
|
||||
@@ -1529,9 +1528,8 @@ class DrillDownSelectToolParameter( SelectToolParameter ):
|
||||
for val in value:
|
||||
options = get_options_list( val )
|
||||
rval.extend( options )
|
||||
if len( rval ) > 1:
|
||||
if not self.repeat:
|
||||
assert self.multiple, "Multiple values provided but parameter is not expecting multiple values"
|
||||
if not self.repeat and len( rval ) > 1 and not self.multiple:
|
||||
raise ValueError( "Multiple values provided but parameter %s is not expecting multiple values." % self.name )
|
||||
rval = self.separator.join( map( value_map, rval ) )
|
||||
if self.tool is None or self.tool.options.sanitize:
|
||||
if self.sanitizer:
|
||||
@@ -1583,7 +1581,9 @@ class DrillDownSelectToolParameter( SelectToolParameter ):
|
||||
rval = []
|
||||
for val in value:
|
||||
rval.append( get_option_display( val, self.options ) or val )
|
||||
return "\n".join( map( str, rval ) )
|
||||
if rval:
|
||||
return "\n".join( map( str, rval ) )
|
||||
return "Nothing selected."
|
||||
|
||||
def get_dependencies( self ):
|
||||
"""
|
||||
@@ -1594,15 +1594,7 @@ class DrillDownSelectToolParameter( SelectToolParameter ):
|
||||
def to_dict( self, trans, view='collection', value_mapper=None, other_values={} ):
|
||||
# skip SelectToolParameter (the immediate parent) bc we need to get options in a different way here
|
||||
d = ToolParameter.to_dict( self, trans )
|
||||
|
||||
options = []
|
||||
try:
|
||||
options = self.get_options( trans=trans, other_values=other_values )
|
||||
except KeyError:
|
||||
# will sometimes error if self.is_dynamic and self.filtered
|
||||
# bc we dont/cant fill out other_values above ({})
|
||||
pass
|
||||
d['options'] = options
|
||||
d['options'] = self.get_options( trans=trans, other_values=other_values )
|
||||
d['display'] = self.display
|
||||
return d
|
||||
|
||||
@@ -1871,7 +1863,7 @@ class DataToolParameter( BaseDataToolParameter ):
|
||||
return ''
|
||||
|
||||
def from_json( self, value, trans, other_values={} ):
|
||||
if trans.workflow_building_mode:
|
||||
if trans.workflow_building_mode is workflow_building_modes.ENABLED:
|
||||
return None
|
||||
if not value and not self.optional:
|
||||
raise ValueError( "History does not include a dataset of the required format / build" )
|
||||
@@ -1937,8 +1929,11 @@ class DataToolParameter( BaseDataToolParameter ):
|
||||
raise ValueError( "The previously selected dataset has entered an unusable state" )
|
||||
if not self.multiple:
|
||||
if len( values ) > 1:
|
||||
raise ValueError( "More than one dataset supplied to single input dataset parameter.")
|
||||
rval = values[ 0 ]
|
||||
raise ValueError( "More than one dataset supplied to single input dataset parameter." )
|
||||
if len( values ) > 0:
|
||||
rval = values[ 0 ]
|
||||
else:
|
||||
raise ValueError( "Invalid dataset supplied to single input dataset parameter." )
|
||||
return rval
|
||||
|
||||
def to_param_dict_string( self, value, other_values={} ):
|
||||
@@ -1954,7 +1949,7 @@ class DataToolParameter( BaseDataToolParameter ):
|
||||
return ", ".join( [ "%s: %s" % ( item.hid, item.name ) for item in value ] )
|
||||
except:
|
||||
pass
|
||||
return "No dataset"
|
||||
return "No dataset."
|
||||
|
||||
def validate( self, value, trans=None ):
|
||||
dataset_count = 0
|
||||
@@ -2035,10 +2030,13 @@ class DataToolParameter( BaseDataToolParameter ):
|
||||
d = super( DataToolParameter, self ).to_dict( trans )
|
||||
extensions = self.extensions
|
||||
all_edam_formats = self._datatypes_registery( trans, self.tool ).edam_formats
|
||||
all_edam_data = self._datatypes_registery( trans, self.tool ).edam_data
|
||||
edam_formats = map(lambda ext: all_edam_formats.get(ext, None),
|
||||
extensions)
|
||||
edam_data = map(lambda ext: all_edam_data.get(ext, None), extensions)
|
||||
|
||||
d['extensions'] = extensions
|
||||
d['edam_formats'] = edam_formats
|
||||
d['edam'] = {'edam_formats': edam_formats, 'edam_data': edam_data}
|
||||
d['multiple'] = self.multiple
|
||||
if self.multiple:
|
||||
# For consistency, should these just always be in the dict?
|
||||
@@ -2048,7 +2046,7 @@ class DataToolParameter( BaseDataToolParameter ):
|
||||
|
||||
# return dictionary without options if context is unavailable
|
||||
history = trans.history
|
||||
if history is None or trans.workflow_building_mode:
|
||||
if history is None or trans.workflow_building_mode is workflow_building_modes.ENABLED:
|
||||
return d
|
||||
|
||||
# prepare dataset/collection matching
|
||||
@@ -2149,7 +2147,7 @@ class DataCollectionToolParameter( BaseDataToolParameter ):
|
||||
return field
|
||||
|
||||
def from_json( self, value, trans, other_values={} ):
|
||||
if trans.workflow_building_mode:
|
||||
if trans.workflow_building_mode is workflow_building_modes.ENABLED:
|
||||
return None
|
||||
if not value and not self.optional:
|
||||
raise ValueError( "History does not include a dataset collection of the correct type or containing the correct types of datasets" )
|
||||
@@ -2210,7 +2208,7 @@ class DataCollectionToolParameter( BaseDataToolParameter ):
|
||||
|
||||
# return dictionary without options if context is unavailable
|
||||
history = trans.history
|
||||
if history is None or trans.workflow_building_mode or other_values is None:
|
||||
if history is None or trans.workflow_building_mode is workflow_building_modes.ENABLED or other_values is None:
|
||||
return d
|
||||
|
||||
# prepare dataset/collection matching
|
||||
|
||||
@@ -124,7 +124,6 @@ class DataMetaFilter( Filter ):
|
||||
if self.multiple:
|
||||
return dataset_value in file_value.split( self.separator )
|
||||
return file_value == dataset_value
|
||||
assert self.ref_name in other_values or ( trans is not None and trans.workflow_building_mode), "Required dependency '%s' not found in incoming values" % self.ref_name
|
||||
ref = other_values.get( self.ref_name, None )
|
||||
is_data = isinstance( ref, galaxy.tools.wrappers.DatasetFilenameWrapper )
|
||||
is_data_list = isinstance( ref, galaxy.tools.wrappers.DatasetListWrapper ) or isinstance( ref, list )
|
||||
@@ -146,7 +145,7 @@ class DataMetaFilter( Filter ):
|
||||
else:
|
||||
meta_value = ref.metadata.get( self.key, None )
|
||||
|
||||
if meta_value is None: # assert meta_value is not None, "Required metadata value '%s' not found in referenced dataset" % self.key
|
||||
if meta_value is None:
|
||||
return [ ( disp_name, optval, selected ) for disp_name, optval, selected in options ]
|
||||
|
||||
if self.column is not None:
|
||||
@@ -208,7 +207,6 @@ class ParamValueFilter( Filter ):
|
||||
def filter_options( self, options, trans, other_values ):
|
||||
if trans is not None and trans.workflow_building_mode:
|
||||
return []
|
||||
assert self.ref_name in other_values, "Required dependency '%s' not found in incoming values" % self.ref_name
|
||||
ref = other_values.get( self.ref_name, None )
|
||||
for ref_attribute in self.ref_attribute:
|
||||
if not hasattr( ref, ref_attribute ):
|
||||
@@ -381,7 +379,6 @@ class RemoveValueFilter( Filter ):
|
||||
def filter_options( self, options, trans, other_values ):
|
||||
if trans is not None and trans.workflow_building_mode:
|
||||
return options
|
||||
assert self.value is not None or ( self.ref_name is not None and self.ref_name in other_values ) or (self.meta_ref is not None and self.meta_ref in other_values ) or ( trans is not None and trans.workflow_building_mode), Exception( "Required dependency '%s' or '%s' not found in incoming values" % ( self.ref_name, self.meta_ref ) )
|
||||
|
||||
def compare_value( option_value, filter_value ):
|
||||
if isinstance( filter_value, list ):
|
||||
@@ -494,7 +491,7 @@ class DynamicOptions( object ):
|
||||
self.missing_index_file = self.tool_data_table.missing_index_file
|
||||
else:
|
||||
self.missing_tool_data_table_name = tool_data_table_name
|
||||
log.warn( "Data table named '%s' is required by tool but not configured" % tool_data_table_name )
|
||||
log.warning( "Data table named '%s' is required by tool but not configured" % tool_data_table_name )
|
||||
# Options are defined by parsing tabular text data from a data file
|
||||
# on disk, a dataset, or the value of another parameter
|
||||
elif data_file is not None or dataset_file is not None or from_parameter is not None:
|
||||
@@ -559,7 +556,7 @@ class DynamicOptions( object ):
|
||||
except AttributeError:
|
||||
name = "a configuration file"
|
||||
# Perhaps this should be an error, but even a warning is useful.
|
||||
log.warn( "Inconsistent number of fields (%i vs %i) in %s using separator %r, check line: %r" %
|
||||
log.warning( "Inconsistent number of fields (%i vs %i) in %s using separator %r, check line: %r" %
|
||||
( field_count, len( fields ), name, self.separator, line ) )
|
||||
rval.append( fields )
|
||||
return rval
|
||||
@@ -582,7 +579,6 @@ class DynamicOptions( object ):
|
||||
if self.dataset_ref_name:
|
||||
dataset = other_values.get( self.dataset_ref_name, None )
|
||||
if not dataset or not hasattr( dataset, 'file_name' ):
|
||||
log.warn( "Required dataset '%s' missing from input" % self.dataset_ref_name )
|
||||
return [] # no valid dataset in history
|
||||
# Ensure parsing dynamic options does not consume more than a megabyte worth memory.
|
||||
path = dataset.file_name
|
||||
@@ -591,7 +587,7 @@ class DynamicOptions( object ):
|
||||
else:
|
||||
# Pass just the first megabyte to parse_file_fields.
|
||||
import StringIO
|
||||
log.warn( "Attempting to load options from large file, reading just first megabyte" )
|
||||
log.warning( "Attempting to load options from large file, reading just first megabyte" )
|
||||
contents = open( path, 'r' ).read( 1048576 )
|
||||
options = self.parse_file_fields( StringIO.StringIO( contents ) )
|
||||
elif self.tool_data_table:
|
||||
|
||||
@@ -62,6 +62,8 @@ class ToolOutput( ToolOutputBase ):
|
||||
if format and format != "input" and app:
|
||||
edam_format = app.datatypes_registry.edam_formats.get(self.format)
|
||||
as_dict["edam_format"] = edam_format
|
||||
edam_data = app.datatypes_registry.edam_data.get(self.format)
|
||||
as_dict["edam_data"] = edam_data
|
||||
return as_dict
|
||||
|
||||
|
||||
|
||||
@@ -78,6 +78,18 @@ class XmlToolSource(ToolSource):
|
||||
def parse_name(self):
|
||||
return self.root.get( "name" )
|
||||
|
||||
def parse_edam_operations(self):
|
||||
edam_ops = self.root.find("edam_operations")
|
||||
if edam_ops is None:
|
||||
return []
|
||||
return [ edam_op.text for edam_op in edam_ops.findall("edam_operation") ]
|
||||
|
||||
def parse_edam_topics(self):
|
||||
edam_topics = self.root.find("edam_topics")
|
||||
if edam_topics is None:
|
||||
return []
|
||||
return [ edam_topic.text for edam_topic in edam_topics.findall("edam_topic") ]
|
||||
|
||||
def parse_description(self):
|
||||
return xml_text(self.root, "description")
|
||||
|
||||
@@ -117,7 +129,7 @@ class XmlToolSource(ToolSource):
|
||||
command_el = self._command_el
|
||||
interpreter = (command_el is not None) and command_el.get("interpreter", None)
|
||||
if not self.legacy_defaults:
|
||||
log.warn("Deprecated interpeter attribute on command element is now ignored.")
|
||||
log.warning("Deprecated interpeter attribute on command element is now ignored.")
|
||||
interpreter = None
|
||||
|
||||
return interpreter
|
||||
@@ -426,7 +438,11 @@ def __parse_element_tests( parent_element ):
|
||||
|
||||
def __parse_test_attributes( output_elem, attrib, parse_elements=False ):
|
||||
assert_list = __parse_assert_list( output_elem )
|
||||
file = attrib.pop( 'file', None )
|
||||
|
||||
# Allow either file or value to specify a target file to compare result with
|
||||
# file was traditionally used by outputs and value by extra files.
|
||||
file = attrib.pop( 'file', attrib.pop( 'value', None ) )
|
||||
|
||||
# File no longer required if an list of assertions was present.
|
||||
attributes = {}
|
||||
# Method of comparison
|
||||
@@ -445,16 +461,19 @@ def __parse_test_attributes( output_elem, attrib, parse_elements=False ):
|
||||
for metadata_elem in output_elem.findall( 'metadata' ):
|
||||
metadata[ metadata_elem.get('name') ] = metadata_elem.get( 'value' )
|
||||
md5sum = attrib.get("md5", None)
|
||||
checksum = attrib.get("checksum", None)
|
||||
element_tests = {}
|
||||
if parse_elements:
|
||||
element_tests = __parse_element_tests( output_elem )
|
||||
|
||||
if not (assert_list or file or extra_files or metadata or md5sum or element_tests):
|
||||
raise Exception( "Test output defines nothing to check (e.g. must have a 'file' check against, assertions to check, metadata or md5 tests, etc...)")
|
||||
has_checksum = md5sum or checksum
|
||||
if not (assert_list or file or extra_files or metadata or has_checksum or element_tests):
|
||||
raise Exception( "Test output defines nothing to check (e.g. must have a 'file' check against, assertions to check, metadata or checksum tests, etc...)")
|
||||
attributes['assert_list'] = assert_list
|
||||
attributes['extra_files'] = extra_files
|
||||
attributes['metadata'] = metadata
|
||||
attributes['md5'] = md5sum
|
||||
attributes['checksum'] = checksum
|
||||
attributes['elements'] = element_tests
|
||||
return file, attributes
|
||||
|
||||
@@ -484,20 +503,15 @@ def __parse_assert_list_from_elem( assert_elem ):
|
||||
return assert_list
|
||||
|
||||
|
||||
def __parse_extra_files_elem( extra ):
|
||||
def __parse_extra_files_elem(extra):
|
||||
# File or directory, when directory, compare basename
|
||||
# by basename
|
||||
extra_type = extra.get( 'type', 'file' )
|
||||
extra_name = extra.get( 'name', None )
|
||||
attrib = dict(extra.attrib)
|
||||
extra_type = attrib.pop('type', 'file')
|
||||
extra_name = attrib.pop('name', None)
|
||||
assert extra_type == 'directory' or extra_name is not None, \
|
||||
'extra_files type (%s) requires a name attribute' % extra_type
|
||||
extra_value = extra.get( 'value', None )
|
||||
assert extra_value is not None, 'extra_files requires a value attribute'
|
||||
extra_attributes = {}
|
||||
extra_attributes['compare'] = extra.get( 'compare', 'diff' ).lower()
|
||||
extra_attributes['delta'] = extra.get( 'delta', '0' )
|
||||
extra_attributes['lines_diff'] = int( extra.get( 'lines_diff', '0' ) )
|
||||
extra_attributes['sort'] = string_as_bool( extra.get( 'sort', False ) )
|
||||
extra_value, extra_attributes = __parse_test_attributes(extra, attrib)
|
||||
return extra_type, extra_value, extra_name, extra_attributes
|
||||
|
||||
|
||||
|
||||
@@ -33,6 +33,12 @@ class YamlToolSource(ToolSource):
|
||||
def parse_description(self):
|
||||
return self.root_dict.get("description", "")
|
||||
|
||||
def parse_edam_operations(self):
|
||||
return self.root_dict.get("edam_operations", [])
|
||||
|
||||
def parse_edam_topics(self):
|
||||
return self.root_dict.get("edam_topics", [])
|
||||
|
||||
def parse_is_multi_byte(self):
|
||||
return self.root_dict.get("is_multi_byte", self.default_is_multi_byte)
|
||||
|
||||
|
||||
@@ -23,19 +23,23 @@ def get_observer_class(config_value, default, monitor_what_str):
|
||||
config_value = config_value or default
|
||||
config_value = str(config_value).lower()
|
||||
if config_value in ("true", "yes", "on", "auto"):
|
||||
expect_observer = config_value != "auto"
|
||||
expect_observer = True
|
||||
observer_class = Observer
|
||||
elif config_value == "polling":
|
||||
expect_observer = True
|
||||
observer_class = PollingObserver
|
||||
else:
|
||||
elif config_value in ('false', 'no', 'off'):
|
||||
expect_observer = False
|
||||
observer_class = None
|
||||
else:
|
||||
message = "Unrecognized value for watch_tools config option: %s" % config_value
|
||||
raise Exception(message)
|
||||
|
||||
if observer_class is None:
|
||||
message = "Watchdog library unavailble, cannot monitor %s." % monitor_what_str
|
||||
log.info(message)
|
||||
if expect_observer:
|
||||
if expect_observer and observer_class is None:
|
||||
message = "Watchdog library unavailable, cannot monitor %s." % monitor_what_str
|
||||
if config_value == "auto":
|
||||
log.info(message)
|
||||
else:
|
||||
raise Exception(message)
|
||||
|
||||
return observer_class
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
"""Module of utilities for verifying test results."""
|
||||
|
||||
import difflib
|
||||
import filecmp
|
||||
import hashlib
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
from .asserts import verify_assertions
|
||||
from .test_data import TestDataResolver
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_TEST_DATA_RESOLVER = TestDataResolver()
|
||||
|
||||
|
||||
def verify(
|
||||
item_label,
|
||||
output_content,
|
||||
attributes,
|
||||
filename=None,
|
||||
get_filename=None,
|
||||
keep_outputs_dir=None,
|
||||
verify_extra_files=None,
|
||||
):
|
||||
"""Verify the content of a test output using test definitions described by attributes.
|
||||
|
||||
Throw an informative assertion error if any of these tests fail.
|
||||
"""
|
||||
if get_filename is None:
|
||||
get_filename = DEFAULT_TEST_DATA_RESOLVER.get_filename
|
||||
|
||||
# Check assertions...
|
||||
assertions = attributes.get("assert_list", None)
|
||||
if attributes is not None and assertions is not None:
|
||||
try:
|
||||
verify_assertions(output_content, attributes["assert_list"])
|
||||
except AssertionError as err:
|
||||
errmsg = '%s different than expected\n' % (item_label)
|
||||
errmsg += str( err )
|
||||
raise AssertionError( errmsg )
|
||||
|
||||
# Verify checksum attributes...
|
||||
# works with older Galaxy style md5=<expected_sum> or cwltest
|
||||
# style checksum=<hash_type>$<hash>.
|
||||
expected_checksum_type = None
|
||||
expected_checksum = None
|
||||
if attributes is not None and attributes.get("md5", None) is not None:
|
||||
expected_checksum_type = "md5"
|
||||
expected_checksum = attributes.get("md5")
|
||||
elif attributes is not None and attributes.get("checksum", None) is not None:
|
||||
checksum_value = attributes.get("checksum", None)
|
||||
expected_checksum_type, expected_checksum = checksum_value.split("$", 1)
|
||||
|
||||
if expected_checksum_type:
|
||||
try:
|
||||
_verify_checksum(output_content, expected_checksum_type, expected_checksum)
|
||||
except AssertionError as err:
|
||||
errmsg = '%s different than expected\n' % (item_label)
|
||||
errmsg += str( err )
|
||||
raise AssertionError( errmsg )
|
||||
|
||||
if filename is not None:
|
||||
local_name = get_filename(filename)
|
||||
temp_name = make_temp_fname(fname=filename)
|
||||
with open(temp_name, 'wb') as f:
|
||||
f.write(output_content)
|
||||
|
||||
# if the server's env has GALAXY_TEST_SAVE, save the output file to that dir
|
||||
if keep_outputs_dir:
|
||||
ofn = os.path.join(keep_outputs_dir, os.path.basename(local_name))
|
||||
log.debug('keep_outputs_dir: %s, ofn: %s', keep_outputs_dir, ofn)
|
||||
try:
|
||||
shutil.copy( temp_name, ofn )
|
||||
except Exception as exc:
|
||||
error_log_msg = 'Could not save output file %s to %s: ' % (temp_name, ofn)
|
||||
error_log_msg += str(exc)
|
||||
log.error(error_log_msg, exc_info=True)
|
||||
else:
|
||||
log.debug('## GALAXY_TEST_SAVE=%s. saved %s' % (keep_outputs_dir, ofn))
|
||||
try:
|
||||
if attributes is None:
|
||||
attributes = {}
|
||||
compare = attributes.get('compare', 'diff')
|
||||
if attributes.get('ftype', None) == 'bam':
|
||||
local_fh, temp_name = _bam_to_sam(local_name, temp_name)
|
||||
local_name = local_fh.name
|
||||
if compare == 'diff':
|
||||
files_diff(local_name, temp_name, attributes=attributes)
|
||||
elif compare == 're_match':
|
||||
files_re_match( local_name, temp_name, attributes=attributes )
|
||||
elif compare == 're_match_multiline':
|
||||
files_re_match_multiline( local_name, temp_name, attributes=attributes )
|
||||
elif compare == 'sim_size':
|
||||
delta = attributes.get('delta', '100')
|
||||
s1 = len(output_content)
|
||||
s2 = os.path.getsize(local_name)
|
||||
if abs(s1 - s2) > int(delta):
|
||||
raise AssertionError( 'Files %s=%db but %s=%db - compare by size (delta=%s) failed' % (temp_name, s1, local_name, s2, delta) )
|
||||
elif compare == "contains":
|
||||
files_contains( local_name, temp_name, attributes=attributes )
|
||||
else:
|
||||
raise Exception( 'Unimplemented Compare type: %s' % compare )
|
||||
if verify_extra_files:
|
||||
extra_files = attributes.get('extra_files', None)
|
||||
if extra_files:
|
||||
verify_extra_files(extra_files)
|
||||
except AssertionError as err:
|
||||
errmsg = '%s different than expected, difference (using %s):\n' % ( item_label, compare )
|
||||
errmsg += "( %s v. %s )\n" % ( local_name, temp_name )
|
||||
errmsg += str( err )
|
||||
raise AssertionError( errmsg )
|
||||
finally:
|
||||
if 'GALAXY_TEST_NO_CLEANUP' not in os.environ:
|
||||
os.remove( temp_name )
|
||||
|
||||
|
||||
def make_temp_fname(fname=None):
|
||||
"""Safe temp name - preserve the file extension for tools that interpret it."""
|
||||
suffix = os.path.split(fname)[-1] # ignore full path
|
||||
fd, temp_prefix = tempfile.mkstemp(prefix='tmp', suffix=suffix)
|
||||
return temp_prefix
|
||||
|
||||
|
||||
def _bam_to_sam(local_name, temp_name):
|
||||
temp_local = tempfile.NamedTemporaryFile( suffix='.sam', prefix='local_bam_converted_to_sam_' )
|
||||
fd, temp_temp = tempfile.mkstemp( suffix='.sam', prefix='history_bam_converted_to_sam_' )
|
||||
os.close( fd )
|
||||
command = 'samtools view -h -o "%s" "%s"' % ( temp_local.name, local_name )
|
||||
check_command( command, 'Converting local (test-data) bam to sam' )
|
||||
command = 'samtools view -h -o "%s" "%s"' % ( temp_temp, temp_name )
|
||||
check_command( command, 'Converting history bam to sam ' )
|
||||
os.remove( temp_name )
|
||||
return temp_local, temp_temp
|
||||
|
||||
|
||||
def _verify_checksum(data, checksum_type, expected_checksum_value):
|
||||
if checksum_type not in ["md5", "sha1", "sha256", "sha512"]:
|
||||
raise Exception("Unimplemented hash algorithm [%s] encountered." % checksum_type)
|
||||
|
||||
h = hashlib.new(checksum_type)
|
||||
h.update( data )
|
||||
actual_checksum_value = h.hexdigest()
|
||||
if expected_checksum_value != actual_checksum_value:
|
||||
template = "Output checksum [%s] does not match expected [%s] (using hash algorithm %s)."
|
||||
message = template % (actual_checksum_value, expected_checksum_value, checksum_type)
|
||||
raise AssertionError(message)
|
||||
|
||||
|
||||
def check_command(command, description):
|
||||
"""Verify a command runs with an exit code of 0."""
|
||||
# TODO: also collect ``which samtools`` and ``samtools --version``
|
||||
p = subprocess.Popen( args=command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True )
|
||||
(stdout, stderr) = p.communicate()
|
||||
if p.returncode:
|
||||
template = description
|
||||
template += " failed: (cmd=[%s], stdout=[%s], stderr=[%s])"
|
||||
message = template % (command, stdout, stderr)
|
||||
raise AssertionError(message)
|
||||
|
||||
|
||||
def files_diff(file1, file2, attributes=None):
|
||||
"""Check the contents of 2 files for differences."""
|
||||
def get_lines_diff( diff ):
|
||||
count = 0
|
||||
for line in diff:
|
||||
if ( line.startswith( '+' ) and not line.startswith( '+++' ) ) or ( line.startswith( '-' ) and not line.startswith( '---' ) ):
|
||||
count += 1
|
||||
return count
|
||||
if not filecmp.cmp( file1, file2 ):
|
||||
files_differ = False
|
||||
local_file = open( file1, 'U' ).readlines()
|
||||
history_data = open( file2, 'U' ).readlines()
|
||||
if attributes is None:
|
||||
attributes = {}
|
||||
if attributes.get( 'sort', False ):
|
||||
history_data.sort()
|
||||
# Why even bother with the check loop below, why not just use the diff output? This seems wasteful.
|
||||
if len( local_file ) == len( history_data ):
|
||||
for i in range( len( history_data ) ):
|
||||
if local_file[i].rstrip( '\r\n' ) != history_data[i].rstrip( '\r\n' ):
|
||||
files_differ = True
|
||||
break
|
||||
else:
|
||||
files_differ = True
|
||||
if files_differ:
|
||||
allowed_diff_count = int(attributes.get( 'lines_diff', 0 ))
|
||||
diff = list( difflib.unified_diff( local_file, history_data, "local_file", "history_data" ) )
|
||||
diff_lines = get_lines_diff( diff )
|
||||
if diff_lines > allowed_diff_count:
|
||||
if 'GALAXY_TEST_RAW_DIFF' in os.environ:
|
||||
diff_slice = diff
|
||||
else:
|
||||
if len(diff) < 60:
|
||||
diff_slice = diff[0:40]
|
||||
else:
|
||||
diff_slice = diff[:25] + ["********\n", "*SNIP *\n", "********\n"] + diff[-25:]
|
||||
# FIXME: This pdf stuff is rather special cased and has not been updated to consider lines_diff
|
||||
# due to unknown desired behavior when used in conjunction with a non-zero lines_diff
|
||||
# PDF forgiveness can probably be handled better by not special casing by __extension__ here
|
||||
# and instead using lines_diff or a regular expression matching
|
||||
# or by creating and using a specialized pdf comparison function
|
||||
if file1.endswith( '.pdf' ) or file2.endswith( '.pdf' ):
|
||||
# PDF files contain creation dates, modification dates, ids and descriptions that change with each
|
||||
# new file, so we need to handle these differences. As long as the rest of the PDF file does
|
||||
# not differ we're ok.
|
||||
valid_diff_strs = [ 'description', 'createdate', 'creationdate', 'moddate', 'id', 'producer', 'creator' ]
|
||||
valid_diff = False
|
||||
invalid_diff_lines = 0
|
||||
for line in diff_slice:
|
||||
# Make sure to lower case strings before checking.
|
||||
line = line.lower()
|
||||
# Diff lines will always start with a + or - character, but handle special cases: '--- local_file \n', '+++ history_data \n'
|
||||
if ( line.startswith( '+' ) or line.startswith( '-' ) ) and line.find( 'local_file' ) < 0 and line.find( 'history_data' ) < 0:
|
||||
for vdf in valid_diff_strs:
|
||||
if line.find( vdf ) < 0:
|
||||
valid_diff = False
|
||||
else:
|
||||
valid_diff = True
|
||||
# Stop checking as soon as we know we have a valid difference
|
||||
break
|
||||
if not valid_diff:
|
||||
invalid_diff_lines += 1
|
||||
log.info('## files diff on %s and %s lines_diff=%d, found diff = %d, found pdf invalid diff = %d' % (file1, file2, allowed_diff_count, diff_lines, invalid_diff_lines))
|
||||
if invalid_diff_lines > allowed_diff_count:
|
||||
# Print out diff_slice so we can see what failed
|
||||
log.info("###### diff_slice ######")
|
||||
raise AssertionError( "".join( diff_slice ) )
|
||||
else:
|
||||
log.info('## files diff on %s and %s lines_diff=%d, found diff = %d' % (file1, file2, allowed_diff_count, diff_lines))
|
||||
for line in diff_slice:
|
||||
for char in line:
|
||||
if ord( char ) > 128:
|
||||
raise AssertionError( "Binary data detected, not displaying diff" )
|
||||
raise AssertionError( "".join( diff_slice ) )
|
||||
|
||||
|
||||
def files_re_match(file1, file2, attributes=None):
|
||||
"""Check the contents of 2 files for differences using re.match."""
|
||||
local_file = open( file1, 'U' ).readlines() # regex file
|
||||
history_data = open( file2, 'U' ).readlines()
|
||||
assert len( local_file ) == len( history_data ), 'Data File and Regular Expression File contain a different number of lines (%s != %s)\nHistory Data (first 40 lines):\n%s' % ( len( local_file ), len( history_data ), ''.join( history_data[:40] ) )
|
||||
if attributes is None:
|
||||
attributes = {}
|
||||
if attributes.get( 'sort', False ):
|
||||
history_data.sort()
|
||||
lines_diff = int(attributes.get( 'lines_diff', 0 ))
|
||||
line_diff_count = 0
|
||||
diffs = []
|
||||
for i in range( len( history_data ) ):
|
||||
if not re.match( local_file[i].rstrip( '\r\n' ), history_data[i].rstrip( '\r\n' ) ):
|
||||
line_diff_count += 1
|
||||
diffs.append( 'Regular Expression: %s\nData file : %s' % ( local_file[i].rstrip( '\r\n' ), history_data[i].rstrip( '\r\n' ) ) )
|
||||
if line_diff_count > lines_diff:
|
||||
raise AssertionError( "Regular expression did not match data file (allowed variants=%i):\n%s" % ( lines_diff, "".join( diffs ) ) )
|
||||
|
||||
|
||||
def files_re_match_multiline(file1, file2, attributes=None):
|
||||
"""Check the contents of 2 files for differences using re.match in multiline mode."""
|
||||
local_file = open( file1, 'U' ).read() # regex file
|
||||
if attributes is None:
|
||||
attributes = {}
|
||||
if attributes.get( 'sort', False ):
|
||||
history_data = open( file2, 'U' ).readlines()
|
||||
history_data.sort()
|
||||
history_data = ''.join( history_data )
|
||||
else:
|
||||
history_data = open( file2, 'U' ).read()
|
||||
# lines_diff not applicable to multiline matching
|
||||
assert re.match( local_file, history_data, re.MULTILINE ), "Multiline Regular expression did not match data file"
|
||||
|
||||
|
||||
def files_contains(file1, file2, attributes=None):
|
||||
"""Check the contents of file2 for substrings found in file1, on a per-line basis."""
|
||||
local_file = open( file1, 'U' ).readlines() # regex file
|
||||
# TODO: allow forcing ordering of contains
|
||||
history_data = open( file2, 'U' ).read()
|
||||
lines_diff = int( attributes.get( 'lines_diff', 0 ) )
|
||||
line_diff_count = 0
|
||||
while local_file:
|
||||
contains = local_file.pop( 0 ).rstrip( '\n\r' )
|
||||
if contains not in history_data:
|
||||
line_diff_count += 1
|
||||
if line_diff_count > lines_diff:
|
||||
raise AssertionError( "Failed to find '%s' in history data. (lines_diff=%i):\n" % ( contains, lines_diff ) )
|
||||
@@ -12,7 +12,7 @@ assertion_module_names = ['text', 'tabular', 'xml']
|
||||
# <MODULE_NAME> to the list of assertion module names defined above.
|
||||
assertion_modules = []
|
||||
for assertion_module_name in assertion_module_names:
|
||||
full_assertion_module_name = 'base.asserts.' + assertion_module_name
|
||||
full_assertion_module_name = 'galaxy.tools.verify.asserts.' + assertion_module_name
|
||||
log.debug(full_assertion_module_name)
|
||||
try:
|
||||
# Dynamically import module
|
||||
@@ -729,7 +729,7 @@ def rst_to_html( s ):
|
||||
class FakeStream( object ):
|
||||
def write( self, str ):
|
||||
if len( str ) > 0 and not str.isspace():
|
||||
log.warn( str )
|
||||
log.warning( str )
|
||||
|
||||
settings_overrides = {
|
||||
"embed_stylesheet": False,
|
||||
@@ -1351,7 +1351,7 @@ def config_directories_from_setting( directories_setting, galaxy_root=galaxy_roo
|
||||
if not directory.startswith( '/' ):
|
||||
directory = os.path.join( galaxy_root, directory )
|
||||
if not os.path.exists( directory ):
|
||||
log.warn( 'directory not found: %s', directory )
|
||||
log.warning( 'directory not found: %s', directory )
|
||||
continue
|
||||
directories.append( directory )
|
||||
return directories
|
||||
|
||||
@@ -140,3 +140,15 @@ def is_bz2( file_path ):
|
||||
def is_gzip( file_path ):
|
||||
is_gzipped, is_valid = check_gzip( file_path )
|
||||
return is_gzipped
|
||||
|
||||
|
||||
__all__ = [
|
||||
'check_binary',
|
||||
'check_bz2',
|
||||
'check_gzip',
|
||||
'check_html',
|
||||
'check_image',
|
||||
'check_zip',
|
||||
'is_gzip',
|
||||
'is_bz2',
|
||||
]
|
||||
|
||||
@@ -1483,7 +1483,7 @@ class ENCODEPeakDataProvider( GenomeDataProvider ):
|
||||
"""
|
||||
|
||||
def get_iterator( self, data_file, chrom, start, end, **kwargs ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def process_data( self, iterator, start_val=0, max_vals=None, **kwargs ):
|
||||
"""
|
||||
|
||||
@@ -283,7 +283,7 @@ class DataSourceParser( object ):
|
||||
test_type = test_elem.get( 'type', 'eq' )
|
||||
test_result = test_elem.text.strip() if test_elem.text else None
|
||||
if not test_type or not test_result:
|
||||
log.warn( 'Skipping test. Needs both type attribute and text node to be parsed: ' +
|
||||
log.warning( 'Skipping test. Needs both type attribute and text node to be parsed: ' +
|
||||
'%s, %s' % ( test_type, test_elem.text ) )
|
||||
continue
|
||||
test_result = test_result.strip()
|
||||
|
||||
@@ -203,7 +203,7 @@ class VisualizationsRegistry( pluginframework.PageServingPluginManager ):
|
||||
if not test_result:
|
||||
# but continue (with other tests) if can't find class by that name
|
||||
# if self.debug:
|
||||
# log.warn( 'visualizations_registry cannot find class (%s)' +
|
||||
# log.warning( 'visualizations_registry cannot find class (%s)' +
|
||||
# ' for applicability test on: %s, id: %s', datatype_class_name,
|
||||
# target_object, getattr( target_object, 'id', '' ) )
|
||||
continue
|
||||
|
||||
@@ -78,7 +78,7 @@ class ResourceParser( object ):
|
||||
if trans.debug:
|
||||
raise
|
||||
else:
|
||||
log.warn( 'Exception parsing visualization param from query: %s, %s, (%s) %s',
|
||||
log.warning( 'Exception parsing visualization param from query: %s, %s, (%s) %s',
|
||||
param_name, query_val, str( type( exception ) ), str( exception ) )
|
||||
resource = None
|
||||
|
||||
@@ -109,7 +109,7 @@ class ResourceParser( object ):
|
||||
config_val = self.parse_parameter( trans, param_config, config_val )
|
||||
|
||||
except Exception as exception:
|
||||
log.warn( 'Exception parsing visualization param from query: ' +
|
||||
log.warning( 'Exception parsing visualization param from query: ' +
|
||||
'%s, %s, (%s) %s' % ( param_name, config_val, str( type( exception ) ), str( exception ) ))
|
||||
config_val = None
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ class BaseController( object ):
|
||||
# this should be here - but catching errors from sharable item controllers that *should* have SharableItemMixin
|
||||
# but *don't* then becomes difficult
|
||||
# def security_check( self, trans, item, check_ownership=False, check_accessible=False ):
|
||||
# log.warn( 'BaseController.security_check: %s, %b, %b', str( item ), check_ownership, check_accessible )
|
||||
# log.warning( 'BaseController.security_check: %s, %b, %b', str( item ), check_ownership, check_accessible )
|
||||
# # meant to be overridden in SharableSecurityMixin
|
||||
# return item
|
||||
|
||||
|
||||
@@ -304,8 +304,8 @@ class InteractiveEnvironmentRequest(object):
|
||||
log.debug( "Container id: %s" % container_id)
|
||||
inspect_data = self.inspect_container(container_id)
|
||||
port_mappings = self.get_container_port_mapping(inspect_data)
|
||||
if self.attr.docker_hostname == 'localhost':
|
||||
self.attr.docker_hostname = self.get_container_gateway_ip(inspect_data)
|
||||
self.attr.docker_hostname = self.get_container_host(inspect_data)
|
||||
log.debug( "Container host: %s", self.attr.docker_hostname )
|
||||
if len(port_mappings) > 1:
|
||||
log.warning("Don't know how to handle proxies to containers with multiple exposed ports. Arbitrarily choosing first")
|
||||
elif len(port_mappings) == 0:
|
||||
@@ -368,15 +368,25 @@ class InteractiveEnvironmentRequest(object):
|
||||
# ]
|
||||
return inspect_data
|
||||
|
||||
def get_container_gateway_ip(self, inspect_data):
|
||||
def get_container_host(self, inspect_data):
|
||||
"""
|
||||
Returns gateway ip from inspect_data
|
||||
Determine the ip address on the container. If inspect_data contains
|
||||
Node.IP return that (e.g. running in Docker Swarm). If the hostname
|
||||
is "localhost", look for NetworkSettings.Gateway. Otherwise, just
|
||||
return the configured docker_hostname.
|
||||
|
||||
:type inspect_data: dict
|
||||
:param inspect_data: output of docker inspect
|
||||
:returns: gateway_ip
|
||||
:returns: IP address or hostname of the node the conatainer is
|
||||
running on.
|
||||
"""
|
||||
gateway_ip = inspect_data[0]['NetworkSettings']['Gateway']
|
||||
return gateway_ip
|
||||
inspect_data = inspect_data[0]
|
||||
if 'Node' in inspect_data:
|
||||
return inspect_data['Node']['IP']
|
||||
elif self.attr.docker_hostname == "localhost":
|
||||
return inspect_data['NetworkSettings']['Gateway']
|
||||
else:
|
||||
return self.attr.docker_hostname
|
||||
|
||||
def get_container_port_mapping(self, inspect_data):
|
||||
"""
|
||||
|
||||
@@ -93,7 +93,7 @@ class PluginManager( object ):
|
||||
# NOTE: prevent silent, implicit overwrite here (two plugins in two diff directories)
|
||||
# TODO: overwriting may be desired
|
||||
elif plugin and plugin.name in self.plugins:
|
||||
log.warn( '%s, plugin with name already exists: %s. Skipping...', self, plugin.name )
|
||||
log.warning( '%s, plugin with name already exists: %s. Skipping...', self, plugin.name )
|
||||
|
||||
except Exception:
|
||||
if not self.skip_bad_plugins:
|
||||
|
||||
@@ -123,6 +123,10 @@ class DatatypesController( BaseAPIController ):
|
||||
def edam_formats( self, trans, **kwds ):
|
||||
return self._datatypes_registry.edam_formats
|
||||
|
||||
@expose_api_anonymous_and_sessionless
|
||||
def edam_data( self, trans, **kwds ):
|
||||
return self._datatypes_registry.edam_data
|
||||
|
||||
@property
|
||||
def _datatypes_registry( self ):
|
||||
return self.app.datatypes_registry
|
||||
|
||||
@@ -334,7 +334,7 @@ class WorkflowsAPIController(BaseAPIController, UsesStoredWorkflowMixin, UsesAnn
|
||||
} )
|
||||
|
||||
# create tool model and default tool state (if missing)
|
||||
tool_model = module.tool.to_json( trans, tool_inputs, workflow_mode=True )
|
||||
tool_model = module.tool.to_json( trans, tool_inputs, workflow_building_mode=True )
|
||||
module.update_state( tool_model[ 'state_inputs' ] )
|
||||
return {
|
||||
'tool_model' : tool_model,
|
||||
|
||||
@@ -299,7 +299,7 @@ def populate_api_routes( webapp, app ):
|
||||
webapp.mapper.resource( 'datatype',
|
||||
'datatypes',
|
||||
path_prefix='/api',
|
||||
collection={ 'sniffers': 'GET', 'mapping': 'GET', 'converters': 'GET', 'edam_formats': 'GET' },
|
||||
collection={ 'sniffers': 'GET', 'mapping': 'GET', 'converters': 'GET', 'edam_data': 'GET', 'edam_formats': 'GET' },
|
||||
parent_resources=dict( member_name='datatype', collection_name='datatypes' ) )
|
||||
webapp.mapper.resource( 'search', 'search', path_prefix='/api' )
|
||||
webapp.mapper.resource( 'page', 'pages', path_prefix="/api")
|
||||
|
||||
@@ -473,7 +473,7 @@ class DatasetInterface( BaseUIController, UsesAnnotations, UsesItemRatings, Uses
|
||||
assert trans.user.id == hda.history.user_id, "HistoryDatasetAssocation does not belong to current user"
|
||||
hdas.append( hda )
|
||||
else:
|
||||
log.warn( "Invalid history_dataset_association id '%r' passed to list", hda_id )
|
||||
log.warning( "Invalid history_dataset_association id '%r' passed to list", hda_id )
|
||||
|
||||
if hdas:
|
||||
if operation == "switch" or operation == "switch_history":
|
||||
|
||||
@@ -24,4 +24,4 @@ class ExternalServiceController( BaseUIController ):
|
||||
results = populated_action.handle_results( trans )
|
||||
return results
|
||||
else:
|
||||
raise 'unknown item class type'
|
||||
raise Exception( 'unknown item class type' )
|
||||
|
||||
@@ -283,7 +283,7 @@ class HistoryController( BaseUIController, SharableMixin, UsesAnnotations, UsesI
|
||||
assert trans.user.id == history.user_id, "History does not belong to current user"
|
||||
histories.append( history )
|
||||
else:
|
||||
log.warn( "Invalid history id '%r' passed to list", history_id )
|
||||
log.warning( "Invalid history id '%r' passed to list", history_id )
|
||||
if histories:
|
||||
if operation == "switch":
|
||||
status, message = self._list_switch( trans, histories )
|
||||
|
||||
@@ -22,10 +22,10 @@ class RBACAgent:
|
||||
permitted_actions = Bunch()
|
||||
|
||||
def associate_components( self, **kwd ):
|
||||
raise 'No valid method of associating provided components: %s' % kwd
|
||||
raise Exception( 'No valid method of associating provided components: %s' % kwd )
|
||||
|
||||
def associate_user_role( self, user, role ):
|
||||
raise 'No valid method of associating a user with a role'
|
||||
raise Exception( 'No valid method of associating a user with a role' )
|
||||
|
||||
def convert_permitted_action_strings( self, permitted_action_strings ):
|
||||
"""
|
||||
@@ -35,7 +35,7 @@ class RBACAgent:
|
||||
return filter( lambda x: x is not None, [ self.permitted_actions.get( action_string ) for action_string in permitted_action_strings ] )
|
||||
|
||||
def create_private_user_role( self, user ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
def get_action( self, name, default=None ):
|
||||
"""Get a permitted action by its dict key or action name"""
|
||||
@@ -49,10 +49,10 @@ class RBACAgent:
|
||||
return self.permitted_actions.__dict__.values()
|
||||
|
||||
def get_item_actions( self, action, item ):
|
||||
raise 'No valid method of retrieving action (%s) for item %s.' % ( action, item )
|
||||
raise Exception( 'No valid method of retrieving action (%s) for item %s.' % ( action, item ) )
|
||||
|
||||
def get_private_user_role( self, user ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
|
||||
class CommunityRBACAgent( RBACAgent ):
|
||||
@@ -93,7 +93,7 @@ class CommunityRBACAgent( RBACAgent ):
|
||||
return self.associate_group_role( kwd['group'], kwd['role'] )
|
||||
elif 'repository' in kwd:
|
||||
return self.associate_repository_category( kwd[ 'repository' ], kwd[ 'category' ] )
|
||||
raise 'No valid method of associating provided components: %s' % kwd
|
||||
raise Exception( 'No valid method of associating provided components: %s' % kwd )
|
||||
|
||||
def associate_group_role( self, group, role ):
|
||||
assoc = self.model.GroupRoleAssociation( group, role )
|
||||
|
||||
@@ -97,7 +97,7 @@ def extract_steps( trans, history=None, job_ids=None, dataset_ids=None, dataset_
|
||||
# Tool steps
|
||||
for job_id in job_ids:
|
||||
if job_id not in jobs_by_id:
|
||||
log.warn( "job_id %s not found in jobs_by_id %s" % ( job_id, jobs_by_id ) )
|
||||
log.warning( "job_id %s not found in jobs_by_id %s" % ( job_id, jobs_by_id ) )
|
||||
raise AssertionError( "Attempt to create workflow with job not connected to current history" )
|
||||
job = jobs_by_id[ job_id ]
|
||||
tool_inputs, associations = step_inputs( trans, job )
|
||||
@@ -141,7 +141,7 @@ def extract_steps( trans, history=None, job_ids=None, dataset_ids=None, dataset_
|
||||
if hid is None:
|
||||
template = "Failed to find matching implicit job - job is %s, jobs are %s, assoc_name is %s."
|
||||
message = template % ( job.id, jobs, assoc.name )
|
||||
log.warn( message )
|
||||
log.warning( message )
|
||||
raise Exception( "Failed to extract job." )
|
||||
else:
|
||||
if hasattr( assoc, "dataset" ):
|
||||
@@ -241,7 +241,7 @@ class WorkflowSummary( object ):
|
||||
|
||||
job_hda = self.__original_hda( dataset_instance )
|
||||
if not job_hda.creating_job_associations:
|
||||
log.warn( "An implicitly create output dataset collection doesn't have a creating_job_association, should not happen!" )
|
||||
log.warning( "An implicitly create output dataset collection doesn't have a creating_job_association, should not happen!" )
|
||||
job = DatasetCollectionCreationJob( dataset_collection )
|
||||
self.jobs[ job ] = [ ( None, dataset_collection ) ]
|
||||
|
||||
|
||||
@@ -465,7 +465,7 @@ class InstallRepositoryManager( object ):
|
||||
message = "Error attempting to retrieve installation information from tool shed "
|
||||
message += "%s for revision %s of repository %s owned by %s: %s" % \
|
||||
( str( tool_shed_url ), str( changeset_revision ), str( name ), str( owner ), str( e ) )
|
||||
log.warn( message )
|
||||
log.warning( message )
|
||||
raise exceptions.InternalServerError( message )
|
||||
if raw_text:
|
||||
# If successful, the response from get_repository_revision_install_info will be 3
|
||||
@@ -478,7 +478,7 @@ class InstallRepositoryManager( object ):
|
||||
else:
|
||||
message = "Unable to retrieve installation information from tool shed %s for revision %s of repository %s owned by %s: %s" % \
|
||||
( str( tool_shed_url ), str( changeset_revision ), str( name ), str( owner ), str( e ) )
|
||||
log.warn( message )
|
||||
log.warning( message )
|
||||
raise exceptions.InternalServerError( message )
|
||||
# Make sure the tool shed returned everything we need for installing the repository.
|
||||
if not repository_revision_dict or not repo_info_dict:
|
||||
|
||||
@@ -119,10 +119,10 @@ class InstallEnvironment( object ):
|
||||
stdout = output.stdout
|
||||
stderr = output.stderr
|
||||
if len( stdout ) > DATABASE_MAX_STRING_SIZE:
|
||||
log.warn( "Length of stdout > %s, so only a portion will be saved in the database." % str( DATABASE_MAX_STRING_SIZE_PRETTY ) )
|
||||
log.warning( "Length of stdout > %s, so only a portion will be saved in the database." % str( DATABASE_MAX_STRING_SIZE_PRETTY ) )
|
||||
stdout = shrink_string_by_size( stdout, DATABASE_MAX_STRING_SIZE, join_by="\n..\n", left_larger=True, beginning_on_size_error=True )
|
||||
if len( stderr ) > DATABASE_MAX_STRING_SIZE:
|
||||
log.warn( "Length of stderr > %s, so only a portion will be saved in the database." % str( DATABASE_MAX_STRING_SIZE_PRETTY ) )
|
||||
log.warning( "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 ]:
|
||||
status = self.app.install_model.ToolDependency.installation_status.ERROR
|
||||
|
||||
@@ -82,7 +82,7 @@ class CompressedFile( object ):
|
||||
if os.path.exists( absolute_filepath ):
|
||||
os.chmod( absolute_filepath, unix_permissions )
|
||||
else:
|
||||
log.warn("Unable to change permission on extracted file '%s' as it does not exist" % absolute_filepath)
|
||||
log.warning("Unable to change permission on extracted file '%s' as it does not exist" % absolute_filepath)
|
||||
return os.path.abspath( os.path.join( extraction_path, common_prefix ) )
|
||||
|
||||
def getmembers_tar( self ):
|
||||
@@ -239,10 +239,10 @@ class RecipeStep( object ):
|
||||
|
||||
def execute_step( self, tool_dependency, package_name, actions, action_dict, filtered_actions, env_file_builder,
|
||||
install_environment, work_dir, current_dir=None, initial_download=False ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method")
|
||||
|
||||
def prepare_step( self, tool_dependency, action_elem, action_dict, install_environment, is_binary_download ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
|
||||
class AssertDirectoryExecutable( RecipeStep ):
|
||||
|
||||
@@ -22,7 +22,7 @@ class RecipeTag( object ):
|
||||
|
||||
def process_tag_set( self, tool_shed_repository, tool_dependency, package_elem, package_name, package_version,
|
||||
from_tool_migration_manager=False, tool_dependency_db_records=None ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
|
||||
class SyncDatabase( object ):
|
||||
|
||||
@@ -16,7 +16,7 @@ class Metadata( object ):
|
||||
return repo.changelog
|
||||
|
||||
def is_valid_for_type( self, app, repository, revisions_to_check=None ):
|
||||
raise "Unimplemented Method"
|
||||
raise Exception( "Unimplemented Method" )
|
||||
|
||||
|
||||
class TipOnly( Metadata ):
|
||||
|
||||
@@ -161,7 +161,7 @@ def get_repository_dependencies( app, tool_shed_url, repository_name, repository
|
||||
tool_shed_accessible = True
|
||||
except Exception as e:
|
||||
tool_shed_accessible = False
|
||||
log.warn( "The URL\n%s\nraised the exception:\n%s\n", util.build_url( tool_shed_url, pathspec=pathspec, params=params ), e )
|
||||
log.warning( "The URL\n%s\nraised the exception:\n%s\n", util.build_url( tool_shed_url, pathspec=pathspec, params=params ), e )
|
||||
if tool_shed_accessible:
|
||||
if len( raw_text ) > 2:
|
||||
encoded_text = json.loads( raw_text )
|
||||
@@ -193,7 +193,7 @@ def get_tool_dependencies( app, tool_shed_url, repository_name, repository_owner
|
||||
tool_shed_accessible = True
|
||||
except Exception as e:
|
||||
tool_shed_accessible = False
|
||||
log.warn( "The URL\n%s\nraised the exception:\n%s\n", util.build_url( tool_shed_url, pathspec=pathspec, params=params ), e )
|
||||
log.warning( "The URL\n%s\nraised the exception:\n%s\n", util.build_url( tool_shed_url, pathspec=pathspec, params=params ), e )
|
||||
if tool_shed_accessible:
|
||||
if text:
|
||||
tool_dependencies_dict = encoding_util.tool_shed_decode( text )
|
||||
|
||||
@@ -366,7 +366,7 @@ def remove_tool_dependency_installation_directory( dependency_install_dir ):
|
||||
except Exception as e:
|
||||
removed = False
|
||||
error_message = "Error removing tool dependency installation directory %s: %s" % ( str( dependency_install_dir ), str( e ) )
|
||||
log.warn( error_message )
|
||||
log.warning( error_message )
|
||||
else:
|
||||
removed = True
|
||||
error_message = ''
|
||||
|
||||
@@ -176,8 +176,9 @@ RELEASE_ISSUE_TEMPLATE = string.Template("""
|
||||
|
||||
- [ ] **Deploy and Test Release**
|
||||
|
||||
- [ ] Deploy to test (${freeze_date} + 1 day).
|
||||
- [ ] Update test to ensure it is running a dev at or past branch point (${freeze_date} + 1 day).
|
||||
- [ ] Deploy to usegalaxy.org (${freeze_date} + 1 week).
|
||||
- [ ] [Update bioblend testing](https://github.com/galaxyproject/bioblend/commit/b74b1c302a1b8fed86786b40d7ecc3520cbadcd3) to include a ``release_${version}`` target - add ``env`` target ``- TOX_ENV=py27 GALAXY_VERSION=release_${version}`` to ``tox.ini``.
|
||||
|
||||
- [ ] **Create Release Notes**
|
||||
|
||||
@@ -226,19 +227,20 @@ RELEASE_ISSUE_TEMPLATE = string.Template("""
|
||||
|
||||
- [ ] **Announce Release**
|
||||
|
||||
- [ ] Verify release included in https://docs.galaxyproject.org/en/master/releases/index.html
|
||||
- [ ] Review announcement in https://github.com/galaxyproject/galaxy/blob/dev/doc/source/releases/${version}_announce.rst
|
||||
- [ ] Stage annoucement content (Wiki, Biostars, Bit.ly link) on annouce date to capture date tags. Note: all final content does not need to be completed to do this.
|
||||
- [ ] Finalize https://github.com/galaxyproject/galaxy/blob/dev/doc/source/releases/${version}_announce.rst
|
||||
- [ ] Post release notes to https://docs.galaxyproject.org/en/master/releases/index.html
|
||||
- [ ] Create wiki *highlights* and post to http://galaxyproject.org News (w/ RSS) and NewsBriefs
|
||||
- [ ] Tweet wiki news *highlights* (or RTD?) via bit.ly link to https://twitter.com/galaxyproject/
|
||||
- [ ] Post *highlights* type News to Galaxy Biostars https://biostar.usegalaxy.org
|
||||
- [ ] Email *highlights* to galaxy-dev and galaxy-announce @lists.galaxyproject.org
|
||||
- [ ] Adjust http://getgalaxy.org text and links to match current master branch
|
||||
- [ ] Create wiki *highlights* and post to http://galaxyproject.org News (w/ RSS) and NewsBriefs. [An Example](https://wiki.galaxyproject.org/News/2016_04_GalaxyRelease).
|
||||
- [ ] Tweet docs news *highlights* via bit.ly link to https://twitter.com/galaxyproject/ (As user ``galaxyproject``, password in Galaxy password store under ``twitter.com / galaxyproject`` ). [An Example](https://twitter.com/galaxyproject/status/733029921316986881).
|
||||
- [ ] Post *highlights* type News to Galaxy Biostars https://biostar.usegalaxy.org. [An Example](https://biostar.usegalaxy.org/p/17712/).
|
||||
- [ ] Email *highlights* to [galaxy-dev](http://dev.list.galaxyproject.org/) and [galaxy-announce](http://announce.list.galaxyproject.org/) @lists.galaxyproject.org. [An Example](http://dev.list.galaxyproject.org/The-Galaxy-release-16-04-is-out-tp4669419.html)
|
||||
- [ ] Adjust http://getgalaxy.org text and links to match current master branch (TODO: describe how to do this)
|
||||
|
||||
- [ ] **Prepare for next release**
|
||||
|
||||
- [ ] Ensure milestone ``${next_version}`` exists.
|
||||
- [ ] Create release issue for next version ``make release-issue RELEASE_CURR=${next_version}``.
|
||||
- [ ] Schedule committer meeting to discuss re-alignment of priorities.
|
||||
- [ ] Close this issue.
|
||||
|
||||
""")
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
GXPIP_VERSION='8.0.2+gx2'
|
||||
|
||||
SET_VENV=1
|
||||
for arg in "$@"; do
|
||||
[ "$arg" = "--skip-venv" ] && SET_VENV=0
|
||||
@@ -133,31 +131,7 @@ fi
|
||||
|
||||
: ${GALAXY_WHEELS_INDEX_URL:="https://wheels.galaxyproject.org/simple"}
|
||||
if [ $REPLACE_PIP -eq 1 ]; then
|
||||
pip_version=`pip --version | awk '{print $2}'`
|
||||
method=`python - << EOF
|
||||
from pkg_resources import parse_version
|
||||
from sys import stdout
|
||||
if parse_version('$pip_version') >= parse_version('6.0'):
|
||||
stdout.write('req')
|
||||
elif parse_version('$pip_version') >= parse_version('1.5'):
|
||||
stdout.write('wheel')
|
||||
else:
|
||||
stdout.write('sdist')
|
||||
EOF`
|
||||
case $method in
|
||||
req)
|
||||
pip install --no-index --find-links ${GALAXY_WHEELS_INDEX_URL}/pip --upgrade "pip==${GXPIP_VERSION}"
|
||||
;;
|
||||
wheel)
|
||||
pip install --upgrade "https://wheels.galaxyproject.org/packages/pip-${GXPIP_VERSION}-py2.py3-none-any.whl"
|
||||
;;
|
||||
sdist)
|
||||
pip install --upgrade "https://wheels.galaxyproject.org/packages/pip-${GXPIP_VERSION}.tar.gz"
|
||||
;;
|
||||
esac
|
||||
|
||||
# binary-compatibility.cfg may need to be created (e.g. on CentOS)
|
||||
[ -n "$VIRTUAL_ENV" -a ! -f ${VIRTUAL_ENV}/binary-compatibility.cfg ] && python ./scripts/binary_compatibility.py -o ${VIRTUAL_ENV}/binary-compatibility.cfg
|
||||
pip install 'pip>=8.1'
|
||||
fi
|
||||
|
||||
if [ $FETCH_WHEELS -eq 1 ]; then
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"scratchbook.js","sources":["../../src/layout/scratchbook.js"],"names":["define","Frames","Backbone","View","extend","initialize","options","self","this","frames","visible","setElement","$el","buttonActive","collection","add","id","icon","tooltip","onclick","active","set","toggle","show_note","note_cls","hide","onbeforeunload","length","buttonLoad","show","on","note","addDataset","dataset_id","require","DATA","dataset","Dataset","$","when","fetch","then","frame_config","title","get","is_tabular","_","find","data_type","indexOf","tabular_dataset","TabularDataset","toJSON","content","parent_elt","createTabularDatasetChunkedView","model","embedded","height","url","Galaxy","root","addTrackster","viz_id","visualization","trackster","viz","Visualization","ui","TracksterUI","type","view_config","container","name","dbkey","stand_alone","latest_revision","drawables","config","view","each","d","hda_ldda","create_visualization","viewport","bookmarks","target","window","open","location","$galaxy_main","parent","document","href","attr"],"mappings":"AACAA,QAAS,oBAAsB,SAAUC,GACzC,MAAOC,UAASC,KAAKC,QACjBC,WAAa,SAAUC,GACnB,GAAIC,GAAOC,IACXF,GAAUA,MACVE,KAAKC,OAAS,GAAIR,GAAOE,MAAOO,SAAU,IAC1CF,KAAKG,WAAYH,KAAKC,OAAOG,KAC7BJ,KAAKK,aAAeP,EAAQQ,WAAWC,KACnCC,GAAkB,qBAClBC,KAAkB,QAClBC,QAAkB,6BAClBC,QAAkB,WACdZ,EAAKa,QAAUb,EAAKa,OACpBb,EAAKM,aAAaQ,KACdC,OAAYf,EAAKa,OACjBG,UAAYhB,EAAKa,OACjBI,SAAYjB,EAAKa,QAAU,iBAE9Bb,EAAKa,QAAUb,EAAKE,OAAOgB,QAEhCC,eAAkB,WACd,MAAKnB,GAAKE,OAAOkB,SAAW,EACjB,cAAgBpB,EAAKE,OAAOkB,SAAW,gCADlD,UAKRnB,KAAKoB,WAAatB,EAAQQ,WAAWC,KACjCC,GAAkB,mBAClBC,KAAkB,SAClBC,QAAkB,wBAClBK,WAAkB,EAClBb,SAAkB,EAClBS,QAAkB,WACdZ,EAAKE,OAAOC,QAAUH,EAAKE,OAAOgB,OAASlB,EAAKE,OAAOoB,UAG/DrB,KAAKC,OAAOqB,GAAI,aAAc,WAC1BtB,KAAKE,SAA4B,GAAjBF,KAAKmB,UAAiBnB,KAAKiB,OAC3ClB,EAAKqB,WAAWP,KAAOU,KAAQvB,KAAKmB,SAAUjB,QAAWF,KAAKmB,SAAW,MAC1EG,GAAI,aAAc,WACjBvB,EAAKqB,WAAWP,KAAOC,OAAUd,KAAKE,QAASO,KAAQT,KAAKE,SAAW,UAAY,oBAK3FsB,WAAY,SAAUC,GAClB,GAAI1B,GAAOC,IACX0B,UAAU,oBAAsB,SAAUC,GACtC,GAAIC,GAAU,GAAID,GAAKE,SAAWrB,GAAKiB,GACvCK,GAAEC,KAAMH,EAAQI,SAAUC,KAAM,WAE5B,GAAIC,IACIC,MAAOP,EAAQQ,IAAI,SAKvBC,EAAaC,EAAEC,MAAQ,UAAW,YAAe,SAAUC,GACvD,MAA2D,KAApDZ,EAAQQ,IAAK,aAAcK,QAASD,IAInD,IAAKH,EAAa,CACd,GAAIK,GAAkB,GAAIf,GAAKgB,eAAgBf,EAAQgB,SACvDN,GAAE1C,OAAQsC,GACNW,QAAS,SAAUC,GACfnB,EAAKoB,iCACDC,MAAcN,EACdI,WAAcA,EACdG,UAAc,EACdC,OAAc,gBAM1BZ,GAAE1C,OAAQsC,GACNiB,IAAKC,OAAOC,KAAO,YAAczB,EAAQpB,GAAK,0BAGtDT,GAAKQ,IAAK2B,QAMtBoB,aAAc,SAASC,GACnB,GAAIxD,GAAOC,IACX0B,UAAS,oBAAqB,iBAAkB,SAAS8B,EAAeC,GACpE,GAAIC,GAAM,GAAIF,GAAcG,eAAenD,GAAI+C,GAC/CzB,GAAEC,KAAM2B,EAAI1B,SAAUC,KAAM,WACxB,GAAI2B,GAAK,GAAIH,GAAUI,YAAYT,OAAOC,MAGtCnB,GACIC,MAAOuB,EAAItB,IAAI,QACf0B,KAAM,QACNjB,QAAS,SAASC,GAEd,GAAIiB,IACAC,UAAWlB,EACXmB,KAAMP,EAAItB,IAAI,SACd5B,GAAIkD,EAAIlD,GAER0D,MAAOR,EAAItB,IAAI,SACf+B,aAAa,GAEjBC,EAAkBV,EAAItB,IAAI,mBAC1BiC,EAAYD,EAAgBE,OAAOC,KAAKF,SAGxC/B,GAAEkC,KAAKH,EAAW,SAASI,GACvBA,EAAE7C,SACE8C,SAAUD,EAAEC,SACZlE,GAAIiE,EAAEhD,cAGd8C,KAAOX,EAAGe,qBAAqBZ,EACAK,EAAgBE,OAAOM,SACvBR,EAAgBE,OAAOC,KAAKF,UAC5BD,EAAgBE,OAAOO,WACvB,IAG3C9E,GAAKQ,IAAI2B,QAMrB3B,IAAK,SAAUT,GACX,GAAuB,UAAlBA,EAAQgF,OACTC,OAAOC,KAAMlF,EAAQqD,SAClB,IAAuB,QAAlBrD,EAAQgF,QAAsC,WAAlBhF,EAAQgF,QAAyC,SAAlBhF,EAAQgF,OAC3EC,OAAOE,SAAWnF,EAAQqD,QACvB,IAAMnD,KAAKY,OAiBdZ,KAAKC,OAAOM,IAAKT,OAjBM,CACvB,GAAIoF,GAAepD,EAAGiD,OAAOI,OAAOC,UAAW7C,KAAM,eACrD,IAAuB,eAAlBzC,EAAQgF,QAA6C,UAAlBhF,EAAQgF,OAC5C,GAA6B,IAAxBI,EAAa/D,OAAc,CAC5B,GAAIkE,GAAOvF,EAAQqD,GAEfkC,IADwB,IAAvBA,EAAK5C,QAAS,KACP,IAEA,IACZ4C,GAAQ,kBACRN,OAAOE,SAAWI,MAElBH,GAAaI,KAAM,MAAOxF,EAAQqD,SAGtC4B,QAAOE,SAAWnF,EAAQqD"}
|
||||
{"version":3,"file":"scratchbook.js","sources":["../../src/layout/scratchbook.js"],"names":["define","Frames","Backbone","View","extend","initialize","options","self","this","frames","visible","setElement","$el","buttonActive","collection","add","id","icon","tooltip","onclick","active","set","toggle","show_note","note_cls","hide","onbeforeunload","length","buttonLoad","show","on","note","history_cache","addDataset","dataset_id","current_dataset","Galaxy","currHistoryPanel","history_id","historyId","name","model","get","dataset_ids","each","push","_findDataset","dataset","offset","history_details","dataset_list","pos","indexOf","_loadDatasetOffset","frame","new_dataset_id","_loadDataset","new_dataset","config","trigger","_","menu","disabled","callback","require","DATA","Dataset","$","when","fetch","then","is_tabular","find","data_type","title","url","content","createTabularDatasetChunkedView","TabularDataset","toJSON","embedded","height","root","addTrackster","viz_id","visualization","trackster","viz","Visualization","ui","TracksterUI","frame_config","type","parent_elt","view_config","container","dbkey","stand_alone","latest_revision","drawables","view","d","hda_ldda","create_visualization","viewport","bookmarks","target","window","open","location","$galaxy_main","parent","document","href","attr"],"mappings":"AACAA,QAAS,oBAAsB,SAAUC,GACzC,MAAOC,UAASC,KAAKC,QACjBC,WAAa,SAAUC,GACnB,GAAIC,GAAOC,IACXF,GAAUA,MACVE,KAAKC,OAAS,GAAIR,GAAOE,MAAOO,SAAU,IAC1CF,KAAKG,WAAYH,KAAKC,OAAOG,KAC7BJ,KAAKK,aAAeP,EAAQQ,WAAWC,KACnCC,GAAkB,qBAClBC,KAAkB,QAClBC,QAAkB,6BAClBC,QAAkB,WACdZ,EAAKa,QAAUb,EAAKa,OACpBb,EAAKM,aAAaQ,KACdC,OAAYf,EAAKa,OACjBG,UAAYhB,EAAKa,OACjBI,SAAYjB,EAAKa,QAAU,iBAE9Bb,EAAKa,QAAUb,EAAKE,OAAOgB,QAEhCC,eAAkB,WACd,MAAKnB,GAAKE,OAAOkB,SAAW,EACjB,cAAgBpB,EAAKE,OAAOkB,SAAW,gCADlD,UAKRnB,KAAKoB,WAAatB,EAAQQ,WAAWC,KACjCC,GAAkB,mBAClBC,KAAkB,SAClBC,QAAkB,wBAClBK,WAAkB,EAClBb,SAAkB,EAClBS,QAAkB,WACdZ,EAAKE,OAAOC,QAAUH,EAAKE,OAAOgB,OAASlB,EAAKE,OAAOoB,UAG/DrB,KAAKC,OAAOqB,GAAI,aAAc,WAC1BtB,KAAKE,SAA4B,GAAjBF,KAAKmB,UAAiBnB,KAAKiB,OAC3ClB,EAAKqB,WAAWP,KAAOU,KAAQvB,KAAKmB,SAAUjB,QAAWF,KAAKmB,SAAW,MAC1EG,GAAI,aAAc,WACjBvB,EAAKqB,WAAWP,KAAOC,OAAUd,KAAKE,QAASO,KAAQT,KAAKE,SAAW,UAAY,mBAEvFF,KAAKwB,kBAITC,WAAY,SAAUC,GAClB,GAAI3B,GAAOC,KACP2B,EAAkB,IACtB,IAAKC,QAAUA,OAAOC,iBAAmB,CACrC,GAAIC,GAAaF,OAAOC,iBAAiBvB,WAAWyB,SACpD/B,MAAKwB,cAAeM,IAAiBE,KAAMJ,OAAOC,iBAAiBI,MAAMC,IAAK,QAAUC,gBACxFP,OAAOC,iBAAiBvB,WAAW8B,KAAM,SAAUH,IAC9CA,EAAMC,IAAK,YAAeD,EAAMC,IAAK,YAAenC,EAAKyB,cAAeM,GAAaK,YAAYE,KAAMJ,EAAMC,IAAK,SAG3H,GAAII,GAAe,SAAUC,EAASC,GAClC,GAAKD,EAAU,CACX,GAAIE,GAAkB1C,EAAKyB,cAAee,EAAQL,IAAK,cACvD,IAAKO,GAAmBA,EAAgBN,YAAc,CAClD,GAAIO,GAAeD,EAAgBN,YAC/BQ,EAAMD,EAAaE,QAASL,EAAQL,IAAK,MAC7C,IAAa,KAARS,GAAcA,EAAMH,GAAU,GAAKG,EAAMH,EAASE,EAAavB,OAChE,MAAOuB,GAAcC,EAAMH,MAKvCK,EAAqB,SAAUN,EAASC,EAAQM,GAChD,GAAIC,GAAiBT,EAAcC,EAASC,EACvCO,GACDhD,EAAKiD,aAAcD,EAAgB,SAAUE,EAAaC,GACtDvB,EAAkBsB,EAClBH,EAAMb,MAAMpB,IAAKqC,KAGrBJ,EAAMb,MAAMkB,QAAS,UAG7BnD,MAAKgD,aAActB,EAAY,SAAUa,EAASW,GAC9CvB,EAAkBY,EAClBxC,EAAKQ,IAAK6C,EAAExD,QAAUyD,OAAU5C,KAAW,4BACXC,QAAW,sBACXC,QAAW,SAAUmC,GAAUD,EAAoBlB,EAAiB,GAAImB,IACxEQ,SAAW,WAAa,OAAQhB,EAAcX,EAAiB,OAC/DlB,KAAW,6BACXC,QAAW,kBACXC,QAAW,SAAUmC,GAAUD,EAAoBlB,EAAiB,EAAGmB,IACvEQ,SAAW,WAAa,OAAQhB,EAAcX,EAAiB,OAAauB,OAIpHF,aAAc,SAAUtB,EAAY6B,GAChC,GAAIxD,GAAOC,IACXwD,UAAU,oBAAsB,SAAUC,GACtC,GAAIlB,GAAU,GAAIkB,GAAKC,SAAWlD,GAAKkB,GACvCiC,GAAEC,KAAMrB,EAAQsB,SAAUC,KAAM,WAC5B,GAAIC,GAAaX,EAAEY,MAAQ,UAAW,YAAe,SAAUC,GAC3D,MAA2D,KAApD1B,EAAQL,IAAK,aAAcU,QAASqB,KAE3CC,EAAQ3B,EAAQL,IAAK,QACrBO,EAAkB1C,EAAKyB,cAAee,EAAQL,IAAK,cAClDO,KACDyB,EAAQzB,EAAgBT,KAAO,KAAOkC,GAE1CX,EAAUhB,EAASwB,GACfG,MAAUA,EACVC,IAAU,KACVC,QAAUX,EAAKY,iCACXpC,MAAc,GAAIwB,GAAKa,eAAgB/B,EAAQgC,UAC/CC,UAAc,EACdC,OAAc,SACfrE,MAEH8D,MAAUA,EACVC,IAAUvC,OAAO8C,KAAO,YAAchD,EAAa,yBACnD0C,QAAU,YAO1BO,aAAc,SAASC,GACnB,GAAI7E,GAAOC,IACXwD,UAAS,oBAAqB,iBAAkB,SAASqB,EAAeC,GACpE,GAAIC,GAAM,GAAIF,GAAcG,eAAexE,GAAIoE,GAC/CjB,GAAEC,KAAMmB,EAAIlB,SAAUC,KAAM,WACxB,GAAImB,GAAK,GAAIH,GAAUI,YAAYtD,OAAO8C,MAGtCS,GACIjB,MAAOa,EAAI7C,IAAI,QACfkD,KAAM,QACNhB,QAAS,SAASiB,GAEd,GAAIC,IACAC,UAAWF,EACXrD,KAAM+C,EAAI7C,IAAI,SACd1B,GAAIuE,EAAIvE,GAERgF,MAAOT,EAAI7C,IAAI,SACfuD,aAAa,GAEjBC,EAAkBX,EAAI7C,IAAI,mBAC1ByD,EAAYD,EAAgBxC,OAAO0C,KAAKD,SAGxCvC,GAAEhB,KAAKuD,EAAW,SAASE,GACvBA,EAAEtD,SACEuD,SAAUD,EAAEC,SACZtF,GAAIqF,EAAEnE,cAGdkE,KAAOX,EAAGc,qBAAqBT,EACAI,EAAgBxC,OAAO8C,SACvBN,EAAgBxC,OAAO0C,KAAKD,UAC5BD,EAAgBxC,OAAO+C,WACvB,IAG3ClG,GAAKQ,IAAI4E,QAMrB5E,IAAK,SAAUT,GACX,GAAuB,UAAlBA,EAAQoG,OACTC,OAAOC,KAAMtG,EAAQqE,SAClB,IAAuB,QAAlBrE,EAAQoG,QAAsC,WAAlBpG,EAAQoG,QAAyC,SAAlBpG,EAAQoG,OAC3EC,OAAOE,SAAWvG,EAAQqE,QACvB,IAAMnE,KAAKY,OAWdZ,KAAKC,OAAOM,IAAKT,OAXM,CACvB,GAAIwG,GAAe3C,EAAGwC,OAAOI,OAAOC,UAAWxC,KAAM,eAC9B,gBAAlBlE,EAAQoG,QAA6C,UAAlBpG,EAAQoG,OACf,IAAxBI,EAAanF,OACdgF,OAAOE,SAAWvG,EAAQqE,KAA+B,IAAvBsC,KAAK7D,QAAS,KAAc,IAAM,KAAQ,kBAE5E0D,EAAaI,KAAM,MAAO5G,EAAQqE,KAGtCgC,OAAOE,SAAWvG,EAAQqE"}
|
||||
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
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user