Client-build: add the webpack task file, merge dev

This commit is contained in:
carlfeberhard
2016-01-15 14:04:10 -05:00
251 changed files with 1962 additions and 2193 deletions
+1 -1
View File
@@ -86,7 +86,7 @@ tool-data/genome/*
tool-data/*.sample
tool-data/testtoolshed.g2.bx.psu.edu/
tool-data/toolshed.g2.bx.psu.edu/
tool-data/**/*.fa
# Test output
test-data-cache
+61 -79
View File
@@ -173,7 +173,7 @@ var Collection = Backbone.Collection.extend({
if ( !Galaxy.user.id ){
var userTab = {
id : 'user',
icon : 'fa-user',
title : 'User',
cls : 'loggedout-only',
tooltip : 'Account registration or login',
menu : [{
@@ -191,7 +191,7 @@ var Collection = Backbone.Collection.extend({
} else {
var userTab = {
id : 'user',
icon : 'fa-user',
title : 'User',
cls : 'loggedin-only',
tooltip : 'Account preferences and saved data',
menu : [{
@@ -243,77 +243,64 @@ var Collection = Backbone.Collection.extend({
/** Masthead tab **/
var Tab = Backbone.View.extend({
initialize: function ( options ) {
var self = this;
this.model = options.model;
this.setElement( this._template() );
this.$dropdown = this.$( '.dropdown' );
this.$toggle = this.$( '.dropdown-toggle' );
this.$menu = this.$( '.dropdown-menu' );
this.$note = this.$( '.dropdown-note' );
this.model = options.model;
this.$el.attr( 'id', this.model.id );
this.model.on( 'init change:title', function() {
this.get( 'title' ) && self.$toggle.html( this.get( 'title' ) );
}).on( 'init change:visible', function() {
self.$el.css( { visibility : this.get( 'visible' ) && 'visible' || 'hidden' } );
}).on( 'init change:note', function() {
self.$note.html( this.get( 'note' ) );
}).on( 'init change:note_cls', function() {
this._prevNoteCls && self.$note.removeClass( this._prevNoteCls );
this.get( 'note_cls' ) && self.$note.addClass( this._prevNoteCls = this.get( 'note_cls' ) );
}).on( 'init change:show_note', function() {
self.$note.css( { 'display' : this.get( 'show_note' ) && 'block' || 'none' } );
}).on( 'init change:target', function() {
self.$toggle.attr( 'target', this.get( 'target' ) );
}).on( 'init change:url', function() {
this.set( 'url', self._formatUrl( this.get( 'url' ) ) );
self.$toggle.attr( 'href', this.get( 'url' ) );
}).on( 'init change:tooltip', function() {
$( '.tooltip' ).remove();
self.$toggle.tooltip( 'destroy' ).attr( 'title', this.get( 'tooltip' ) );
this.get( 'tooltip' ) && self.$toggle.tooltip( { placement: 'bottom' } );
}).on( 'init change:cls', function() {
this._prevCls && self.$toggle.removeClass( this._prevCls );
this.get( 'cls' ) && self.$toggle.addClass( this._prevCls = this.get( 'cls' ) );
}).on( 'init change:icon', function() {
this._prevIcon && self.$toggle.removeClass( this._prevIcon );
this.get( 'icon' ) && self.$toggle.addClass( this._prevIcon = 'fa fa-2x ' + this.get( 'icon' ) );
}).on( 'init change:toggle', function() {
self.$toggle[ this.get( 'toggle' ) && 'addClass' || 'removeClass' ]( 'toggle' );
}).on( 'init change:disabled', function() {
self.$toggle[ this.get( 'disabled' ) && 'addClass' || 'removeClass' ]( 'disabled' );
self._configurePopover();
}).on( 'init change:active', function() {
self.$dropdown[ this.get( 'active' ) && 'addClass' || 'removeClass' ]( 'active' );
}).on( 'init change:show_menu', function() {
if ( this.get( 'menu' ) && this.get( 'show_menu' ) ) {
self.$menu.show();
$( '#dd-helper' ).show().off().on( 'click', function() {
$( '#dd-helper' ).hide();
self.model.set( 'show_menu', false );
});
} else {
self.$menu.hide();
$( '#dd-helper' ).hide();
}
}).on( 'init change:menu', function() {
self.$menu.empty().removeClass( 'dropdown-menu' );
self.$toggle.find( 'b' ).remove();
if ( this.get( 'menu' ) ) {
_.each( this.get( 'menu' ), function( menuItem ) {
self.$menu.append( self._buildMenuItem( menuItem ) );
menuItem.divider && self.$menu.append( $( '<li/>' ).addClass( 'divider' ) );
});
self.$menu.addClass( 'dropdown-menu' );
self.$toggle.append( $( '<b/>' ).addClass( 'caret' ) );
}
}).trigger( 'init' );
this.listenTo( this.model, 'change', this.render, this );
},
/** Attach events */
events: {
'click .dropdown-toggle' : '_toggleClick'
},
render: function() {
var self = this;
$( '.tooltip' ).remove();
this.$el.attr( 'id', this.model.id )
.css( { visibility : this.model.get( 'visible' ) && 'visible' || 'hidden' } );
this.model.set( 'url', this._formatUrl( this.model.get( 'url' ) ) );
this.$note.html( this.model.get( 'note' ) || '' )
.removeClass().addClass( 'dropdown-note' )
.addClass( this.model.get( 'note_cls' ) )
.css( { 'display' : this.model.get( 'show_note' ) && 'block' || 'none' } )
this.$toggle.html( this.model.get( 'title' ) || '' )
.removeClass().addClass( 'dropdown-toggle' )
.addClass( this.model.get( 'cls' ) )
.addClass( this.model.get( 'icon' ) && 'fa fa-2x ' + this.model.get( 'icon' ) )
.addClass( this.model.get( 'toggle' ) && 'toggle' )
.attr( 'target', this.model.get( 'target' ) )
.attr( 'href', this.model.get( 'url' ) )
.attr( 'title', this.model.get( 'tooltip' ) )
.tooltip( 'destroy' );
this.model.get( 'tooltip' ) && this.$toggle.tooltip( { placement: 'bottom' } );
this.$dropdown.removeClass().addClass( 'dropdown' )
.addClass( this.model.get( 'disabled' ) && 'disabled' )
.addClass( this.model.get( 'active' ) && 'active' );
if ( this.model.get( 'menu' ) && this.model.get( 'show_menu' ) ) {
this.$menu.show();
$( '#dd-helper' ).show().off().on( 'click', function() {
$( '#dd-helper' ).hide();
self.model.set( 'show_menu', false );
});
} else {
self.$menu.hide();
$( '#dd-helper' ).hide();
}
this.$menu.empty().removeClass( 'dropdown-menu' );
if ( this.model.get( 'menu' ) ) {
_.each( this.model.get( 'menu' ), function( menuItem ) {
self.$menu.append( self._buildMenuItem( menuItem ) );
menuItem.divider && self.$menu.append( $( '<li/>' ).addClass( 'divider' ) );
});
self.$menu.addClass( 'dropdown-menu' );
self.$toggle.append( $( '<b/>' ).addClass( 'caret' ) );
}
return this;
},
/** Add new menu item */
_buildMenuItem: function ( options ) {
var self = this;
@@ -354,26 +341,21 @@ var Tab = Backbone.View.extend({
} else {
model.set( 'show_menu', true );
}
} else {
function buildLink( label, url ) {
return $( '<div/>' ).append( $( '<a/>' ).attr( 'href', Galaxy.root + url ).html( label ) ).html()
}
this.$toggle.popover && this.$toggle.popover( 'destroy' );
this.$toggle.popover({
html : true,
placement : 'bottom',
content : 'Please ' + buildLink( 'login', 'user/login?use_panels=True' ) + ' or ' +
buildLink( 'register', 'user/create?use_panels=True' ) + ' to use this feature.'
}).popover( 'show' );
setTimeout( function() { self.$toggle.popover( 'destroy' ) }, 5000 );
}
},
/** Configures login notification/popover */
_configurePopover: function() {
var self = this;
function buildLink( label, url ) {
return $( '<div/>' ).append( $( '<a/>' ).attr( 'href', Galaxy.root + url ).html( label ) ).html()
}
this.$toggle.popover && this.$toggle.popover( 'destroy' );
this.model.get( 'disabled' ) && this.$toggle.popover({
html : true,
placement : 'bottom',
content : 'Please ' + buildLink( 'login', 'user/login?use_panels=True' ) + ' or ' +
buildLink( 'register', 'user/create?use_panels=True' ) + ' to use this feature.'
}).on( 'shown.bs.popover', function() {
setTimeout( function() { self.$toggle.popover( 'hide' ) }, 5000 );
});
},
/** Url formatting */
_formatUrl: function( url ) {
return typeof url == 'string' && url.indexOf( '//' ) === -1 && url.charAt( 0 ) != '/' ? Galaxy.root + url : url;
+3
View File
@@ -4,6 +4,9 @@ define([
'utils/add-logging',
'utils/localization'
], function( _, Backbone, addLogging, _l ){
'use strict';
//==============================================================================
/** @class Mixin to add logging capabilities to an object.
* Designed to allow switching an objects log output off/on at one central
@@ -4,7 +4,8 @@ define([
"mvc/base-mvc",
"utils/localization"
], function( DC_LI, DATASET_LI_EDIT, BASE_MVC, _l ){
/* global Backbone */
'use strict';
//==============================================================================
var DCListItemView = DC_LI.DCListItemView;
/** @class Edit view for DatasetCollection.
@@ -4,7 +4,8 @@ define([
"mvc/base-mvc",
"utils/localization"
], function( LIST_ITEM, DATASET_LI, BASE_MVC, _l ){
/* global Backbone */
'use strict';
//==============================================================================
var FoldoutListItemView = LIST_ITEM.FoldoutListItemView,
ListItemView = LIST_ITEM.ListItemView;
@@ -33,11 +34,11 @@ var DCListItemView = FoldoutListItemView.extend(
_setUpListeners : function(){
FoldoutListItemView.prototype._setUpListeners.call( this );
// re-rendering on deletion
this.model.on( 'change', function( model, options ){
this.listenTo( this.model, 'change', function( model, options ){
if( _.isEqual( _.keys( model.changed ), [ 'deleted' ] ) ){
this.render();
}
}, this );
});
},
// ......................................................................... rendering
@@ -4,6 +4,8 @@ define([
"utils/localization"
], function( DATASET_MODEL, BASE_MVC, _l ){
'use strict';
var logNamespace = 'collections';
//==============================================================================
/*
@@ -6,6 +6,8 @@ define([
"utils/localization",
"ui/editable-text",
], function( DC_VIEW, DC_MODEL, DC_EDIT, BASE_MVC, _l ){
'use strict';
/* =============================================================================
TODO:
@@ -6,6 +6,8 @@ define([
"utils/localization"
], function( LIST_VIEW, DC_MODEL, DC_LI, BASE_MVC, _l ){
'use strict';
var logNamespace = 'collections';
/* =============================================================================
TODO:
@@ -83,12 +85,14 @@ var CollectionView = _super.extend(
_super.prototype._setUpItemViewListeners.call( panel, view );
// use pub-sub to: handle drilldown expansion and collapse
view.on( 'expanded:drilldown', function( v, drilldown ){
this._expandDrilldownPanel( drilldown );
}, this );
view.on( 'collapsed:drilldown', function( v, drilldown ){
this._collapseDrilldownPanel( drilldown );
}, this );
panel.listenTo( view, {
'expanded:drilldown': function( v, drilldown ){
this._expandDrilldownPanel( drilldown );
},
'collapsed:drilldown': function( v, drilldown ){
this._collapseDrilldownPanel( drilldown );
}
});
return this;
},
@@ -9,6 +9,8 @@ define([
"ui/hoverhighlight"
], function( HDCA, STATES, BASE_MVC, UI_MODAL, naturalSort, _l ){
'use strict';
var logNamespace = 'collections';
/*==============================================================================
TODO:
@@ -1008,7 +1010,7 @@ var collectionCreatorModal = function _collectionCreatorModal( elements, options
title : options.title || _l( 'Create a collection' ),
body : creator.$el,
width : '80%',
height : 'min-content',
height : '100%',
closing_events: true
});
creator.render();
@@ -7,6 +7,8 @@ define([
"ui/hoverhighlight"
], function( levenshteinDistance, naturalSort, LIST_COLLECTION_CREATOR, baseMVC, _l ){
'use strict';
var logNamespace = 'collections';
/* ============================================================================
TODO:
@@ -5,6 +5,8 @@ define([
"utils/localization"
], function( LIST_CREATOR, HDCA, BASE_MVC, _l ){
'use strict';
var logNamespace = 'collections';
/*==============================================================================
TODO:
@@ -5,6 +5,7 @@ define([
'mvc/base-mvc',
'utils/localization'
], function( DATASET, DATASET_LIST, MODAL, BASE_MVC, _l ){
'use strict';
var logNamespace = 'dataset';
/* ============================================================================
@@ -7,6 +7,8 @@ define([
"mvc/base-mvc",
"utils/localization"
], function( STATES, DATASET_LI, TAGS, ANNOTATIONS, faIconButton, BASE_MVC, _l ){
'use strict';
//==============================================================================
var _super = DATASET_LI.DatasetListItemView;
/** @class Editing view for DatasetAssociation.
@@ -5,7 +5,7 @@ define([
"mvc/base-mvc",
"utils/localization"
], function( LIST_ITEM, STATES, faIconButton, BASE_MVC, _l ){
/* global Backbone */
'use strict';
var logNamespace = 'dataset';
/*==============================================================================
@@ -44,7 +44,7 @@ var DatasetListItemView = _super.extend(
_super.prototype._setUpListeners.call( this );
// re-rendering on any model changes
this.model.on( 'change', function( model, options ){
this.listenTo( this.model, 'change', function( model, options ){
// if the model moved into the ready state and is expanded without details, fetch those details now
if( this.model.changedAttributes().state && this.model.inReadyState()
&& this.expanded && !this.model.hasDetails() ){
@@ -54,7 +54,7 @@ var DatasetListItemView = _super.extend(
} else {
this.render();
}
}, this );
});
},
// ......................................................................... expandable
@@ -4,6 +4,7 @@ define([
"mvc/base-mvc",
"utils/localization"
], function( LIST_VIEW, DATASET_LI, BASE_MVC, _l ){
'use strict';
var logNamespace = 'dataset';
/* =============================================================================
@@ -3,6 +3,7 @@ define([
"mvc/base-mvc",
"utils/localization"
], function( STATES, BASE_MVC, _l ){
'use strict';
var logNamespace = 'dataset';
//==============================================================================
@@ -1,5 +1,7 @@
define([
], function(){
'use strict';
//==============================================================================
/** Map of possible HDA/collection/job states to their string equivalents.
* A port of galaxy.model.Dataset.states.
+6 -6
View File
@@ -31,14 +31,14 @@ define([ 'utils/utils' ], function( Utils ) {
var dict = {};
this._iterate( this.app.section.$el, dict );
// add to result dictionary
// add to result dictionary, label elements
var result_dict = {};
this.flat_dict = {};
function add( flat_id, input_id, input_value ) {
self.flat_dict[ flat_id ] = input_id;
result_dict[ flat_id ] = input_value;
};
self.app.element_list[ input_id ] && self.app.element_list[ input_id ].$el.attr( 'tour_id', flat_id );
}
// converter between raw dictionary and job dictionary
function convert( identifier, head ) {
for ( var index in head ) {
@@ -73,7 +73,7 @@ define([ 'utils/utils' ], function( Utils ) {
break;
case 'conditional':
var value = self.app.field_list[ input.id ].value();
add ( flat_id + '|' + input.test_param.name, input.id, value );
add( flat_id + '|' + input.test_param.name, input.id, value );
var selectedCase = matchCase( input, value );
if ( selectedCase != -1 ) {
convert( flat_id, head[ input.id + '-section-' + selectedCase ] );
@@ -90,10 +90,10 @@ define([ 'utils/utils' ], function( Utils ) {
if ( field.collapsed && input.collapsible_value ) {
value = input.collapsible_value;
}
add ( flat_id, input.id, value );
add( flat_id, input.id, value );
if ( input.payload ) {
for ( var p_id in input.payload ) {
add ( p_id, input.id, input.payload[ p_id ] );
add( p_id, input.id, input.payload[ p_id ] );
}
}
}
+1 -1
View File
@@ -92,7 +92,7 @@ define([], function() {
/** Main Template
*/
_template: function(options) {
var tmp = '<div class="ui-form-element input-name-' + options.name + '">' +
var tmp = '<div class="ui-form-element">' +
'<div class="ui-form-error ui-error">' +
'<span class="fa fa-arrow-down"/><span class="ui-form-error-text"/>' +
'</div>' +
@@ -179,14 +179,13 @@ define(['utils/utils',
}
}
}
// create input element
var self = this;
return new Ui.Input({
id : 'field-' + input_def.id,
area : input_def.area,
onchange : function() {
self.app.trigger('change');
onchange : function( new_value ) {
input_def.onchange ? input_def.onchange( new_value ) : self.app.trigger( 'change' );
}
});
},
@@ -5,9 +5,8 @@ define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc']
/** This class creates a ui component which enables the dynamic creation of portlets
*/
var View = Backbone.View.extend({
/** Initialize
*/
initialize : function(options) {
var self = this;
this.options = Utils.merge(options, {
title : 'Section',
empty_text : 'Not available.',
@@ -15,13 +14,12 @@ var View = Backbone.View.extend({
min : null
});
this.setElement('<div/>');
var self = this;
// create button
this.button_new = new Ui.ButtonIcon({
icon : 'fa-plus',
title : 'Insert ' + options.title_new,
tooltip : 'Add new ' + options.title_new + ' block',
title : 'Insert ' + this.options.title_new,
tooltip : 'Add new ' + this.options.title_new + ' block',
floating: 'clear',
onclick : function() {
if (options.onnew) {
+1 -1
View File
@@ -190,7 +190,7 @@ define(['utils/utils', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'mvc/form/form-sec
});
// append message
this.portlet.append(this.message.$el.addClass('ui-margin-top'));
this.portlet.append(this.message.$el);
// append tool section
this.portlet.append(this.section.$el);
@@ -3,7 +3,8 @@ define([
"utils/localization"
], function( MODAL, _l ){
"use strict";
'use strict';
//==============================================================================
/**
* A dialog/modal that allows copying a user history or 'importing' from user
@@ -4,6 +4,9 @@ define([
"mvc/base-mvc",
"utils/localization"
], function( DATASET_LI_EDIT, HDA_LI, BASE_MVC, _l ){
'use strict';
//==============================================================================
var _super = DATASET_LI_EDIT.DatasetListItemEdit;
/** @class Editing view for HistoryDatasetAssociation.
+3 -1
View File
@@ -3,7 +3,9 @@ define([
"mvc/base-mvc",
"utils/localization"
], function( DATASET_LI, BASE_MVC, _l ){
/* global Backbone */
'use strict';
//==============================================================================
var _super = DATASET_LI.DatasetListItemView;
/** @class Read only view for HistoryDatasetAssociation.
@@ -4,6 +4,9 @@ define([
"mvc/base-mvc",
"utils/localization"
], function( DATASET, HISTORY_CONTENT, BASE_MVC, _l ){
'use strict';
//==============================================================================
var _super = DATASET.DatasetAssociation,
hcontentMixin = HISTORY_CONTENT.HistoryContentMixin;
@@ -4,6 +4,9 @@ define([
"ui/fa-icon-button",
"utils/localization"
], function( HDCA_LI, DC_VIEW_EDIT, faIconButton, _l ){
'use strict';
//==============================================================================
var _super = HDCA_LI.HDCAListItemView;
/** @class Editing view for HistoryDatasetCollectionAssociation.
+5 -3
View File
@@ -5,7 +5,9 @@ define([
"mvc/base-mvc",
"utils/localization"
], function( STATES, DC_LI, DC_VIEW, BASE_MVC, _l ){
/* global Backbone */
'use strict';
//==============================================================================
var _super = DC_LI.DCListItemView;
/** @class Read only view for HistoryDatasetCollectionAssociation (a dataset collection inside a history).
@@ -22,9 +24,9 @@ var HDCAListItemView = _super.extend(
_setUpListeners : function(){
_super.prototype._setUpListeners.call( this );
this.model.on({
this.listenTo( this.model, {
'change:populated change:visible' : function( model, options ){ this.render(); },
}, this );
});
},
/** Override to provide the proper collections panels as the foldout */
@@ -3,6 +3,9 @@ define([
"mvc/history/history-content-model",
"utils/localization"
], function( DC_MODEL, HISTORY_CONTENT, _l ){
'use strict';
/*==============================================================================
Models for DatasetCollections contained within a history.
@@ -4,6 +4,8 @@ define([
"utils/localization"
], function( STATES, BASE_MVC, _l ){
'use strict';
var logNamespace = 'history';
//==============================================================================
/** How the type_id attribute is built for the history's mixed contents collection */
@@ -6,6 +6,8 @@ define([
"utils/localization"
], function( HISTORY_CONTENT, HDA_MODEL, HDCA_MODEL, BASE_MVC, _l ){
'use strict';
var logNamespace = 'history';
//==============================================================================
/** @class Backbone collection for history content.
@@ -6,6 +6,8 @@ define([
"utils/localization"
], function( HISTORY_CONTENTS, UTILS, BASE_MVC, _l ){
'use strict';
var logNamespace = 'history';
//==============================================================================
/** @class Model for a Galaxy history resource - both a record of user
@@ -78,7 +80,7 @@ var History = Backbone.Model
if( this.contents ){
this.contents.historyId = newId;
}
}, this );
});
},
//TODO: see base-mvc
@@ -540,7 +542,7 @@ var HistoryCollection = Backbone.Collection
this.trigger( 'no-longer-current', oldCurrentId );
this.currentHistoryId = history.id;
}
}, this );
});
},
/** override to allow passing options.order and setting the sort order to one of sortOrders */
@@ -9,6 +9,8 @@ define([
'libs/d3'
], function( JobDAG, JOB, JOB_LI, HISTORY_CONTENT, DATASET_LI, BASE_MVC, _l ){
'use strict';
var logNamespace = 'history';
// ============================================================================
/*
@@ -157,8 +159,8 @@ var HistoryStructureComponent = Backbone.View.extend( BASE_MVC.LoggableMixin ).e
// create the bbone view for the job (to be positioned later accrd. to the layout) and cache
var li = new view.JobItemClass({ model: job, tool: jobData.tool, jobData: jobData });
li.on( 'expanding expanded collapsing collapsed', view.renderGraph, view );
li.foldout.on( 'view:expanding view:expanded view:collapsing view:collapsed', view.renderGraph, view );
view.listenTo( li, 'expanding expanded collapsing collapsed', view.renderGraph );
view.listenTo( li.foldout, 'view:expanding view:expanded view:collapsing view:collapsed', view.renderGraph );
return li;
},
@@ -169,7 +171,7 @@ var HistoryStructureComponent = Backbone.View.extend( BASE_MVC.LoggableMixin ).e
typeId = HISTORY_CONTENT.typeIdStr( content.history_content_type, content.id );
content = view.model.contents.get( typeId );
var li = new view.ContentItemClass({ model: content });
li.on( 'expanding expanded collapsing collapsed', view.renderGraph, view );
view.listenTo( li, 'expanding expanded collapsing collapsed', view.renderGraph );
return li;
},
@@ -5,6 +5,9 @@ define([
"mvc/base-mvc",
"utils/localization"
], function( HISTORY_VIEW, HDA_LI, HDCA_LI, BASE_MVC, _l ){
'use strict';
/* =============================================================================
TODO:
@@ -4,6 +4,9 @@ define([
"mvc/base-mvc",
"utils/localization"
], function( HISTORY_MODEL, HISTORY_VIEW_EDIT, BASE_MVC, _l ){
'use strict';
// ============================================================================
/** session storage for history panel preferences (and to maintain state)
*/
@@ -158,12 +161,12 @@ var CurrentHistoryView = _super.extend(
//TODO:?? may not be needed? see history-view-edit, 369
// if a hidden item is created (gen. by a workflow), moves thru the updater to the ready state,
// then: remove it from the collection if the panel is set to NOT show hidden datasets
this.collection.on( 'state:ready', function( model, newState, oldState ){
this.listenTo( this.collection, 'state:ready', function( model, newState, oldState ){
if( ( !model.get( 'visible' ) )
&& ( !this.storage.get( 'show_hidden' ) ) ){
this.removeItemView( model );
}
}, this );
});
},
/** listening for history events */
@@ -257,27 +260,28 @@ var CurrentHistoryView = _super.extend(
_renderTags : function( $where ){
var panel = this;
// render tags and show/hide based on preferences
_super.prototype._renderTags.call( this, $where );
if( this.preferences.get( 'tagsEditorShown' ) ){
this.tagsEditor.toggle( true );
_super.prototype._renderTags.call( panel, $where );
if( panel.preferences.get( 'tagsEditorShown' ) ){
panel.tagsEditor.toggle( true );
}
// store preference when shown or hidden
this.tagsEditor.on( 'hiddenUntilActivated:shown hiddenUntilActivated:hidden',
panel.listenTo( panel.tagsEditor, 'hiddenUntilActivated:shown hiddenUntilActivated:hidden',
function( tagsEditor ){
panel.preferences.set( 'tagsEditorShown', tagsEditor.hidden );
});
}
);
},
/** In this override, get and set current panel preferences when editor is used */
_renderAnnotation : function( $where ){
var panel = this;
// render annotation and show/hide based on preferences
_super.prototype._renderAnnotation.call( this, $where );
if( this.preferences.get( 'annotationEditorShown' ) ){
this.annotationEditor.toggle( true );
_super.prototype._renderAnnotation.call( panel, $where );
if( panel.preferences.get( 'annotationEditorShown' ) ){
panel.annotationEditor.toggle( true );
}
// store preference when shown or hidden
this.annotationEditor.on( 'hiddenUntilActivated:shown hiddenUntilActivated:hidden',
panel.listenTo( panel.annotationEditor, 'hiddenUntilActivated:shown hiddenUntilActivated:hidden',
function( annotationEditor ){
panel.preferences.set( 'annotationEditorShown', annotationEditor.hidden );
}
@@ -325,12 +329,12 @@ var CurrentHistoryView = _super.extend(
_super.prototype._setUpItemViewListeners.call( panel, view );
// use pub-sub to: handle drilldown expansion and collapse
view.on( 'expanded:drilldown', function( v, drilldown ){
panel.listenTo( view, 'expanded:drilldown', function( v, drilldown ){
this._expandDrilldownPanel( drilldown );
}, this );
view.on( 'collapsed:drilldown', function( v, drilldown ){
});
panel.listenTo( view, 'collapsed:drilldown', function( v, drilldown ){
this._collapseDrilldownPanel( drilldown );
}, this );
});
// when content is manipulated, make it the current-content
// view.on( 'visualize', function( v, ev ){
@@ -376,7 +380,7 @@ var CurrentHistoryView = _super.extend(
// ........................................................................ external objects/MVC
listenToGalaxy : function( galaxy ){
// TODO: MEM: questionable reference island / closure practice
galaxy.on( 'galaxy_main:load', function( data ){
this.listenTo( galaxy, 'galaxy_main:load', function( data ){
var pathToMatch = data.fullpath,
useToURLRegexMap = {
'display' : /datasets\/([a-f0-9]+)\/display/,
@@ -401,7 +405,7 @@ var CurrentHistoryView = _super.extend(
// need to type mangle to go from web route to history contents
hdaId = 'dataset-' + hdaId;
this._setCurrentContentById( hdaId );
}, this );
});
},
//TODO: remove quota meter from panel and remove this
@@ -30,6 +30,9 @@ define([
PopupMenu,
_l
){
'use strict';
/* =============================================================================
TODO:
@@ -90,7 +93,7 @@ var HistoryViewEdit = _super.extend(
});
panel.on( 'view:attached view:removed', function(){
panel._renderCounts();
}, panel );
});
},
// ------------------------------------------------------------------------ listeners
@@ -98,19 +101,21 @@ var HistoryViewEdit = _super.extend(
_setUpCollectionListeners : function(){
_super.prototype._setUpCollectionListeners.call( this );
this.collection.on( 'change:deleted', this._handleHdaDeletionChange, this );
this.collection.on( 'change:visible', this._handleHdaVisibleChange, this );
this.collection.on( 'change:purged', function( model ){
// hafta get the new nice-size w/o the purged model
this.model.fetch();
}, this );
this.listenTo( this.collection, {
'change:deleted': this._handleHdaDeletionChange,
'change:visible': this._handleHdaVisibleChange,
'change:purged' : function( model ){
// hafta get the new nice-size w/o the purged model
this.model.fetch();
}
});
return this;
},
/** listening for history and HDA events */
_setUpModelListeners : function(){
_super.prototype._setUpModelListeners.call( this );
this.model.on( 'change:size', this.updateHistoryDiskSize, this );
this.listenTo( this.model, 'change:size', this.updateHistoryDiskSize );
return this;
},
@@ -497,16 +502,14 @@ var HistoryViewEdit = _super.extend(
},
/** */
drop : function( ev ){
//console.warn( 'dataTransfer:', ev.dataTransfer.getData( 'text' ) );
//console.warn( 'dataTransfer:', ev.originalEvent.dataTransfer.getData( 'text' ) );
ev.preventDefault();
//ev.stopPropagation();
ev.dataTransfer.dropEffect = 'move';
//console.debug( 'ev.dataTransfer:', ev.dataTransfer );
var dataTransfer = ev.originalEvent.dataTransfer;
dataTransfer.dropEffect = 'move';
var panel = this,
data = ev.dataTransfer.getData( "text" );
data = dataTransfer.getData( "text" );
try {
data = JSON.parse( data );
@@ -23,6 +23,8 @@ define([
_l
){
'use strict';
var logNamespace = 'history';
// ============================================================================
@@ -377,11 +379,13 @@ var HistoryView = _super.extend(
//TODO:?? could use 'view:expanded' here?
// maintain a list of items whose bodies are expanded
view.on( 'expanded', function( v ){
panel.storage.addExpanded( v.model );
});
view.on( 'collapsed', function( v ){
panel.storage.removeExpanded( v.model );
panel.listenTo( view, {
'expanded': function( v ){
panel.storage.addExpanded( v.model );
},
'collapsed': function( v ){
panel.storage.removeExpanded( v.model );
}
});
return this;
},
@@ -2,6 +2,9 @@ define([
'utils/graph',
'utils/add-logging'
],function( GRAPH, addLogging ){
'use strict';
// ============================================================================
var _super = GRAPH.Graph;
/** A Directed acyclic Graph built from a history's job data.
@@ -8,6 +8,8 @@ define([
"ui/search-input"
], function( HISTORY_MODEL, HISTORY_VIEW_EDIT, historyCopyDialog, baseMVC, ajaxQueue ){
'use strict';
var logNamespace = 'history';
/* ==============================================================================
TODO:
@@ -5,7 +5,8 @@ define([
"utils/localization"
], function( PopupMenu, historyCopyDialog, BASE_MVC, _l ){
"use strict";
'use strict';
// ============================================================================
var menu = [
{
@@ -550,7 +550,11 @@ var FolderToolbarView = Backbone.View.extend({
},
error: function(model, response){
if (typeof response.responseJSON !== "undefined"){
mod_toastr.error(response.responseJSON.err_msg);
if (response.responseJSON.err_code === 404001){
mod_toastr.warning(response.responseJSON.err_msg);
} else{
mod_toastr.error(response.responseJSON.err_msg);
}
} else {
mod_toastr.error('An error ocurred.');
}
+3 -1
View File
@@ -3,6 +3,8 @@ define([
'utils/localization'
], function( BASE_MVC, _l ){
'use strict';
var logNamespace = 'list';
//==============================================================================
/** A view which, when first rendered, shows only summary data/attributes, but
@@ -475,7 +477,7 @@ var FoldoutListItemView = ListItemView.extend({
_expandByDrilldown : function(){
var view = this;
// attachment and rendering done by listener
view.foldout.on( 'close', function(){
view.listenTo( view.foldout, 'close', function(){
view.trigger( 'collapsed:drilldown', view, view.foldout );
});
view.trigger( 'expanded:drilldown', view, view.foldout );
+49 -43
View File
@@ -6,6 +6,8 @@ define([
"ui/search-input"
], function( LIST_ITEM, LoadingIndicator, BASE_MVC, _l ){
'use strict';
var logNamespace = 'list';
/* ============================================================================
TODO:
@@ -120,29 +122,30 @@ var ListPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(/** @lends
//TODO: move errorHandler down into list-view from history-view or
// pass to global error handler (Galaxy)
this.on( 'error', function( model, xhr, options, msg, details ){
//this.errorHandler( model, xhr, options, msg, details );
console.error( model, xhr, options, msg, details );
}, this );
// show hide the loading indicator
this.on( 'loading', function(){
this._showLoadingIndicator( 'loading...', 40 );
}, this );
this.on( 'loading-done', function(){
this._hideLoadingIndicator( 40 );
}, this );
this.on({
error: function( model, xhr, options, msg, details ){
//this.errorHandler( model, xhr, options, msg, details );
console.error( model, xhr, options, msg, details );
},
// show hide the loading indicator
loading: function(){
this._showLoadingIndicator( 'loading...', 40 );
},
'loading-done': function(){
this._hideLoadingIndicator( 40 );
},
});
// throw the first render up as a diff namespace using once (for outside consumption)
this.once( 'rendered', function(){
this.trigger( 'rendered:initial', this );
}, this );
});
// debugging
if( this.logger ){
this.on( 'all', function( event ){
this.log( this + '', arguments );
}, this );
});
}
this._setUpCollectionListeners();
@@ -156,21 +159,22 @@ var ListPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(/** @lends
this.collection.off();
// bubble up error events
this.collection.on( 'error', function( model, xhr, options, msg, details ){
this.trigger( 'error', model, xhr, options, msg, details );
}, this );
this.collection.on( 'reset', function(){
this.renderItems();
}, this );
this.collection.on( 'add', this.addItemView, this );
this.collection.on( 'remove', this.removeItemView, this );
this.listenTo( this.collection, {
error : function( model, xhr, options, msg, details ){
this.trigger( 'error', model, xhr, options, msg, details );
},
reset : function(){
this.renderItems();
},
add : this.addItemView,
remove : this.removeItemView
});
// debugging
if( this.logger ){
this.collection.on( 'all', function( event ){
this.listenTo( this.collection, 'all', function( event ){
this.info( this + '(collection)', arguments );
}, this );
});
}
return this;
},
@@ -180,23 +184,25 @@ var ListPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(/** @lends
this.log( this + '._setUpViewListeners' );
// shift to select a range
this.on( 'view:selected', function( view, ev ){
if( ev && ev.shiftKey && this.lastSelected ){
var lastSelectedView = this.viewFromModelId( this.lastSelected );
if( lastSelectedView ){
this.selectRange( view, lastSelectedView );
this.on({
'view:selected': function( view, ev ){
if( ev && ev.shiftKey && this.lastSelected ){
var lastSelectedView = this.viewFromModelId( this.lastSelected );
if( lastSelectedView ){
this.selectRange( view, lastSelectedView );
}
} else if( ev && ev.altKey && !this.selecting ){
this.showSelectors();
}
} else if( ev && ev.altKey && !this.selecting ){
this.showSelectors();
}
this.selected.push( view.model.id );
this.lastSelected = view.model.id;
}, this );
this.selected.push( view.model.id );
this.lastSelected = view.model.id;
},
this.on( 'view:de-selected', function( view, ev ){
this.selected = _.without( this.selected, view.model.id );
//this.lastSelected = view.model.id;
}, this );
'view:de-selected': function( view, ev ){
this.selected = _.without( this.selected, view.model.id );
//this.lastSelected = view.model.id;
}
});
},
// ------------------------------------------------------------------------ rendering
@@ -426,14 +432,14 @@ var ListPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(/** @lends
_setUpItemViewListeners : function( view ){
var panel = this;
// send all events to the panel, re-namspaceing them with the view prefix
view.on( 'all', function(){
this.listenTo( view, 'all', function(){
var args = Array.prototype.slice.call( arguments, 0 );
args[0] = 'view:' + args[0];
panel.trigger.apply( panel, args );
});
// drag multiple - hijack ev.setData to add all selected items
view.on( 'draggable:dragstart', function( ev, v ){
this.listenTo( view, 'draggable:dragstart', function( ev, v ){
//TODO: set multiple drag data here
var json = {},
selected = this.getSelectedModels();
@@ -912,7 +918,7 @@ var ModelListPanel = ListPanel.extend({
// override
this.log( this + '._setUpModelListeners', this.model );
// bounce model errors up to the panel
this.model.on( 'error', function(){
this.listenTo( this.model, 'error', function(){
var args = Array.prototype.slice.call( arguments, 0 );
//args.unshift( 'model:error' );
args.unshift( 'error' );
@@ -291,4 +291,4 @@ define(['utils/utils', 'utils/deferred', 'mvc/ui/ui-misc', 'mvc/form/form-view',
return $el;
}
});
});
});
@@ -7,9 +7,8 @@ define(['utils/utils', 'mvc/tool/tool-form-base'],
// create form view
var View = ToolFormBase.extend({
initialize: function(options) {
// link this
var self = this;
this.hasLabelListeners = false;
this.workflow = options.workflow;
// link with node representation in workflow module
this.node = options.node;
@@ -40,7 +39,6 @@ define(['utils/utils', 'mvc/tool/tool-form-base'],
// module information for the tool to update the workflow
// state stored on the client with. User needs to save
// for this to take effect.
self.initializeLabelListener();
self.node.update_field_data(data);
self.errors(data && data.tool_model)
}
@@ -73,29 +71,6 @@ define(['utils/utils', 'mvc/tool/tool-form-base'],
ToolFormBase.prototype.initialize.call(this, options);
},
initializeLabelListener: function() {
var self = this;
if(this.hasLabelListeners !== false) {
return;
}
this.hasLabelListeners = [];
var outputSections = _.where(this.options.inputs, {outputSection: true});
var labelInputs = outputSections.map(function(entry) {
var sectionId = entry.id;
var outputId = entry.outputId;
var $section = $("#" + sectionId);
var $labelRow = $section.find(".section-row").first();
var labelTextInput = $labelRow.find("input")[0];
$(labelTextInput).bind('input propertychange', function() {
var newLabel = $(labelTextInput).val();
var workflow = self.node.app.workflow;
workflow.attemptUpdateOutputLabel( self.node, outputId, newLabel );
});
});
},
/** Builds all sub sections
*/
_makeSections: function(options){
@@ -150,6 +125,7 @@ define(['utils/utils', 'mvc/tool/tool-form-base'],
*/
_makeSection: function(output_id, datatypes){
// format datatypes
var self = this;
var extensions = [];
var input_terminal_names = [];
@@ -188,15 +164,14 @@ define(['utils/utils', 'mvc/tool/tool-form-base'],
title : 'Configure Output: \'' + output_id + '\'',
type : 'section',
flat : true,
outputSection: true,
outputId : output_id,
inputs : [{
action : 'Label',
label : 'Label',
type : 'text',
value : '',
ignore : '',
help : 'This will provide a short name to describe the output - this must be unique across workflows.'
value : ( output = this.node.getWorkflowOutput( output_id ) ) && output.label || '',
help : 'This will provide a short name to describe the output - this must be unique across workflows.',
onchange : function( new_value ) {
self.workflow.attemptUpdateOutputLabel( self.node, output_id, new_value );
}
},{
action : 'RenameDatasetAction',
pja_arg : 'newname',
@@ -267,21 +242,13 @@ define(['utils/utils', 'mvc/tool/tool-form-base'],
};
// visit input nodes and enrich by name/value pairs from server data
var self = this;
function visit (head, head_list) {
head_list = head_list || [];
head_list.push(head);
for (var i in head.inputs) {
var input = head.inputs[i];
var action = input.action;
if ( action == "Label") {
var workflowOutput = self.node.getWorkflowOutput(output_id);
if ( workflowOutput ) {
input.value = workflowOutput['label'] || '';
} else{
input.value = '';
}
} else if (action) {
if (action) {
// construct identifier as expected by backend
input.name = 'pja__' + output_id + '__' + input.action;
if (input.pja_arg) {
+1 -1
View File
@@ -14,7 +14,7 @@ var View = Backbone.View.extend({
this.multiple = options.multiple || false;
// create message handler
this.message = new Ui.Message({ cls: 'ui-margin-top' });
this.message = new Ui.Message();
// create portlet
this.portlet = new Portlet.View({ cls: 'ui-portlet-section' });
+84 -201
View File
@@ -10,257 +10,141 @@ define(['utils/utils',
'mvc/ui/ui-modal'],
function( Utils, Select, Slider, Options, Drilldown, Buttons, Modal ) {
/** Image wrapper */
var Image = Backbone.View.extend({
initialize : function(options) {
this.options = Utils.merge(options, {
url : '',
cls : ''
});
this.setElement(this._template(this.options));
},
_template: function(options) {
return '<img class="ui-image ' + options.cls + '" src="' + options.url + '"/>';
}
});
/** Label wrapper */
var Label = Backbone.View.extend({
initialize : function(options) {
this.options = Utils.merge(options, {
title : '',
cls : '',
tagname : 'label'
});
this.setElement(this._template(this.options));
tagName: 'label',
initialize: function( options ) {
this.model = options && options.model || new Backbone.Model( options );
this.tagName = options.tagName || this.tagName;
this.setElement( $( '<' + this.tagName + '/>' ) );
this.listenTo( this.model, 'change', this.render, this );
this.render();
},
title: function(new_title) {
this.$el.html(new_title);
title: function( new_title ) {
this.model.set( 'title', new_title );
},
value: function() {
return options.title;
return this.model.get( 'title' );
},
_template: function(options) {
return $( '<' + options.tagname + '/>' ).addClass( 'ui-label' ).addClass( options.cls ).html( options.title );
}
});
/** Displays an icon with title */
var Icon = Backbone.View.extend({
initialize : function(options) {
this.options = Utils.merge(options, {
floating : 'right',
icon : '',
tooltip : '',
placement : 'bottom',
title : '',
cls : ''
});
this.setElement(this._template(this.options));
$(this.el).tooltip({title: options.tooltip, placement: 'bottom'});
},
_template: function(options) {
return '<div>' +
'<span class="fa ' + options.icon + '" class="ui-icon"/>&nbsp;' +
options.title +
'</div>';
}
});
/** Renders an anchor element */
var Anchor = Backbone.View.extend({
initialize : function(options) {
this.options = Utils.merge(options, {
title : '',
cls : ''
});
this.setElement(this._template(this.options));
$(this.el).on('click', options.onclick);
},
_template: function(options) {
return '<div><a href="javascript:void(0)" class="ui-anchor ' + options.cls + '">' + options.title + '</a></div>';
render: function() {
this.$el.removeClass()
.addClass( 'ui-label' )
.addClass( this.model.get( 'cls' ) )
.html( this.model.get( 'title' ) );
return this;
}
});
/** Displays messages used e.g. in the tool form */
var Message = Backbone.View.extend({
initialize : function(options) {
this.options = Utils.merge(options, {
initialize: function( options ) {
this.model = options && options.model || new Backbone.Model({
message : null,
status : 'info',
cls : '',
persistent : false
});
this.setElement('<div class="' + this.options.cls + '"/>');
this.options.message && this.update(this.options);
}).set( options );
this.listenTo( this.model, 'change', this.render, this );
this.render();
},
// update
update: function(options) {
// get options
this.options = Utils.merge(options, this.options);
// show message
if (options.message != '') {
this.$el.html(this._template(this.options));
update: function( options ) {
this.model.set( options );
},
render: function() {
this.$el.removeClass().addClass( 'ui-message' ).addClass( this.model.get( 'cls' ) );
var status = this.model.get( 'status' );
if ( this.model.get( 'large' ) ) {
this.$el.addClass((( status == 'success' && 'done' ) ||
( status == 'danger' && 'error' ) ||
status ) + 'messagelarge' );
} else {
this.$el.addClass( 'alert' ).addClass( 'alert-' + status );
}
if ( this.model.get( 'message' ) ) {
this.$el.html( this.model.get( 'message' ) );
this.$el.fadeIn();
// clear previous timeouts
if (this.timeout) {
window.clearTimeout(this.timeout);
}
// set timeout if message is not persistent
if (!options.persistent) {
this.timeout && window.clearTimeout( this.timeout );
if ( !this.model.get( 'persistent' ) ) {
var self = this;
this.timeout = window.setTimeout(function() {
if (self.$el.is(':visible')) {
self.$el.fadeOut();
} else {
self.$el.hide();
}
}, 3000);
this.timeout = window.setTimeout( function() {
self.$el.fadeOut();
}, 3000 );
}
} else {
this.$el.fadeOut();
}
},
// template
_template: function(options) {
var cls_status = 'ui-message alert alert-' + options.status;
if (options.large) {
cls_status = ( ( options.status == 'success' && 'done' ) ||
( options.status == 'danger' && 'error' ) ||
options.status ) + 'messagelarge';
}
return '<div class="' + cls_status + '" >' +
options.message +
'</div>';
}
});
/** Render a search box */
var Searchbox = Backbone.View.extend({
initialize : function(options) {
this.options = Utils.merge(options, {
onclick : null,
searchword : ''
});
this.setElement(this._template(this.options));
var self = this;
if (this.options.onclick) {
this.$el.on('submit', function(e) {
var search_field = self.$el.find('#search');
self.options.onclick(search_field.val());
});
}
},
_template: function(options) {
return '<div class="ui-search">' +
'<form onsubmit="return false;">' +
'<input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="' + options.searchword + '">' +
'<button type="submit" class="btn search-btn">' +
'<i class="fa fa-search"></i>' +
'</button>' +
'</form>' +
'</div>';
return this;
}
});
/** Renders an input element used e.g. in the tool form */
var Input = Backbone.View.extend({
initialize : function(options) {
// configure options
this.options = Utils.merge(options, {
initialize: function( options ) {
this.model = options && options.model || new Backbone.Model({
type : 'text',
placeholder : '',
disabled : false,
visible : true,
cls : '',
area : false
});
// create new element
this.setElement(this._template(this.options));
// set initial value
if (this.options.value !== undefined) {
this.value(this.options.value);
}
// disable input field
if (this.options.disabled) {
this.$el.prop('disabled', true);
}
// hide input field
if (!this.options.visible) {
this.$el.hide();
}
// onchange event handler. fires on user activity.
var self = this;
this.$el.on('input', function() {
if (self.options.onchange) {
self.options.onchange(self.$el.val());
}
});
}).set( options );
this.tagName = this.model.get( 'area' ) ? 'textarea' : 'input';
this.setElement( $( '<' + this.tagName + '/>' ) );
this.listenTo( this.model, 'change', this.render, this );
this.render();
},
// value
value : function (new_val) {
if (new_val !== undefined) {
this.$el.val( ( typeof new_val === 'string' && new_val ) || '' );
}
return this.$el.val();
events: {
'input': '_onchange'
},
// template
_template: function(options) {
if (options.area) {
return '<textarea id="' + options.id + '" class="ui-textarea ' + options.cls + '"></textarea>';
} else {
return '<input id="' + options.id + '" type="' + options.type + '" value="' + options.value + '" placeholder="' + options.placeholder + '" class="ui-input ' + options.cls + '">';
}
value: function( new_val ) {
new_val !== undefined && this.model.set( 'value', typeof new_val === 'string' ? new_val : '' );
return this.model.get( 'value' );
},
render: function() {
this.$el.removeClass()
.addClass( 'ui-' + this.tagName )
.addClass( this.model.get( 'cls' ) )
.attr( 'id', this.model.id )
.attr( 'type', this.model.get( 'type' ) )
.attr( 'placeholder', this.model.get( 'placeholder' ) )
.val( this.model.get( 'value' ) );
this.model.get( 'disabled' ) ? this.$el.attr( 'disabled', true ) : this.$el.removeAttr( 'disabled' );
this.$el[ this.model.get( 'visible' ) ? 'show' : 'hide' ]();
return this;
},
_onchange: function() {
this.value( this.$el.val() );
this.model.get( 'onchange' ) && this.model.get( 'onchange' )( this.model.get( 'value' ) );
}
});
/** Creates a hidden element input field used e.g. in the tool form */
var Hidden = Backbone.View.extend({
initialize : function(options) {
this.options = options;
this.setElement(this._template(this.options));
if (this.options.value !== undefined) {
this.value(this.options.value);
}
initialize: function( options ) {
this.model = options && options.model || new Backbone.Model( options );
this.setElement( $ ( '<div/>' ).append( this.$info = $( '<div/>' ) )
.append( this.$hidden = $( '<div/>' ) ) );
this.listenTo( this.model, 'change', this.render, this );
this.render();
},
value : function (new_val) {
if (new_val !== undefined) {
this.$('hidden').val(new_val);
}
return this.$('hidden').val();
value: function( new_val ) {
new_val !== undefined && this.model.set( 'value', new_val );
return this.model.get( 'value' );
},
_template: function(options) {
var tmpl = '<div id="' + options.id + '" >';
if (options.info) {
tmpl += '<div>' + options.info + '</div>';
}
tmpl += '<hidden value="' + options.value + '"/>' +
'</div>';
return tmpl;
render: function() {
this.$el.attr( 'id', this.model.id );
this.$hidden.val( this.model.get( 'value' ) );
this.model.get( 'info' ) ? this.$info.show().html( this.model.get( 'info' ) ) : this.$info.hide();
return this;
}
});
return {
Anchor : Anchor,
Button : Buttons.ButtonDefault,
ButtonIcon : Buttons.ButtonIcon,
ButtonCheck : Buttons.ButtonCheck,
ButtonMenu : Buttons.ButtonMenu,
ButtonLink : Buttons.ButtonLink,
Icon : Icon,
Image : Image,
Input : Input,
Label : Label,
Message : Message,
@@ -268,7 +152,6 @@ define(['utils/utils',
RadioButton : Options.RadioButton,
Checkbox : Options.Checkbox,
Radio : Options.Radio,
Searchbox : Searchbox,
Select : Select,
Hidden : Hidden,
Slider : Slider,
@@ -322,7 +322,7 @@ return Backbone.View.extend({
'<td>' +
'<div id="genome" class="upload-genome"/>' +
'</td>' +
'<td><div id="settings" class="upload-icon-button fa fa-gear"/></td>' +
'<td><div id="settings" class="upload-settings upload-icon-button fa fa-gear"/></td>' +
'<td>' +
'<div id="info" class="upload-info">' +
'<div class="progress">' +
@@ -1,93 +1,43 @@
/** This renders the content of the settings popup, allowing users to specify flags i.e. for space-to-tab conversion **/
define(['utils/utils'], function(Utils) {
define( [ 'utils/utils' ], function( Utils ) {
return Backbone.View.extend({
// options
options: {
class_check : 'upload-icon-button fa fa-check-square-o',
class_uncheck : 'upload-icon-button fa fa-square-o'
class_check : 'fa-check-square-o',
class_uncheck : 'fa-square-o',
parameters : [{
id : 'space_to_tab',
title : 'Convert spaces to tabs',
},{
id : 'to_posix_lines',
title : 'Use POSIX standard'
}]
},
// initialize
initialize: function(app) {
// link app
this.app = app;
// link this
initialize: function( options ) {
var self = this;
// set template
this.setElement(this._template());
// link model
this.model = this.app.model;
// ui event: space-to-tab
this.$('#upload-space-to-tab').on('click', function() {
self._switchState('#upload-space-to-tab', 'space_to_tab');
});
// ui event: to-posix-lines
this.$('#upload-to-posix-lines').on('click', function() {
self._switchState('#upload-to-posix-lines', 'to_posix_lines');
});
// render
this.render();
this.model = options.model;
this.setElement( $( '<div/>' ).addClass( 'upload-settings' ) );
this.$el.append( $( '<div/>' ).addClass( 'upload-settings-cover' ) );
this.$el.append( $( '<table/>' ).addClass( 'upload-settings-table ui-table-striped' ).append( '<tbody/>' ) );
this.$cover = this.$( '.upload-settings-cover' );
this.$table = this.$( '.upload-settings-table > tbody' );
this.listenTo ( this.model, 'change', this.render, this );
this.model.trigger( 'change' );
},
// render
render: function() {
// render states
this._renderState('#upload-space-to-tab', this.model.get('space_to_tab'));
this._renderState('#upload-to-posix-lines', this.model.get('to_posix_lines'));
// disable options
var $cover = this.$('#upload-settings-cover');
if (!this.model.get('enabled')) {
$cover.show();
} else {
$cover.hide();
}
},
// switch state
_switchState: function (element_id, parameter_id) {
if (this.model.get('enabled')) {
var checked = !this.model.get(parameter_id);
this.model.set(parameter_id, checked);
this._renderState(element_id, checked);
}
},
// render state
_renderState: function (element_id, checked) {
var $it = this.$(element_id);
$it.removeClass();
if (checked) {
$it.addClass(this.options.class_check);
} else {
$it.addClass(this.options.class_uncheck);
}
},
// load template
_template: function() {
return '<div class="upload-settings" style="position: relative;">' +
'<div id="upload-settings-cover" class="upload-settings-cover"/>' +
'<table class="ui-table-striped">' +
'<tbody>' +
'<tr>' +
'<td><div id="upload-space-to-tab"/></td>' +
'<td>Convert spaces to tabs</td>' +
'</tr>' +
'<tr>' +
'<td><div id="upload-to-posix-lines"/></td>' +
'<td>Use POSIX standard</td>' +
'</tr>' +
'</tbody>' +
'</table>' +
'</div>';
var self = this;
this.$table.empty();
_.each( this.options.parameters, function( parameter ) {
var $checkbox = $( '<div/>' ).addClass( 'upload-' + parameter.id + ' upload-icon-button fa' )
.addClass( self.model.get( parameter.id ) && self.options.class_check || self.options.class_uncheck )
.on( 'click', function() {
self.model.get( 'enabled' ) && self.model.set( parameter.id, !self.model.get( parameter.id ) )
});
self.$table.append( $( '<tr/>' ).append( $( '<td/>' ).append( $checkbox ) )
.append( $( '<td/>' ).append( parameter.title ) ) )
});
this.$cover[ this.model.get( 'enabled' ) && 'hide' || 'show' ]();
}
});
});
});
@@ -4,6 +4,7 @@ define([
'mvc/base-mvc',
'utils/localization'
], function( _, Backbone, baseMVC, _l ){
'use strict';
var logNamespace = 'user';
//==============================================================================
@@ -2,6 +2,7 @@ define([
"mvc/base-mvc",
"utils/localization"
], function( baseMVC, _l ){
'use strict';
var logNamespace = 'user';
//==============================================================================
@@ -27,7 +28,7 @@ var UserQuotaMeter = Backbone.View.extend( baseMVC.LoggableMixin ).extend(
_.extend( this.options, options );
//this.bind( 'all', function( event, data ){ this.log( this + ' event:', event, data ); }, this );
this.model.bind( 'change:quota_percent change:total_disk_usage', this.render, this );
this.listenTo( this.model, 'change:quota_percent change:total_disk_usage', this.render );
},
/** Re-load user model data from the api */
@@ -617,9 +617,7 @@ EditorFormView = Backbone.View.extend({
// Global state for the whole workflow
reset: function() {
if ( this.workflow ) {
this.workflow.remove_all();
}
this.workflow && this.workflow.remove_all();
this.workflow = Globals.workflow = new Workflow( this, $("#canvas-container") );
},
@@ -795,6 +793,7 @@ EditorFormView = Backbone.View.extend({
if (node.type == 'tool' && Utils.isJSON(text)) {
var options = JSON.parse(text);
options.node = node;
options.workflow = this.workflow;
options.datatypes = this.datatypes;
formView = new ToolForm.View(options);
} else {
+5 -8
View File
@@ -123,16 +123,13 @@ function request (options) {
data : options.data || {},
url : options.url
}
// encode data into url
if (ajaxConfig.type == 'GET' || ajaxConfig.type == 'DELETE') {
if (ajaxConfig.url.indexOf('?') == -1) {
ajaxConfig.url += '?';
} else {
ajaxConfig.url += '&';
if ( ajaxConfig.type == 'GET' || ajaxConfig.type == 'DELETE' ) {
if ( !$.isEmptyObject(ajaxConfig.data) ) {
ajaxConfig.url += ajaxConfig.url.indexOf('?') == -1 ? '?' : '&';
ajaxConfig.url += $.param(ajaxConfig.data, true);
}
ajaxConfig.url = ajaxConfig.url + $.param(ajaxConfig.data, true);
ajaxConfig.data = null;
ajaxConfig.data = null;
} else {
ajaxConfig.dataType = 'json';
ajaxConfig.url = ajaxConfig.url;
+5 -1
View File
@@ -64,7 +64,11 @@
.ui-message {
padding: 2px 10px 2px 10px;
margin: 0px;
margin-top: @ui-margin-vertical-large;
margin-bottom: 0px;
float: left;
width: 100%;
display: none;
}
.ui-modal {
+1
View File
@@ -227,6 +227,7 @@
}
.upload-settings {
position: relative;
.upload-settings-cover {
position: absolute;
width: 100%;
+38
View File
@@ -0,0 +1,38 @@
/**
* Grunt task to bundle apps using webpack (see also ../webpack.config.js).
*/
module.exports = function( grunt ){
"use strict";
var path = require( 'path' );
// there is a taskrunner specifically for this - but it's not straightforward
// and duplicates some of the config/code in webpack.config,
// https://github.com/webpack/grunt-webpack
// http://webpack.github.io/docs/usage-with-grunt.html
// so we'll use grunt-exec and call the webpack cli instead (until CLI and runner are unified a bit more?)
grunt.loadNpmTasks( 'grunt-exec' );
function webpackCLI(){
var args = Array.prototype.slice.call( arguments );
args.unshift( path.join( __dirname, '../node_modules/webpack/bin/webpack.js' ) );
return args.join( ' ' );
}
grunt.registerTask( 'webpack', function(){
grunt.log.writeln( 'bundling webpack apps for production...' );
grunt.config( 'exec.webpack-production.command', webpackCLI( '-p' ) );
grunt.task.run( 'exec:webpack-production' );
});
grunt.registerTask( 'webpack-dev', function(){
grunt.log.writeln( 'bundling webpack apps for development...' );
grunt.config( 'exec.webpack-dev.command', webpackCLI( '-d' ) );
grunt.task.run( 'exec:webpack-dev' );
});
grunt.registerTask( 'webpack-watch', function(){
grunt.log.writeln( 'bundling webpack apps for development and watching for changes...' );
grunt.config( 'exec.webpack-watch.command', webpackCLI( '-d', '--watch' ) );
grunt.task.run( 'exec:webpack-watch' );
});
};
+24 -3
View File
@@ -172,7 +172,7 @@ paste.app_factory = galaxy.web.buildapp:app_factory
# from the Tool Shed will fail.
#tool_dependency_dir = None
# The dependency resolves config file specifies an ordering and options for how
# The dependency resolves config file specifies an ordering and options for how
# Galaxy resolves tool dependencies (requirement tags in Tool XML). The default
# ordering is to the use the tool shed for tools installed that way, use local
# Galaxy packages, and then use conda if available.
@@ -301,6 +301,19 @@ paste.app_factory = galaxy.web.buildapp:app_factory
# Set to false to disable various checks Galaxy will do to ensure it
# can run job scripts before attempting to execute or submit them.
#check_job_script_integrity = True
# Number of checks to execute if check_job_script_integrity is enabled.
#check_job_script_integrity_count = 35
# Time to sleep between checks if check_job_script_integrity is enabled (in seconds).
#check_job_script_integrity_sleep = .25
# Set the default shell used by jobs Galaxy-wide. This defaults to
# sh and can be overidden at the destination level for
# heterogenous clusters. conda job resolution requires bash or zsh
# so if this is not switched to /bin/bash for instance - conda resolution
# should be disabled. (16.01 will likely be the last release with a
# default of /bin/sh instead of /bin/bash).
#default_job_shell = /bin/sh
# Citation related caching. Tool citations information maybe fetched from
# external sources such as http://dx.doi.org/ by Galaxy - the following
@@ -662,6 +675,14 @@ nglims_config_file = tool-data/nglims.yaml
# by setting the following option to True.
#serve_xss_vulnerable_mimetypes = False
# Return a Access-Control-Allow-Origin response header that matches the Origin
# header of the request if that Origin hostname matches one of the strings or
# regular expressions listed here. This is a comma separated list of hostname
# strings or regular expressions beginning and ending with /.
# E.g. mysite.com,google.com,usegalaxy.org,/^[\w\.]*example\.com/
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
#allowed_origin_hostnames = None
# Set the following to True to use IPython nbconvert to build HTML from IPython
# notebooks in Galaxy histories. This process may allow users to execute
# arbitrary code or serve arbitrary HTML. If enabled, IPython must be
@@ -878,8 +899,8 @@ use_interactive = True
# Set the following to a number of threads greater than 1 to spawn
# a Python task queue for dealing with large tool submissions (either
# through the tool form or as part of an individual workflow step across
# large collection). The size of a "large" tool request is controlled by
# the second parameter below and defaults to 10. This affects workflow
# large collection). The size of a "large" tool request is controlled by
# the second parameter below and defaults to 10. This affects workflow
# scheduling and web processes, not job handlers.
#tool_submission_burst_threads = 1
#tool_submission_burst_at = 10
@@ -1,43 +0,0 @@
[main]
# Following options are ignored if using the Galaxy dynamic proxy but
# are useful if mapping a range of ports for environment consumption.
#password_auth = False
#ssl = False
[docker]
# Command to launch docker container. For example `sudo docker` or `docker-lxc`.
# If you need to use a command like `sg` you can do that here, just be sure to
# wrap all of the docker portion in single quotes. E.g. `sg 'docker' 'docker {docker_args}'`
#
# It is recommended that you use command_inject if you need to inject
# additional parameters. This command string is re-used for a `docker inspect`
# command and will likely cause errors if it is extensively modified, past the
# usual group/sudo changes.
#command = docker {docker_args}
# The docker image name that should be started.
image = bgruening/docker-ipython-notebook:15.10.1
# Additional arguments that are passed to the `docker run` command.
#command_inject = --sig-proxy=true -e DEBUG=false
# URL to access the Galaxy API with from the spawn Docker containter, if empty
# this falls back to galaxy.ini's galaxy_infrastructure_url and finally to the
# Docker host of the spawned container if that is also not set.
#galaxy_url =
# The Docker hostname. It can be useful to run the Docker daemon on a different
# host than Galaxy.
#docker_hostname = localhost
# Try to set the tempdirectory to world execute - this can fix the issue
# where 'sudo docker' is not able to mount the folder otherwise.
# "finalize namespace chdir to /import permission denied"
#wx_tempdir = False
# Overwride the IE tempdirectory. This can be useful if you regular tempdir is
# located on an NFS share, which does not work well as Docker volume. In this case
# you can have a shared sshfs share which you can use as temporary directory to
# share data between the IE and Galaxy.
#docker_galaxy_temp_dir = None
@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE interactive_environment SYSTEM "../../interactive_environments.dtd">
<interactive_environment name="IPython">
<data_sources>
<data_source>
<model_class>HistoryDatasetAssociation</model_class>
<test type="isinstance" test_attr="datatype" result_type="datatype">tabular.Tabular</test>
<test type="isinstance" test_attr="datatype" result_type="datatype">data.Text</test>
<to_param param_attr="id">dataset_id</to_param>
</data_source>
</data_sources>
<params>
<param type="dataset" var_name_in_template="hda" required="true">dataset_id</param>
</params>
<entry_point entry_point_type="mako">ipython.mako</entry_point>
</interactive_environment>
@@ -1,85 +0,0 @@
function message_failed_auth(password){
toastr.info(
"Automatic authorization failed. You can manually login with:<br>" + password + "<br> <a href='https://github.com/bgruening/galaxy-ipython/wiki/Automatic-Authorization-Failed' target='_blank'>More details ...</a>",
"Please login manually",
{'closeButton': true, 'timeOut': 100000, 'tapToDismiss': false}
);
}
function message_failed_connection(){
toastr.error(
"Could not connect to IPython Notebook. Please contact your administrator. <a href='https://github.com/bgruening/galaxy-ipython/wiki/Could-not-connect-to-IPython-Notebook' target='_blank'>More details ...</a>",
"Security warning",
{'closeButton': true, 'timeOut': 20000, 'tapToDismiss': true}
);
}
function message_no_auth(){
// No longer a security issue, proxy validates Galaxy session token.
/*
toastr.warning(
"IPython Notebook was lunched without authentication. This is a security issue. <a href='https://github.com/bgruening/galaxy-ipython/wiki/IPython-Notebook-was-lunched-without-authentication' target='_blank'>More details ...</a>",
"Security warning",
{'closeButton': true, 'timeOut': 20000, 'tapToDismiss': false}
);
*/
}
/**
* Load an interactive environment (IE) from a remote URL
* @param {String} password: password used to authenticate to the remote resource
* @param {String} notebook_login_url: URL that should be POSTed to for login
* @param {String} notebook_access_url: the URL embeded in the page and loaded
*
*/
function load_notebook(password, notebook_login_url, notebook_access_url){
$( document ).ready(function() {
// Test notebook_login_url for accessibility, executing the login+load function whenever
// we've successfully connected to the IE.
test_ie_availability(notebook_login_url, function(){
_handle_notebook_loading(password, notebook_login_url, notebook_access_url);
});
});
}
/**
* Must be implemented by IEs
*/
function _handle_notebook_loading(password, notebook_login_url, notebook_access_url){
if ( ie_password_auth ) {
// Make an AJAX POST
$.ajax({
type: "POST",
// to the Login URL
url: notebook_login_url,
// With our password
data: {
'password': password
},
xhrFields: {
withCredentials: true
},
// If that is successful, load the notebook
success: function(){
append_notebook(notebook_access_url);
},
error: function(jqxhr, status, error){
if(ie_password_auth){
// Failure happens due to CORS
message_failed_auth(password);
append_notebook(notebook_access_url);
}else{
message_failed_connection();
// Do we want to try and load the notebook anyway? Just in case?
append_notebook(notebook_access_url);
}
}
});
}
else {
// Not using password auth, just embed it to avoid content-origin issues.
message_no_auth();
append_notebook(notebook_access_url);
}
}
@@ -1,59 +0,0 @@
<%namespace name="ie" file="ie.mako" />
<%
import os
import shutil
import hashlib
# Sets ID and sets up a lot of other variables
ie_request.load_deploy_config()
ie_request.attr.docker_port = 6789
ie_request.attr.import_volume = False
if ie_request.attr.PASSWORD_AUTH:
m = hashlib.sha1()
m.update( ie_request.notebook_pw + ie_request.notebook_pw_salt )
PASSWORD = 'sha1:%s:%s' % (ie_request.notebook_pw_salt, m.hexdigest())
else:
PASSWORD = "none"
## IPython Specific
if hda.datatype.__class__.__name__ == "Ipynb":
DATASET_HID = hda.hid
else:
DATASET_HID = None
# Add all environment variables collected from Galaxy's IE infrastructure
ie_request.launch(env_override={
'notebook_password': PASSWORD,
'dataset_hid': DATASET_HID,
})
## General IE specific
# Access URLs for the notebook from within galaxy.
notebook_access_url = ie_request.url_template('${PROXY_URL}/ipython/notebooks/ipython_galaxy_notebook.ipynb')
notebook_login_url = ie_request.url_template('${PROXY_URL}/ipython/login?next=${PROXY_PREFIX}%2Fipython%2Ftree')
%>
<html>
<head>
${ ie.load_default_js() }
</head>
<body>
<script type="text/javascript">
${ ie.default_javascript_variables() }
var notebook_login_url = '${ notebook_login_url }';
var notebook_access_url = '${ notebook_access_url }';
${ ie.plugin_require_config() }
// Load notebook
requirejs(['interactive_environments', 'plugin/ipython'], function(){
load_notebook(ie_password, notebook_login_url, notebook_access_url);
});
</script>
<div id="main" width="100%" height="100%">
</div>
</body>
</html>
@@ -1,43 +0,0 @@
{
"metadata": {
"name": "",
"signature": "sha256:%s"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Welcome to the interactive Galaxy IPython Notebook."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can access your data via the dataset number. For example, ``handle = open(get(42), 'r')``.",
"To save data, write your data to a file, and then call ``put('filename.txt')``. The dataset will then be available in your galaxy history.",
"Notebooks can be saved to Galaxy by clicking the large green button at the top right of the IPython interface.<br>",
"More help and informations can be found on the project [website](https://github.com/bgruening/galaxy-ipython)."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 1
}
],
"metadata": {}
}
]
}
+167 -47
View File
@@ -1,96 +1,216 @@
id: galaxy_ui
name: Galaxy UI
description: A gentle introduction to the Galaxy User Interface
title_default: "Welcome to Galaxy"
# A tour is made of several steps, each of them beginning with a dash '-'
steps:
# 'title's will be displayed in the header of each step-container
# If you don't specify any title, a default title is used, defined above.
- title: "Welcome to Galaxy"
content: "This short tour will walk you through Galaxy's user interface."
# 'content' is the actual text that is shown to the user
content: "This short tour will guide you through Galaxy's user interface.<br>
You can navigate with your arrow keys and leave the tour at any time point with 'Escape' or the 'End tour' button."
# backdrop is just one of many properties you can attach to one step-container,
# a full reference can be found at http://bootstraptour.com/api/
backdrop: true
- element: ".upload-button"
intro: "Use this button to upload your data."
# 'element' is the JQuery Selector (http://api.jquery.com/category/selectors/) of the element you want to describe
# In this case we want to highlight the Upload button with the `.upload-button` selector
- title: "Upload your data"
element: ".upload-button"
intro: "Galaxy supports many ways to get in your data.<br>
Use this button to upload your data."
# position of the text box relative to the selected element
position: "right"
# You can trigger click() events on arbitrary elements before (preclick) or after (postclick) the element is shown
postclick:
- ".upload-button"
- element: "button#btn-local"
intro: "Upload data from your computer."
- title: "Upload your data"
element: "button#btn-local"
intro: "You can upload data from your computer."
position: "top"
postclick:
- "button#btn-new"
- element: "button#btn-new"
intro: "Copy and Paste data or include URLs."
- title: "Upload your data"
element: "button#btn-new"
intro: "Copy and paste data directly into Galaxy or include URLs that lead to your data"
position: "top"
preclick:
- ".upload-button"
- element: "textarea#text-content"
intro: "Insert data into Galaxy."
- title: "Insert URLs"
element: "textarea#text-content"
intro: "URLs separated by a line break are automatically downloaded by Galaxy."
position: "top"
textinsert: |
https://raw.githubusercontent.com/arq5x/bedtools/master/test/merge/a.full.bed
https://raw.githubusercontent.com/arq5x/bedtools/master/test/merge/a.full.bed
https://raw.githubusercontent.com/arq5x/bedtools/master/test/merge/a.full.bed
https://raw.githubusercontent.com/bgruening/galaxytools/adf077b912ddebd97b07b947b855cdd2862ed8ef/tools/augustus/test-data/human_augustus.fa
https://raw.githubusercontent.com/bgruening/galaxytools/adf077b912ddebd97b07b947b855cdd2862ed8ef/tools/sailfish/test-data/reads_2.fastq
https://raw.githubusercontent.com/bgruening/galaxytools/adf077b912ddebd97b07b947b855cdd2862ed8ef/tools/statistics/test-data/anderson.tabular
- element: "button#btn-start"
- title: "Start the upload"
element: "button#btn-start"
intro: "Upload the data into your Galaxy history."
position: "bottom"
position: "top"
postclick:
- "button#btn-start"
- element: "button#btn-close"
intro: "Hit the close button in upload."
position: "bottom"
- title: "Close upload/download manager"
element: "button#btn-close"
intro: "Close the upload manager with this button or with a click outside of the manager window."
position: "top"
postclick:
- "#btn-close"
- title: "Tools"
element: "#left"
intro: "This is your ToolBox. All tools available in your Galaxy instance you can find here."
position: "right"
- element: 'a[href$="tool_runner?tool_id=Filter1"]'
- title: "Tool search bar"
element: '#tool-search-query'
intro: "You can search for tools by keywords."
position: "right"
textinsert: 'filter'
- title: "Tool categories"
element: '#title_filter > a'
intro: "Tools are grouped into categories to make them easier to find."
position: "right"
preclick:
- 'a[href$="tool_runner?tool_id=Filter1"]'
postclick:
- "#title_filter a"
- element: '#center-panel'
intro: "This is your Filter tool."
- title: "Select a tool"
element: 'a[href$="tool_runner?tool_id=Filter1"]'
intro: "Select and load a tool for your analysis by clicking the underlined link."
position: "right"
preclick:
- '#center-panel'
postclick:
- 'a[href$="tool_runner?tool_id=Filter1"]'
- element: '#uid-0'
intro: "Your tool parameters."
- title: "Filter Tool"
element: '#center-panel'
intro: "Your tool is loaded into the main Galaxy page and ready for use."
position: "right"
#backdropContainer: 'background'
#backdrop: true
- title: "Tool parameters"
element: '#uid-0'
intro: "Here you can choose your tool parameters. Select your input dataset from your history and specify parameters for your analysis."
position: "right"
- element: 'div.toolHelp'
intro: "Your tool parameters."
- title: "Tool help"
element: 'div.ui-form-help'
intro: "Every Galaxy tool has a help section with detailed information about the tool and its parameters.
Have a look and study your tool in depth by reading it."
position: "top"
- title: "Run your tool"
element: '#execute'
intro: "Click on 'Execute' to run your tool and send it to the compute cluster.
Don't be afraid to test different settings in parallel. Galaxy can handle multiple runs of the same tool."
position: "right"
- element: '#execute'
intro: "Send your tool to the Compute Cluster."
position: "right"
preclick:
postclick:
- '#execute'
- element: "#right"
intro: "This is your history! All anylysis steps will be recorded and can be redone at any time."
- title: "History"
element: "#right"
intro: "This is your Galaxy history! All analysis steps with results of the tools and their parameters will be recorded here and can be redone at any time.<br>
A running tool is shown in yellow and if your calculation is done, it turns green. If your dataset is
grey this means you are queued and need to wait until your tool can be started. If your dataset turns into red, an error has occurred. Please report the bug to the Galaxy team with the bug report button."
position: "left"
- element: "#masthead"
intro: "Your top panel will give you access to a lot of useful things."
- title: "Rename history"
element: "#current-history-panel > div.controls > div.title > div"
intro: "Name your history here and press enter."
position: "left"
preclick:
- "#current-history-panel > div.controls > div.title > div"
- title: "View dataset"
element: ".fa-eye:eq(0)"
intro: "View your dataset by clicking the eye button."
position: "left"
#preclick:
# - ".fa-eye:eq(0)"
- title: "Rename dataset"
element: ".fa-pencil:eq(0)"
intro: "Rename your dataset by clicking the pencil button."
position: "left"
#preclick:
# - ".fa-pencil:eq(0)"
- title: "Remove dataset"
element: ".fa-times:eq(0)"
intro: "Delete your dataset by clicking the x-button."
position: "left"
#postclick:
# - ".fa-times:eq(0)"
- title: "Dataset information"
element: "div.title-bar.clear:eq(0)"
intro: "Clicking on your dataset provides you with more information regarding your dataset (e.g. filetype or size)."
position: "left"
preclick:
- "div.title-bar.clear:eq(0)"
- title: "Re-run tool"
element: ".fa-refresh:eq(1)"
intro: "By clicking the reload button, you can re-run your tool again (e.g. with different parameters or on another dataset)."
position: "left"
preclick:
- ".fa-refresh:eq(1)"
- title: "Panel collaps"
element: "#left > div.unified-panel-footer > div.panel-collapse.left"
intro: "To extend the view for your main Galaxy page in the middle, you can collapse the tool panel on the left hand side. Clicking the panel arrow on the right hand side, collapses the history."
position: "top"
postclick:
- "#left > div.unified-panel-footer > div.panel-collapse.left"
- title: 'Top panel'
element: "#masthead"
intro: "The top panel will give you access to a lot of useful things."
position: "bottom"
- element: "#analysis"
intro: "Start your <b>analysis</b> from here."
- title: 'Analyze data'
element: "#analysis"
intro: "This is the current view. Start your <b>analysis</b> from here."
position: "bottom"
- element: "#workflow"
intro: "Manage, Import, Export and Share your <b>Workflows</b>."
- title: 'Workflow'
element: "#workflow"
intro: "Create, manage, import, export and share your <b>Workflows</b>."
position: "bottom"
- element: "#shared"
intro: "Get access to all <b>Workflows, <b>Histories</b>, <b>Pages</b>, <b>Visualizations</b> and you <b>Data Library</b> that are shared with you."
- title: 'Shared data'
element: "#shared"
intro: "Get access to all <b>Workflows</b>, <b>Histories</b>, <b>Pages</b>, <b>Visualizations</b> and your <b>Data Library</b> that are shared with you."
position: "bottom"
- element: "#visualization"
intro: "Want to start visualize your data in Trackster? Start here!"
- title: 'Visualization'
element: "#visualization"
intro: "Do you want to start to visualize your data in Trackster? Start here!<br>Galaxy offers a lot more visualizations!"
position: "bottom"
- element: "#help"
intro: "Here you get more help from the Galaxy <b>Community</b> with Videos and a QA board."
- title: 'Help'
element: "#help"
intro: "Here you get more help from the Galaxy <b>Community</b> with Videos, a QA board and more tours."
position: "bottom"
- element: "#user"
- title: 'User Preferences'
element: "#user"
intro: "Login and start your analysis!"
position: "bottom"
- title: 'Scratchbook'
element: "#enable-scratchbook"
intro: "Scratchbook offers you multiple visualizations next to each other. Have a look at our Scratchbook tour to learn more about it."
position: "bottom"
- title: "Enjoy Galaxy"
intro: "Thanks for taking this tour! Happy research with Galaxy!"
+45 -40
View File
@@ -1,90 +1,95 @@
name: History Introduction
description: A detailed introduction to the <b>Galaxy History</b>
description: A detailed introduction to the Galaxy History
title_default: "Galaxy History Introduction"
steps:
- content: "This short tour will walk you through <b>Galaxy's History</b> and datasets."
- content: "This short tour will guide you through <b>Galaxy's History</b> and datasets."
- element: ".upload-button"
- title: "Upload data"
element: ".upload-button"
intro: |
At first we get some data into your Galaxy and into your History.<br>
Use this button to upload your data.
"At first we upload some data into your Galaxy history.<br>
Use this button to upload your data."
position: "right"
postclick:
- ".upload-button"
- element: "button#btn-local"
intro: "Upload data from your computer."
- title: "Upload your data"
element: "button#btn-local"
intro: "You can upload data from your computer."
position: "top"
postclick:
- "button#btn-new"
- element: "button#btn-new"
intro: "Copy and Paste data or include URLs to data which will be fetched automatically by Galaxy."
- title: "Upload your data"
element: "button#btn-new"
intro: "Copy and paste data directly into Galaxy or include URLs that lead to your data."
position: "top"
- element: "textarea#text-content"
intro: "We insert some URLs to get example data in Galaxy."
- title: "Insert URLs"
element: "textarea#text-content"
intro: "URLs separated by a line break are automatically downloaded by Galaxy."
position: "bottom"
textinsert: |
file://home/bag/Bilder/Python-Programming-in-Galaxy.png
file://home/bag/Downloads/a.tab
https://wiki.galaxyproject.org/Images/GalaxyLogo?action=AttachFile&do=get&target=galaxy_project_logo.jpg
https://raw.githubusercontent.com/bgruening/galaxytools/adf077b912ddebd97b07b947b855cdd2862ed8ef/tools/statistics/test-data/anderson.tabular
- element: "button#btn-start"
- title: "Upload your data"
element: "button#btn-start"
intro: "Upload the data into your Galaxy <b>History</b>."
position: "bottom"
position: "top"
postclick:
- "button#btn-start"
- "button#btn-close"
- element: "#right"
intro: "This is your history! All anylysis steps will be recorded and can be redone at any time."
- title: "History"
element: "#right"
intro: "This is your history! All analysis steps will be recorded and can be redone at any time."
position: "left"
- element: "#dataset-2d9035b3fc152403"
- title: "Dataset information"
element: "div.title-bar.clear:eq(0)"
intro: "This is one of your uploaded datasets. You can get more informations and options like different visualizations by clicking on it."
position: "left"
postclick:
- "#dataset-2d9035b3fc152403 > div.title-bar.clear > div > span.name"
- "div.title-bar.clear:eq(0)"
- element: "#dataset-2d9035b3fc152403 > div.details > div.summary > div.datatype > label"
title: "Metadata"
intro: "Galaxy has assigned a datatype too your dataset during upload, which you can see here."
- title: "Metadata"
element: "#current-history-panel > div.list-items > div:nth-child(1) > div.details > div.summary > div.datatype > label"
intro: "Galaxy has assigned a datatype to your dataset during upload, which you can see here."
position: "left"
- element: "#dataset-2d9035b3fc152403 > div.details > div.actions.clear > div.left > a.download-btn.icon-btn"
- element: "#current-history-panel > div.list-items > div:nth-child(1) > div.details > div.actions.clear > div.left > a.download-btn.icon-btn"
title: "Download your dataset"
intro: "You can download every dataset by using the floppy disc symbol."
position: "left"
- element: "#dataset-2d9035b3fc152403 > div.details > div.actions.clear > div.left > a.icon-btn.params-btn"
- element: "#current-history-panel > div.list-items > div:nth-child(1) > div.details > div.actions.clear > div.left > a.icon-btn.params-btn"
title: "Even more information"
intro: "Get an overview of all metadata associated with your dataset by using the Information symbol."
position: "left"
preclick:
- "#dataset-2d9035b3fc152403 > div.details > div.actions.clear > div.left > a.icon-btn.params-btn"
- "#current-history-panel > div.list-items > div:nth-child(1) > div.details > div.actions.clear > div.left > a.icon-btn.params-btn"
- element: "#dataset-2d9035b3fc152403 > div.primary-actions > a.icon-btn.display-btn"
- element: "#current-history-panel > div.list-items > div:nth-child(1) > div.primary-actions > a.icon-btn.display-btn"
title: "Inspect your data"
intro: "The eye symbol can be used to look at your data."
position: "left"
preclick:
- "#dataset-2d9035b3fc152403 > div.primary-actions > a.icon-btn.display-btn"
- "#current-history-panel > div.list-items > div:nth-child(1) > div.primary-actions > a.icon-btn.display-btn"
- element: "#dataset-2d9035b3fc152403 > div.primary-actions > a.icon-btn.edit-btn"
- element: "#current-history-panel > div.list-items > div:nth-child(1) > div.primary-actions > a.icon-btn.edit-btn"
title: "Edit metadata"
intro: "With the pencil button you can edit metadata attributes of your dataset, like the associated filetype or the dataset name."
position: "left"
preclick:
- "#dataset-2d9035b3fc152403 > div.primary-actions > a.icon-btn.edit-btn"
- "#current-history-panel > div.list-items > div:nth-child(1) > div.primary-actions > a.icon-btn.edit-btn"
- element: "#dataset-2d9035b3fc152403 > div.primary-actions > a.icon-btn.delete-btn"
- element: "#current-history-panel > div.list-items > div:nth-child(1) > div.primary-actions > a.icon-btn.delete-btn"
title: "Remove datasets"
intro: "You can remove a dataset from the history with the cross symbol."
position: "left"
postclick:
- "#dataset-2d9035b3fc152403 > div.primary-actions > a.icon-btn.delete-btn"
- "#current-history-panel > div.list-items > div:nth-child(1) > div.primary-actions > a.icon-btn.delete-btn"
- element: "#current-history-panel > div.controls > div.subtitle > a"
title: "Include all deleted datasets"
@@ -93,14 +98,14 @@ steps:
postclick:
- "#current-history-panel > div.controls > div.subtitle > a"
- element: "#dataset-2d9035b3fc152403 > div.warnings > div > a"
- element: "#current-history-panel > div.list-items > div:nth-child(1) > div.warnings > div > a"
title: "Undeleting a dataset"
intro: |
"Galaxy datasets are only marked as deleled and can be recovered by exeecuting this link.
Please note that datasets marked as deleted can be purged by your administrator at any time. :beer: "
Galaxy datasets are only marked as deleled and can be recovered by clicking this link.
Please note that datasets marked as deleted can be purged by your administrator at any time.
position: "bottom"
postclick:
- "#dataset-2d9035b3fc152403 > div.warnings > div > a"
- "#current-history-panel > div.list-items > div:nth-child(1) > div.warnings > div > a"
- element: "#current-history-panel > div.controls > div.subtitle > a"
title: "Hiding all deleted datasets"
@@ -111,7 +116,7 @@ steps:
- element: "#current-history-panel > div.controls > div.title > div"
title: "Change your History name"
intro: "You can change the history name clicking on the title"
intro: "You can change the history name clicking on the title."
position: "bottom"
preclick:
- "#current-history-panel > div.controls > div.title > div"
@@ -122,11 +127,11 @@ steps:
position: "left"
textinsert: "WWFSMD"
preclick:
- "#current-history-panel > div.controls > div.search > div > input"
- "#current-history-panel > div.controls > div.search > div > input"
- element: "#history-options-button"
title: "History Options"
intro: "In the History menue you will find a lot more usful History options."
intro: "In the History menu you will find a lot more useful History options."
position: "left"
postclick:
- "#history-options-button"
@@ -0,0 +1,77 @@
name: Scratchbook - Introduction
title_default: "Scratchbook Introduction"
description: "An introduction on how to display multiple datasets and visualizations next to each other."
steps:
- content: "This short tour will walk you through <b>Galaxy's Scratchbook</b> feature"
- element: "#tool-panel-upload-button"
intro: "Before using the Scratchbook, we will upload some tabular data."
position: "right"
postclick:
- "#tool-panel-upload-button"
- element: "#btn-new"
intro: "We will be using the paste feature to create a new dataset."
position: "top"
postclick:
- "#btn-new"
- element: ".text-content:first"
intro: "...and paste content into the text area field."
position: "top"
textinsert: |
1 0.039 0.000
2 0.455 0.000
3 0.472 0.000
4 0.030 0.000
5 0.000 0.000
6 0.000 0.000
7 0.000 0.000
8 0.000 0.000
- element: ".upload-settings:first"
intro: "Now, we may further configure the upload content."
position: "right"
postclick:
- ".upload-settings:first"
- element: ".upload-space_to_tab:first"
intro: "...by specifying that all spaces in our table should be converted into tabs."
position: "left"
postclick:
- ".upload-space_to_tab:first"
- element: "#btn-start"
intro: "Upload the data into your Galaxy history."
position: "top"
postclick:
- "#btn-start"
- element: "#btn-close"
intro: "Hit the close button to close the upload dialog."
position: "top"
postclick:
- "#btn-close"
- element: "#enable-scratchbook > .dropdown > .dropdown-toggle"
intro: "Clicking this button will enable Galaxy's Scratchbook mode."
position: "right"
postclick:
- "#enable-scratchbook > .dropdown > .dropdown-toggle"
- element: "#right"
intro: "This is your history. It contains all datasets you are currently working with including our uploaded table."
position: "left"
- element: ".fa-eye:first"
intro: "Clicking the eye-icon usually displays a dataset in the center panel."
position: "left"
postclick:
- ".fa-eye:first"
- element: "#frame-0"
intro: "However while in Scratchbook mode, the dataset will be shown as resizable window."
position: "right"
- title: "Done."
intro: "You have created a Scratchbook view. Click on the background and select more datasets."
File diff suppressed because one or more lines are too long
+24 -2
View File
@@ -169,6 +169,7 @@ class Configuration( object ):
self.job_queue_cleanup_interval = int( kwargs.get("job_queue_cleanup_interval", "5") )
self.cluster_files_directory = os.path.abspath( kwargs.get( "cluster_files_directory", "database/pbs" ) )
self.job_working_directory = resolve_path( kwargs.get( "job_working_directory", "database/job_working_directory" ), self.root )
self.default_job_shell = kwargs.get( "default_job_shell", "/bin/sh" )
self.cleanup_job = kwargs.get( "cleanup_job", "always" )
self.container_image_cache_path = self.resolve_path( kwargs.get( "container_image_cache_path", "database/container_images" ) )
self.outputs_to_working_directory = string_as_bool( kwargs.get( 'outputs_to_working_directory', False ) )
@@ -258,8 +259,11 @@ class Configuration( object ):
self.log_events = string_as_bool( kwargs.get( 'log_events', 'False' ) )
self.sanitize_all_html = string_as_bool( kwargs.get( 'sanitize_all_html', True ) )
self.sanitize_whitelist_file = resolve_path( kwargs.get( 'sanitize_whitelist_file', "config/sanitize_whitelist.txt" ), self.root )
self.reload_sanitize_whitelist()
self.sanitize_whitelist = []
if kwargs.get('sanitize_whitelist_file', None) is not None:
self.reload_sanitize_whitelist()
self.serve_xss_vulnerable_mimetypes = string_as_bool( kwargs.get( 'serve_xss_vulnerable_mimetypes', False ) )
self.allowed_origin_hostnames = self._parse_allowed_origin_hostnames( kwargs )
self.trust_ipython_notebook_conversion = string_as_bool( kwargs.get( 'trust_ipython_notebook_conversion', False ) )
self.enable_old_display_applications = string_as_bool( kwargs.get( "enable_old_display_applications", "True" ) )
self.brand = kwargs.get( 'brand', None )
@@ -480,7 +484,7 @@ class Configuration( object ):
if not line.startswith("#"):
self.sanitize_whitelist.append(line.strip())
except IOError:
log.warning("Sanitize log file %s does not exist, continuing with no tools whitelisted.")
log.warning("Sanitize log file %s does not exist, continuing with no tools whitelisted.", self.sanitize_whitelist_file)
def __parse_config_file_options( self, kwargs ):
"""
@@ -669,6 +673,24 @@ class Configuration( object ):
port = None
return port
def _parse_allowed_origin_hostnames( self, kwargs ):
"""
Parse a CSV list of strings/regexp of hostnames that should be allowed
to use CORS and will be sent the Access-Control-Allow-Origin header.
"""
allowed_origin_hostnames = listify( kwargs.get( 'allowed_origin_hostnames', None ) )
if not allowed_origin_hostnames:
return None
def parse( string ):
# a string enclosed in fwd slashes will be parsed as a regexp: e.g. /<some val>/
if string[0] == '/' and string[-1] == '/':
string = string[1:-1]
return re.compile( string, flags=( re.UNICODE | re.LOCALE ) )
return string
return [ parse( v ) for v in allowed_origin_hostnames if v ]
def get_database_engine_options( kwargs, model_prefix='' ):
"""
+1
View File
@@ -81,6 +81,7 @@ class TabularData( data.Text ):
# For now, default to the old behavior, ugly as it is. Remove this after adding 'matrix'.
max_peek_size = 1000000 # 1 MB
if os.stat( dataset.file_name ).st_size < max_peek_size:
self._clean_and_set_mime_type( trans, dataset.get_mime() )
return open( dataset.file_name )
else:
trans.response.set_content_type( "text/html" )
@@ -0,0 +1,170 @@
# packages with C extensions
bx-python==0.7.3 --hash:sha256=0a0fd962edd0f9afdf5d7ccbdf46dc220a0cb652073a93411dd6f7f649f07d91 \
--hash:sha256=46dc3042c7e475363830fa92d4a613ae10b58db7f114ff8193d2ee0bc3c4607e \
--hash:sha256=b93a9378a5d0e29ea8a13e026c170f48bf1f8316a39c342b1eb54f557b4fb3c4 \
--hash:sha256=d06c7bf0ae7f019521aeb5ffe4df48bb5fdd4d75d7ad00e0059b997c4f13ca3a \
--hash:sha256=05d0ab8fd13319d5ef9edb246dc6805640ea7574bb885a0b8607474271ac5793 \
--hash:sha256=5a026869227a6464eba23835765a36ffc2910f7af51b81f672a97c0d005e04a3 \
--hash:sha256=85be43a6b94f0c841d9954f820133db35067854504c1de87dd0089bb06eca18d \
--hash:sha256=d085824eb33c54d333b99dca29b49890457a8263f431b54b17ae3052be191d2b \
--hash:sha256=41bcf85b9be9f61ba7c7bae48c5a5ae3251868a1b25f02b6eb93b29bcabfd00c \
--hash:sha256=c9b71aee26ee85fbcbb3060109d79531bfa8991f4924bdcfed63d909a5937290
MarkupSafe==0.23 --hash:sha256=3a79d9650b7e79943be51a045c7c39a77ebbe9a337e8af51a5575e39332dce87 \
--hash:sha256=e0a4155493d1cfa72e985dbe1660a44d64a173282801563956e061b24371266a \
--hash:sha256=147013ed157f1423a0d0047043c6bbccbef31a52d82e2a10dfc3c6de9392765c \
--hash:sha256=d25d14cb01284aed33690b85bfde8de206ffcfdc52351588bcf17480839bef6f \
--hash:sha256=29958f81958e0dd9f5dd36d52f2ac549d875dde3559b783578118c9005693852 \
--hash:sha256=287a1c6b0d2a08cb76be6e584bf119649405f015598cf8b78d4a592cc80700a0 \
--hash:sha256=973cadf7b9907f9c81d9b898817d6a485b37325176befec2389fa2ced4c61a51 \
--hash:sha256=a365fd3468c86741aec5901f4b07990aaa0b458fb79e9f3557378a63e6d627e9 \
--hash:sha256=ba7af558b18ba9c05bb0d36f22a5ea65ee11ba44a6cf8a2950f2f80c08260e11 \
--hash:sha256=51bf7f077938c64dd00de6732996ccee8ceba2206c69acfb07f66430ca76372f
PyYAML==3.11 --hash:sha256=2912c1fb56c316461d003a8b8f1f41e1ed8387b2e47a4523f8a4eec8aa85e241 \
--hash:sha256=f4437443dc014c04ceee8cc94d4165f01ba23643991fd2c6b919f26cf9997474 \
--hash:sha256=b62cde962d41377c175831fa3fd6ac41585d2e2111ca4c45a6ee80a832457e92 \
--hash:sha256=aad37be9d524ba2dba9a3114b620b2800b40e67e455c9741a5cb81a6a0e882f6 \
--hash:sha256=03e0f4ac96599c1d687b080f1610ab0469e8785bb48cfdf860f2076a08ea6406 \
--hash:sha256=7dc97b5b1b920f6bbe0e47cfa6ff112f6eede35924a63354f80d672354f25160 \
--hash:sha256=ceb5dccec2045d4a864c6e808b397b10830476c44bdc64b80c18bf29e481ba07 \
--hash:sha256=9b184a4a7d3d383b39cb73429d3798370facaee4263465b575f243c7ede3f9c3 \
--hash:sha256=f90314e2ed46ea2da980aff88b91c3cc8ce93edd4658011dd462a8f28399533b \
--hash:sha256=80936dca10b611cd54ca52939aac938d59653830a6a6265bef5d11896de8e249
SQLAlchemy==1.0.8 --hash:sha256=3c357f36c141205cea2b5ec4c4e9885602452fea06428d6c20596c66c9a43243 \
--hash:sha256=17fad7f37f902dbec37ca2777af3021f9a4ed31079d64f7f888e7b29517240a3 \
--hash:sha256=e177904a384b9bc68914afb32a6ed2cc73ed7787444e3e1fdf85e3b9cfe5f847 \
--hash:sha256=91ed10baf56b6e29665f2b9fcb0c690afc6cc2c2e8e19c7f92b58092a4002e14 \
--hash:sha256=f5d6156d1d7865cd23b76ddad3f53ec07a3009a2cd8082a829cd1f24b366db5c \
--hash:sha256=3c3f3baf07f868c1c3f86d63dc2efa4455e95d76745f1af561f1ccf0fd9e8c81 \
--hash:sha256=a9fb8061aa767ca2ad22983a11e074ac231f44a56709721c60cc1992f2a92350 \
--hash:sha256=884b522d2d067cffd103f4e1a5342c678803cd6903da24a3f757b57b00eb188b \
--hash:sha256=d5dde66c1603853aebbfbbd74d79c60678f7d98c17abce4be4ebbb697dfd7265 \
--hash:sha256=42346d5e91c5e0a5a975352d8af3cfd8b2dad602dd07ec41b6b848ac5205cf5b
# Mercurial >= 3.5 changed the bundle format, which breaks hg push of TS repositories
mercurial==3.4.2 --hash:sha256=7851864b03929c09e07670bf8ab7d59f3529650c935a70d09fb6ce7f6a84e2a5 \
--hash:sha256=c23b02b4c32edc2d0799221a9d35abd916fb8a1acd1c07d64c16a235ef677b9e \
--hash:sha256=ca72ddfaea681a070b62edcb8e41d58bd24a2b04f73e66658565d189a76f3819 \
--hash:sha256=fdad4496f3d7f3e7eced771fa46e21c074989f8437ddf3e0ff6c0eee964e4c29 \
--hash:sha256=964a10ec1114dbee3696134bafed676f66038759b73de8593f92616f0e53f371 \
--hash:sha256=c6ca6fbe56a8919dfc521e80ab781ab565760d87f4a6170e788d67eb6d69d30f \
--hash:sha256=69540318fa9f7a3a0428647003d4f1fa8865d29648e73999b921cae039145ce9 \
--hash:sha256=b3de0ee851cf8750f53102437c9a04c7217a8c6f7411030ab3bb5534885f3315 \
--hash:sha256=46f67af52c7b1aed68b67daa33c26eafc0fb1d371954d3266fce739446cfcb1d \
--hash:sha256=000afb932f0ae45c365cbc0457044e8800811fdad7eee9332b6403b83423ab0a
numpy==1.9.2 --hash:sha256=931ce6fd1180a10d58a925b614775706c05de35bca5805e705e1da17e1326862 \
--hash:sha256=2340c4b72fdab79ac0fc04bb6629b26eeb93d10f4945b6b1f07d9be8663cab84 \
--hash:sha256=83fe34ff67653a639c57cfd04a0d48dda5913250fd95c8466af1d8416b58af59 \
--hash:sha256=aeb182d95ddb2dfd81683907be193cfc11c4d0ba744faf457013499fa14a131e \
--hash:sha256=d6f1eec7ae250892a2b142af406e43760042badae8e2f168136eace5dd9f05c3 \
--hash:sha256=0b0883cac08e3c0999159ba7f34c9b94d26d7d1a2be4017b792145d722646fb7 \
--hash:sha256=a124d11b1bec5c517d60ad9414564b5af0828421112d2a00771d22715eab1c3c \
--hash:sha256=fabc2f76266de7396e2752baabf287cdd0cc2ed23c1f36ca3c3e8b094e86b87c \
--hash:sha256=f83a667d3a38643b3bf6361904cd6c4f2a18d1420c2204c7f269cd36b730c404 \
--hash:sha256=dab9bd8c867403340b370ea383c8eda3dc984dd5efc91904a5695e00b1762fc9
pycrypto==2.6.1 --hash:sha256=44c20785a1057b8d5e190d6a1847f7c62a8180b9b27a3aca7c3ec920bfb8e7b7 \
--hash:sha256=785ba61251cda6e574e0affc4412c346ef615455b81287fe0d6a2e1c5aed5172 \
--hash:sha256=5ec40d95520a665843915763c8cbbf40457330bd7ebf2a55ffea1b10a519d12b \
--hash:sha256=2cb43f0b293a18e6d5818287150994cf6083b1a9cdff65c19d1150a34aa813bc \
--hash:sha256=d48e46f4ccd5c21f3e01bbdbd8e7a86443fc7abdf3f93829c3d04ed684ec22c5 \
--hash:sha256=30312bd39f45c91f287f3e6e54c40988d30b1be9a9f332585e3cc00ee5f91554 \
--hash:sha256=d129d6d3441efecf2bc7e6b36cb35e99642248d72dbf59b992e6940b9359dabc \
--hash:sha256=8884b92835a1c0c763099981d19c990fdc3ae2b7011eb93b1f96e34a346b2d2f \
--hash:sha256=7e7e9abc0ae522ae86772d98b7144e0d2ef7791d124936f283680f84fe8cce6c \
--hash:sha256=61d3b42eaf89108b8a24c3736fb770f768efb89b1efaf0825efb5c316f0bffdc
# Install python_lzo if you want to support indexed access to lzo-compressed
# locally cached maf files via bx-python
#python_lzo==1.8 --hash:sha256=638b38bc1d83561a9807365676f5b2ba6f18491753a673e6a9c5913bd542fe1a \
# --hash:sha256=cda3d6c27e69a9d04eb96db6b4b96fbe7facdd11dc2b9a82fe3c65b84b40fe44 \
# --hash:sha256=7ededfdb65b4eb282a7cc1600c6f5b4f483b39a70b3460c2f4651ee8fc431f77 \
# --hash:sha256=86a61008a8ab5f8ca973bd7e7b1d031c89637257dcf7215bff1913f17d3c596f \
# --hash:sha256=1d6af33e40383dba0c3ee26eee3e501e805fe42537dd0096788190bbc8fd7aae \
# --hash:sha256=6d08ad35322a5969dfd8ef5af7ff4cdf625d6a7bfa8e915b77f5935f58e1c7b1 \
# --hash:sha256=99b7e0c186c5b84d80de6e7b70359b6fc456c02bd2b31fc598140fbc6618d651 \
# --hash:sha256=be967c38c4e33f66823d10fb5efca42a0a23269459ce41239c173ccc114b603e \
# --hash:sha256=a34d7431e30c6d61c22b92d51224ea34d68be51aa42ec95a053b7f19be3fef0d \
# --hash:sha256=be76281c1c7f24d44e3415787d2a05688f6bbda2dc9bba92155ae3ca0d6716e7
# pure Python packages
Paste==2.0.2 --hash:sha256=4e7bb2d8cbdc47ab46e4af0cb61d2af91fccc620a08415d9c4da9e499f0455fd
PasteDeploy==1.5.2 --hash:sha256=3922127d3acc6e274a800978b9293c874b3ef4ac2eb8bf485e2c85b22d1f260a
docutils==0.12 --hash:sha256=732dfc2d706ea390c264bc69110d3d6c7c3a520628a052ccc5998466f95d5c29
wchartype==0.1 --hash:sha256=2932471fe3a4e5cac4539c1b49bbc2bbd24ec3f00532c7f27c80b7756fdc177d
repoze.lru==0.6 --hash:sha256=731cc0b0a184c9fd270a4f29d9635099bb0398823e9a1a39bf4f488d1ead57b3
Routes==2.2 --hash:sha256=1d61dc9f1bbd86504de221568743133fbdfeb70f11cee4222cef72aa108e834c
WebOb==1.4.1 --hash:sha256=dc3c45ac0b56a3c65f47f1da6c23760dfe0139e8a84caaf1cfc9276b3e10875a
WebHelpers==1.3 --hash:sha256=8969ec3fb851872096067a805d512c3bed1952e6fc66f1ef1d1c6a7470937688
Mako==1.0.2 --hash:sha256=d3f372cbc2e7de080b5f7056d160f3ac8279353a2ea8f1ef8fd5b0cf0a6a3b17
pytz==2015.4 --hash:sha256=3bec70eef120ad0bf9143e59bbf36715ec1232fb0550ae2b8aa6c107aacfa6f2
Babel==2.0 --hash:sha256=aa725635ef189f77b6b0579efe1e91602d7cf63a31f6dd719a88ee53642bb5ab
Beaker==1.7.0 --hash:sha256=334427853ac291e4ecd1e03addb48e231681ab9b6c2bc793c0f0fb98024b70b1
# Cheetah and dependencies
Cheetah==2.4.4 --hash:sha256=24cf67789b7a9f1e0a55cba266b6aad16e97aaf25810fd6f2f7e7b36005c1161 \
--hash:sha256=30c6dd32c066f483462cebc7fc37feb454d6a3d35e8b599da17624b2541761ab \
--hash:sha256=fcbff7d96509419cbcefa231d6fee4aca98d2f04f8339848c19da3e82aebcf27 \
--hash:sha256=5c758550b8170b01e016b75ec05dbd2c32b56513d6e1ef9177c5290f4e166ad2 \
--hash:sha256=6aaeef7f742df6a23c4132bb33000196053b661a150fdd98311f25f09d3730c1 \
--hash:sha256=469e7ddc2f4a9b147b2b5c258fc9f97cee9842790c1849b941bae165b390da92 \
--hash:sha256=75f05eda3b16c621b5b570f9c5b317f6ea94b01296b9e1ef2583560d153578bd \
--hash:sha256=6da983e9d189a3c389e98506871ff836a83df1792dba5e4a684d27d948402d7a \
--hash:sha256=55b0c2696eb321415a9eca86303e3c359dee550d7f6fc719bc960f23422d2290 \
--hash:sha256=2caf567b6cdd54f806ce12d98302e380d4bbbed8990663f9bce52d69358fc488
Markdown==2.6.3 --hash:sha256=59417f5eb3dace08309d81e48fc903217d12d66677f367674b22c317b0f04284
# BioBlend and dependencies
bioblend==0.6.1 --hash:sha256=f5eea1f6c31264ef7bfab8c70deac2b9229a10e5c56508a6542f5643ad9e2a5b
boto==2.38.0 --hash:sha256=1760584368da0c3861dbed448dcb439334ce831044262a5ca5188167f8bba585
requests==2.8.1 --hash:sha256=70e285122c97b1d104824482cb929246b2b8a2b9858897c4fab3acec83f1e03c
requests-toolbelt==0.4.0 --hash:sha256=94694e32845b84ed2186fdf56219b949582ebd08dc3abc55c0549958f2029643
# kombu and dependencies
kombu==3.0.30 --hash:sha256=562010f0deb1f04e3abd154b0ef5e246d606b54cb2c5f29e8c4651b354d0b082 \
--hash:sha256=5baff23a2b2d78eecb7c97700ea359ab80744c719e311fb446513d7b72ddbc96
amqp==1.4.8 --hash:sha256=c7874d845c9bdffbf754ce84f105a1b8c7a6cffb61f362ac67591536ba8c0c1a \
--hash:sha256=caada1c29d5e73e13ed8706442ee0fbb1440de9b6fca4df12fc8ff59dd61f6f6
anyjson==0.3.3 --hash:sha256=2c84f23be20e3c465151a55917b8e38a04c579394057e232c16fb5ca0c6ae108
# sqlalchemy-migrate and dependencies
sqlalchemy-migrate==0.10.0 --hash:sha256=2aaa4e7070c8447d564f1c173937c2c5a45f889eb31a0fc80add5fc175c45a5e
decorator==4.0.2 --hash:sha256=d8c3f7e18efba558084648d6dd6c6b0850e6f5c08c392975ae196c4b4eb7be2a
Tempita==0.5.3dev --hash:sha256=df0c6513e565b213733b3f8bf7bcca75998f166042692e1712e3fe36568db234
sqlparse==0.1.16 --hash:sha256=221d383f1236f9c05aadd2c4edf4274144279ad06821d7d9bf5a70751157f75d
pbr==1.8.0 --hash:sha256=355a0c2ba71120dce1c522387e494c60eb4f44fa9d03067cb9816187e6e803e9
# six is also a Pulsar client dep
six==1.9.0 --hash:sha256=cf806ab65d5e16561df30c2cea2fb2cf3e6aa82e48f22036dff177e20f61e188
Parsley==1.3 --hash:sha256=32fd648334146e4005dae41d559d32edfff9f3d5f503f8b5d233dbfe3a15a28b
nose==1.3.7 --hash:sha256=f36054c5786e84ff6b131f3249a3cce82787f1a930ab053287c0edaa9f840d0f
SVGFig==1.1.6 --hash:sha256=300cf4b37b4773498d4ea96c703cdb5f09215978b02828dadb786fb248e0b54b
# Fabric and dependencies
Fabric==1.10.2 --hash:sha256=8fe1eb0b0f271e2d41445e7da4470548d3bdf882aab1c1f143505c599996793b
paramiko==1.15.2 --hash:sha256=c92b168c8db94a9e1362f3fc27bc21e8c20794885bf2f7d303b5ad717c044ebc
ecdsa==0.13 --hash:sha256=89f149066e4a1e419892cef830fd0db85c227d5d427f7075422ace83429e2d26
# pycrypto, but it is a direct Galaxy dependency as well
# Can't use Whoosh latest due to a bug but need to backport a bugfix from a
# newer release.
#
# https://bitbucket.org/mchaput/whoosh/pull-requests/50/fix-lru-thread-safety/diff
Whoosh==2.4.1+gx1 --hash:sha256=98897e796c048810d71f7f4fc174914869f1b3b77f44e5a19a5e649b078d5e0e \
--hash:sha256=5ec3c22e782c86e981fab62a24ac9feea09e42c43b763a6493c78b82a3b6e3fd
# Flexible BAM index naming
pysam==0.8.3+gx1 --hash:sha256=020aa9101579ac1e82a194fdb08f49f517c634911409e9a2cda4d0a1c72a8c7c \
--hash:sha256=1a3d86849b9bd962979b65aaa9af236030dcc1db40296c88d2aa436a0c9df79b \
--hash:sha256=0fc55fb252eb0e7914679e9e22672fdc6a1e09804cbcc62769f004ebbed9b4c1 \
--hash:sha256=dde8f5037661d7be42e2c3f50c01566dcaedbf2f88133a3bb50c6ae3f75e6e13 \
--hash:sha256=7809fd926a071519c0a2b220346e45c094577877e5b2adba2903e7b52490c736 \
--hash:sha256=021070ed70a89e19eee6a989933d69d0bdb076c02342e2987bb5fab43f63ad17 \
--hash:sha256=374ea868bf64daa4665e8743db1be2e88712953a923020225f57a589b790537c \
--hash:sha256=9884b6904face1977649847261e7c984120adaa169a0d62e07820a44c71e18c5 \
--hash:sha256=873b81951e9d572b53ab4c7a0d3ef915f7d0e1db5f75603d8861cf1d3810491e \
--hash:sha256=37d0ba3880b5a517f354281159f6751f6f9f1c1074ea48bf5f4c424e6ec488dd \
--hash:sha256=db99cb20cb5e07998b2acfd29e34c367ef408a184a7b3150586212175a0719bf \
--hash:sha256=a1fcb2a6459b799bff7a046e190452b151c5985dea404eaee82bd645b1bfe34d \
--hash:sha256=306e4d900dfb582cf87bc21904e2193ef81db76173e976b74152c95ddd93bdc6 \
--hash:sha256=2341438d636b8e3cb51b219aab1cc909142d3af176042d12b128d4177682b1ab \
--hash:sha256=0f33df9eba7b079b7489ac3dd908a6e44b0e98d094e633b29035d33bfc990b9e \
--hash:sha256=faa8aae3f8f105c5c823a7d570dd3caba31ece69b8f3325106435b9f1fcb68d2 \
--hash:sha256=2db995758d666c51fecf11cbee1afda357477e01077aacf68ae0c00304c7bc51 \
--hash:sha256=2de7a2098f64672d0396ac727633285f3562f804e7845e105ee19da544d7da8a
+43 -144
View File
@@ -1,170 +1,69 @@
# packages with C extensions
bx-python==0.7.3 --hash:sha256=0a0fd962edd0f9afdf5d7ccbdf46dc220a0cb652073a93411dd6f7f649f07d91 \
--hash:sha256=46dc3042c7e475363830fa92d4a613ae10b58db7f114ff8193d2ee0bc3c4607e \
--hash:sha256=b93a9378a5d0e29ea8a13e026c170f48bf1f8316a39c342b1eb54f557b4fb3c4 \
--hash:sha256=d06c7bf0ae7f019521aeb5ffe4df48bb5fdd4d75d7ad00e0059b997c4f13ca3a \
--hash:sha256=05d0ab8fd13319d5ef9edb246dc6805640ea7574bb885a0b8607474271ac5793 \
--hash:sha256=5a026869227a6464eba23835765a36ffc2910f7af51b81f672a97c0d005e04a3 \
--hash:sha256=85be43a6b94f0c841d9954f820133db35067854504c1de87dd0089bb06eca18d \
--hash:sha256=d085824eb33c54d333b99dca29b49890457a8263f431b54b17ae3052be191d2b \
--hash:sha256=41bcf85b9be9f61ba7c7bae48c5a5ae3251868a1b25f02b6eb93b29bcabfd00c \
--hash:sha256=c9b71aee26ee85fbcbb3060109d79531bfa8991f4924bdcfed63d909a5937290
MarkupSafe==0.23 --hash:sha256=3a79d9650b7e79943be51a045c7c39a77ebbe9a337e8af51a5575e39332dce87 \
--hash:sha256=e0a4155493d1cfa72e985dbe1660a44d64a173282801563956e061b24371266a \
--hash:sha256=147013ed157f1423a0d0047043c6bbccbef31a52d82e2a10dfc3c6de9392765c \
--hash:sha256=d25d14cb01284aed33690b85bfde8de206ffcfdc52351588bcf17480839bef6f \
--hash:sha256=29958f81958e0dd9f5dd36d52f2ac549d875dde3559b783578118c9005693852 \
--hash:sha256=287a1c6b0d2a08cb76be6e584bf119649405f015598cf8b78d4a592cc80700a0 \
--hash:sha256=973cadf7b9907f9c81d9b898817d6a485b37325176befec2389fa2ced4c61a51 \
--hash:sha256=a365fd3468c86741aec5901f4b07990aaa0b458fb79e9f3557378a63e6d627e9 \
--hash:sha256=ba7af558b18ba9c05bb0d36f22a5ea65ee11ba44a6cf8a2950f2f80c08260e11 \
--hash:sha256=51bf7f077938c64dd00de6732996ccee8ceba2206c69acfb07f66430ca76372f
PyYAML==3.11 --hash:sha256=2912c1fb56c316461d003a8b8f1f41e1ed8387b2e47a4523f8a4eec8aa85e241 \
--hash:sha256=f4437443dc014c04ceee8cc94d4165f01ba23643991fd2c6b919f26cf9997474 \
--hash:sha256=b62cde962d41377c175831fa3fd6ac41585d2e2111ca4c45a6ee80a832457e92 \
--hash:sha256=aad37be9d524ba2dba9a3114b620b2800b40e67e455c9741a5cb81a6a0e882f6 \
--hash:sha256=03e0f4ac96599c1d687b080f1610ab0469e8785bb48cfdf860f2076a08ea6406 \
--hash:sha256=7dc97b5b1b920f6bbe0e47cfa6ff112f6eede35924a63354f80d672354f25160 \
--hash:sha256=ceb5dccec2045d4a864c6e808b397b10830476c44bdc64b80c18bf29e481ba07 \
--hash:sha256=9b184a4a7d3d383b39cb73429d3798370facaee4263465b575f243c7ede3f9c3 \
--hash:sha256=f90314e2ed46ea2da980aff88b91c3cc8ce93edd4658011dd462a8f28399533b \
--hash:sha256=80936dca10b611cd54ca52939aac938d59653830a6a6265bef5d11896de8e249
SQLAlchemy==1.0.8 --hash:sha256=3c357f36c141205cea2b5ec4c4e9885602452fea06428d6c20596c66c9a43243 \
--hash:sha256=17fad7f37f902dbec37ca2777af3021f9a4ed31079d64f7f888e7b29517240a3 \
--hash:sha256=e177904a384b9bc68914afb32a6ed2cc73ed7787444e3e1fdf85e3b9cfe5f847 \
--hash:sha256=91ed10baf56b6e29665f2b9fcb0c690afc6cc2c2e8e19c7f92b58092a4002e14 \
--hash:sha256=f5d6156d1d7865cd23b76ddad3f53ec07a3009a2cd8082a829cd1f24b366db5c \
--hash:sha256=3c3f3baf07f868c1c3f86d63dc2efa4455e95d76745f1af561f1ccf0fd9e8c81 \
--hash:sha256=a9fb8061aa767ca2ad22983a11e074ac231f44a56709721c60cc1992f2a92350 \
--hash:sha256=884b522d2d067cffd103f4e1a5342c678803cd6903da24a3f757b57b00eb188b \
--hash:sha256=d5dde66c1603853aebbfbbd74d79c60678f7d98c17abce4be4ebbb697dfd7265 \
--hash:sha256=42346d5e91c5e0a5a975352d8af3cfd8b2dad602dd07ec41b6b848ac5205cf5b
bx-python==0.7.3
MarkupSafe==0.23
PyYAML==3.11
SQLAlchemy==1.0.8
# Mercurial >= 3.5 changed the bundle format, which breaks hg push of TS repositories
mercurial==3.4.2 --hash:sha256=7851864b03929c09e07670bf8ab7d59f3529650c935a70d09fb6ce7f6a84e2a5 \
--hash:sha256=c23b02b4c32edc2d0799221a9d35abd916fb8a1acd1c07d64c16a235ef677b9e \
--hash:sha256=ca72ddfaea681a070b62edcb8e41d58bd24a2b04f73e66658565d189a76f3819 \
--hash:sha256=fdad4496f3d7f3e7eced771fa46e21c074989f8437ddf3e0ff6c0eee964e4c29 \
--hash:sha256=964a10ec1114dbee3696134bafed676f66038759b73de8593f92616f0e53f371 \
--hash:sha256=c6ca6fbe56a8919dfc521e80ab781ab565760d87f4a6170e788d67eb6d69d30f \
--hash:sha256=69540318fa9f7a3a0428647003d4f1fa8865d29648e73999b921cae039145ce9 \
--hash:sha256=b3de0ee851cf8750f53102437c9a04c7217a8c6f7411030ab3bb5534885f3315 \
--hash:sha256=46f67af52c7b1aed68b67daa33c26eafc0fb1d371954d3266fce739446cfcb1d \
--hash:sha256=000afb932f0ae45c365cbc0457044e8800811fdad7eee9332b6403b83423ab0a
numpy==1.9.2 --hash:sha256=931ce6fd1180a10d58a925b614775706c05de35bca5805e705e1da17e1326862 \
--hash:sha256=2340c4b72fdab79ac0fc04bb6629b26eeb93d10f4945b6b1f07d9be8663cab84 \
--hash:sha256=83fe34ff67653a639c57cfd04a0d48dda5913250fd95c8466af1d8416b58af59 \
--hash:sha256=aeb182d95ddb2dfd81683907be193cfc11c4d0ba744faf457013499fa14a131e \
--hash:sha256=d6f1eec7ae250892a2b142af406e43760042badae8e2f168136eace5dd9f05c3 \
--hash:sha256=0b0883cac08e3c0999159ba7f34c9b94d26d7d1a2be4017b792145d722646fb7 \
--hash:sha256=a124d11b1bec5c517d60ad9414564b5af0828421112d2a00771d22715eab1c3c \
--hash:sha256=fabc2f76266de7396e2752baabf287cdd0cc2ed23c1f36ca3c3e8b094e86b87c \
--hash:sha256=f83a667d3a38643b3bf6361904cd6c4f2a18d1420c2204c7f269cd36b730c404 \
--hash:sha256=dab9bd8c867403340b370ea383c8eda3dc984dd5efc91904a5695e00b1762fc9
pycrypto==2.6.1 --hash:sha256=44c20785a1057b8d5e190d6a1847f7c62a8180b9b27a3aca7c3ec920bfb8e7b7 \
--hash:sha256=785ba61251cda6e574e0affc4412c346ef615455b81287fe0d6a2e1c5aed5172 \
--hash:sha256=5ec40d95520a665843915763c8cbbf40457330bd7ebf2a55ffea1b10a519d12b \
--hash:sha256=2cb43f0b293a18e6d5818287150994cf6083b1a9cdff65c19d1150a34aa813bc \
--hash:sha256=d48e46f4ccd5c21f3e01bbdbd8e7a86443fc7abdf3f93829c3d04ed684ec22c5 \
--hash:sha256=30312bd39f45c91f287f3e6e54c40988d30b1be9a9f332585e3cc00ee5f91554 \
--hash:sha256=d129d6d3441efecf2bc7e6b36cb35e99642248d72dbf59b992e6940b9359dabc \
--hash:sha256=8884b92835a1c0c763099981d19c990fdc3ae2b7011eb93b1f96e34a346b2d2f \
--hash:sha256=7e7e9abc0ae522ae86772d98b7144e0d2ef7791d124936f283680f84fe8cce6c \
--hash:sha256=61d3b42eaf89108b8a24c3736fb770f768efb89b1efaf0825efb5c316f0bffdc
mercurial==3.4.2
numpy==1.9.2
pycrypto==2.6.1
# Install python_lzo if you want to support indexed access to lzo-compressed
# locally cached maf files via bx-python
#python_lzo==1.8 --hash:sha256=638b38bc1d83561a9807365676f5b2ba6f18491753a673e6a9c5913bd542fe1a \
# --hash:sha256=cda3d6c27e69a9d04eb96db6b4b96fbe7facdd11dc2b9a82fe3c65b84b40fe44 \
# --hash:sha256=7ededfdb65b4eb282a7cc1600c6f5b4f483b39a70b3460c2f4651ee8fc431f77 \
# --hash:sha256=86a61008a8ab5f8ca973bd7e7b1d031c89637257dcf7215bff1913f17d3c596f \
# --hash:sha256=1d6af33e40383dba0c3ee26eee3e501e805fe42537dd0096788190bbc8fd7aae \
# --hash:sha256=6d08ad35322a5969dfd8ef5af7ff4cdf625d6a7bfa8e915b77f5935f58e1c7b1 \
# --hash:sha256=99b7e0c186c5b84d80de6e7b70359b6fc456c02bd2b31fc598140fbc6618d651 \
# --hash:sha256=be967c38c4e33f66823d10fb5efca42a0a23269459ce41239c173ccc114b603e \
# --hash:sha256=a34d7431e30c6d61c22b92d51224ea34d68be51aa42ec95a053b7f19be3fef0d \
# --hash:sha256=be76281c1c7f24d44e3415787d2a05688f6bbda2dc9bba92155ae3ca0d6716e7
#python_lzo==1.8
# pure Python packages
Paste==2.0.2 --hash:sha256=4e7bb2d8cbdc47ab46e4af0cb61d2af91fccc620a08415d9c4da9e499f0455fd
PasteDeploy==1.5.2 --hash:sha256=3922127d3acc6e274a800978b9293c874b3ef4ac2eb8bf485e2c85b22d1f260a
docutils==0.12 --hash:sha256=732dfc2d706ea390c264bc69110d3d6c7c3a520628a052ccc5998466f95d5c29
wchartype==0.1 --hash:sha256=2932471fe3a4e5cac4539c1b49bbc2bbd24ec3f00532c7f27c80b7756fdc177d
repoze.lru==0.6 --hash:sha256=731cc0b0a184c9fd270a4f29d9635099bb0398823e9a1a39bf4f488d1ead57b3
Routes==2.2 --hash:sha256=1d61dc9f1bbd86504de221568743133fbdfeb70f11cee4222cef72aa108e834c
WebOb==1.4.1 --hash:sha256=dc3c45ac0b56a3c65f47f1da6c23760dfe0139e8a84caaf1cfc9276b3e10875a
WebHelpers==1.3 --hash:sha256=8969ec3fb851872096067a805d512c3bed1952e6fc66f1ef1d1c6a7470937688
Mako==1.0.2 --hash:sha256=d3f372cbc2e7de080b5f7056d160f3ac8279353a2ea8f1ef8fd5b0cf0a6a3b17
pytz==2015.4 --hash:sha256=3bec70eef120ad0bf9143e59bbf36715ec1232fb0550ae2b8aa6c107aacfa6f2
Babel==2.0 --hash:sha256=aa725635ef189f77b6b0579efe1e91602d7cf63a31f6dd719a88ee53642bb5ab
Beaker==1.7.0 --hash:sha256=334427853ac291e4ecd1e03addb48e231681ab9b6c2bc793c0f0fb98024b70b1
Paste==2.0.2
PasteDeploy==1.5.2
docutils==0.12
wchartype==0.1
repoze.lru==0.6
Routes==2.2
WebOb==1.4.1
WebHelpers==1.3
Mako==1.0.2
pytz==2015.4
Babel==2.0
Beaker==1.7.0
# Cheetah and dependencies
Cheetah==2.4.4 --hash:sha256=24cf67789b7a9f1e0a55cba266b6aad16e97aaf25810fd6f2f7e7b36005c1161 \
--hash:sha256=30c6dd32c066f483462cebc7fc37feb454d6a3d35e8b599da17624b2541761ab \
--hash:sha256=fcbff7d96509419cbcefa231d6fee4aca98d2f04f8339848c19da3e82aebcf27 \
--hash:sha256=5c758550b8170b01e016b75ec05dbd2c32b56513d6e1ef9177c5290f4e166ad2 \
--hash:sha256=6aaeef7f742df6a23c4132bb33000196053b661a150fdd98311f25f09d3730c1 \
--hash:sha256=469e7ddc2f4a9b147b2b5c258fc9f97cee9842790c1849b941bae165b390da92 \
--hash:sha256=75f05eda3b16c621b5b570f9c5b317f6ea94b01296b9e1ef2583560d153578bd \
--hash:sha256=6da983e9d189a3c389e98506871ff836a83df1792dba5e4a684d27d948402d7a \
--hash:sha256=55b0c2696eb321415a9eca86303e3c359dee550d7f6fc719bc960f23422d2290 \
--hash:sha256=2caf567b6cdd54f806ce12d98302e380d4bbbed8990663f9bce52d69358fc488
Markdown==2.6.3 --hash:sha256=59417f5eb3dace08309d81e48fc903217d12d66677f367674b22c317b0f04284
Cheetah==2.4.4
Markdown==2.6.3
# BioBlend and dependencies
bioblend==0.6.1 --hash:sha256=f5eea1f6c31264ef7bfab8c70deac2b9229a10e5c56508a6542f5643ad9e2a5b
boto==2.38.0 --hash:sha256=1760584368da0c3861dbed448dcb439334ce831044262a5ca5188167f8bba585
requests==2.8.1 --hash:sha256=70e285122c97b1d104824482cb929246b2b8a2b9858897c4fab3acec83f1e03c
requests-toolbelt==0.4.0 --hash:sha256=94694e32845b84ed2186fdf56219b949582ebd08dc3abc55c0549958f2029643
bioblend==0.6.1
boto==2.38.0
requests==2.8.1
requests-toolbelt==0.4.0
# kombu and dependencies
kombu==3.0.30 --hash:sha256=562010f0deb1f04e3abd154b0ef5e246d606b54cb2c5f29e8c4651b354d0b082 \
--hash:sha256=5baff23a2b2d78eecb7c97700ea359ab80744c719e311fb446513d7b72ddbc96
amqp==1.4.8 --hash:sha256=c7874d845c9bdffbf754ce84f105a1b8c7a6cffb61f362ac67591536ba8c0c1a \
--hash:sha256=caada1c29d5e73e13ed8706442ee0fbb1440de9b6fca4df12fc8ff59dd61f6f6
anyjson==0.3.3 --hash:sha256=2c84f23be20e3c465151a55917b8e38a04c579394057e232c16fb5ca0c6ae108
kombu==3.0.30
amqp==1.4.8
anyjson==0.3.3
# sqlalchemy-migrate and dependencies
sqlalchemy-migrate==0.10.0 --hash:sha256=2aaa4e7070c8447d564f1c173937c2c5a45f889eb31a0fc80add5fc175c45a5e
decorator==4.0.2 --hash:sha256=d8c3f7e18efba558084648d6dd6c6b0850e6f5c08c392975ae196c4b4eb7be2a
Tempita==0.5.3dev --hash:sha256=df0c6513e565b213733b3f8bf7bcca75998f166042692e1712e3fe36568db234
sqlparse==0.1.16 --hash:sha256=221d383f1236f9c05aadd2c4edf4274144279ad06821d7d9bf5a70751157f75d
pbr==1.8.0 --hash:sha256=355a0c2ba71120dce1c522387e494c60eb4f44fa9d03067cb9816187e6e803e9
sqlalchemy-migrate==0.10.0
decorator==4.0.2
Tempita==0.5.3dev
sqlparse==0.1.16
pbr==1.8.0
# six is also a Pulsar client dep
six==1.9.0 --hash:sha256=cf806ab65d5e16561df30c2cea2fb2cf3e6aa82e48f22036dff177e20f61e188
Parsley==1.3 --hash:sha256=32fd648334146e4005dae41d559d32edfff9f3d5f503f8b5d233dbfe3a15a28b
nose==1.3.7 --hash:sha256=f36054c5786e84ff6b131f3249a3cce82787f1a930ab053287c0edaa9f840d0f
SVGFig==1.1.6 --hash:sha256=300cf4b37b4773498d4ea96c703cdb5f09215978b02828dadb786fb248e0b54b
six==1.9.0
Parsley==1.3
nose==1.3.7
SVGFig==1.1.6
# Fabric and dependencies
Fabric==1.10.2 --hash:sha256=8fe1eb0b0f271e2d41445e7da4470548d3bdf882aab1c1f143505c599996793b
paramiko==1.15.2 --hash:sha256=c92b168c8db94a9e1362f3fc27bc21e8c20794885bf2f7d303b5ad717c044ebc
ecdsa==0.13 --hash:sha256=89f149066e4a1e419892cef830fd0db85c227d5d427f7075422ace83429e2d26
Fabric==1.10.2
paramiko==1.15.2
ecdsa==0.13
# pycrypto, but it is a direct Galaxy dependency as well
# Can't use Whoosh latest due to a bug but need to backport a bugfix from a
# newer release.
#
# https://bitbucket.org/mchaput/whoosh/pull-requests/50/fix-lru-thread-safety/diff
Whoosh==2.4.1+gx1 --hash:sha256=98897e796c048810d71f7f4fc174914869f1b3b77f44e5a19a5e649b078d5e0e \
--hash:sha256=5ec3c22e782c86e981fab62a24ac9feea09e42c43b763a6493c78b82a3b6e3fd
Whoosh==2.4.1+gx1
# Flexible BAM index naming
pysam==0.8.3+gx1 --hash:sha256=020aa9101579ac1e82a194fdb08f49f517c634911409e9a2cda4d0a1c72a8c7c \
--hash:sha256=1a3d86849b9bd962979b65aaa9af236030dcc1db40296c88d2aa436a0c9df79b \
--hash:sha256=0fc55fb252eb0e7914679e9e22672fdc6a1e09804cbcc62769f004ebbed9b4c1 \
--hash:sha256=dde8f5037661d7be42e2c3f50c01566dcaedbf2f88133a3bb50c6ae3f75e6e13 \
--hash:sha256=7809fd926a071519c0a2b220346e45c094577877e5b2adba2903e7b52490c736 \
--hash:sha256=021070ed70a89e19eee6a989933d69d0bdb076c02342e2987bb5fab43f63ad17 \
--hash:sha256=374ea868bf64daa4665e8743db1be2e88712953a923020225f57a589b790537c \
--hash:sha256=9884b6904face1977649847261e7c984120adaa169a0d62e07820a44c71e18c5 \
--hash:sha256=873b81951e9d572b53ab4c7a0d3ef915f7d0e1db5f75603d8861cf1d3810491e \
--hash:sha256=37d0ba3880b5a517f354281159f6751f6f9f1c1074ea48bf5f4c424e6ec488dd \
--hash:sha256=db99cb20cb5e07998b2acfd29e34c367ef408a184a7b3150586212175a0719bf \
--hash:sha256=a1fcb2a6459b799bff7a046e190452b151c5985dea404eaee82bd645b1bfe34d \
--hash:sha256=306e4d900dfb582cf87bc21904e2193ef81db76173e976b74152c95ddd93bdc6 \
--hash:sha256=2341438d636b8e3cb51b219aab1cc909142d3af176042d12b128d4177682b1ab \
--hash:sha256=0f33df9eba7b079b7489ac3dd908a6e44b0e98d094e633b29035d33bfc990b9e \
--hash:sha256=faa8aae3f8f105c5c823a7d570dd3caba31ece69b8f3325106435b9f1fcb68d2 \
--hash:sha256=2db995758d666c51fecf11cbee1afda357477e01077aacf68ae0c00304c7bc51 \
--hash:sha256=2de7a2098f64672d0396ac727633285f3562f804e7845e105ee19da544d7da8a
pysam==0.8.3+gx1
+12 -4
View File
@@ -43,6 +43,9 @@ log = logging.getLogger( __name__ )
# and should eventually become API'd
TOOL_PROVIDED_JOB_METADATA_FILE = 'galaxy.json'
# Override with config.default_job_shell.
DEFAULT_JOB_SHELL = '/bin/sh'
class JobDestination( Bunch ):
"""
@@ -55,6 +58,7 @@ class JobDestination( Bunch ):
self['runner'] = None
self['legacy'] = False
self['converted'] = False
self['shell'] = None
self['env'] = []
self['resubmit'] = []
# dict is appropriate (rather than a bunch) since keys may not be valid as attributes
@@ -785,6 +789,10 @@ class JobWrapper( object ):
def get_parallelism(self):
return self.tool.parallelism
@property
def shell(self):
return self.job_destination.shell or getattr(self.app.config, 'default_job_shell', DEFAULT_JOB_SHELL)
@property
def commands_in_new_shell(self):
return self.app.config.commands_in_new_shell
@@ -1195,8 +1203,8 @@ class JobWrapper( object ):
# either use the metadata from originating output dataset, or call set_meta on the copies
# it would be quicker to just copy the metadata from the originating output dataset,
# but somewhat trickier (need to recurse up the copied_from tree), for now we'll call set_meta()
if ( self.app.config.retry_metadata_internally
and not self.external_output_metadata.external_metadata_set_successfully(dataset, self.sa_session ) ):
if ( self.app.config.retry_metadata_internally and
not self.external_output_metadata.external_metadata_set_successfully(dataset, self.sa_session ) ):
# If Galaxy was expected to sniff type and didn't - do so.
if dataset.ext == "_sniff_":
extension = sniff.handle_uploaded_dataset_file( dataset.dataset.file_name, self.app.datatypes_registry )
@@ -1204,8 +1212,8 @@ class JobWrapper( object ):
# call datatype.set_meta directly for the initial set_meta call during dataset creation
dataset.datatype.set_meta( dataset, overwrite=False )
elif ( job.states.ERROR != final_job_state
and not self.external_output_metadata.external_metadata_set_successfully( dataset, self.sa_session ) ):
elif ( job.states.ERROR != final_job_state and
not self.external_output_metadata.external_metadata_set_successfully( dataset, self.sa_session ) ):
dataset._state = model.Dataset.states.FAILED_METADATA
else:
# load metadata from file
+16 -11
View File
@@ -1,16 +1,19 @@
from os import getcwd
from os import chmod
from os.path import join
from os.path import abspath
from galaxy import util
from galaxy.jobs.runners.util.job_script import (
INTEGRITY_INJECTION,
write_script,
check_script_integrity,
)
from logging import getLogger
log = getLogger( __name__ )
CAPTURE_RETURN_CODE = "return_code=$?"
YIELD_CAPTURED_CODE = 'sh -c "exit $return_code"'
DEFAULT_SHELL = "/bin/sh"
def build_command(
@@ -19,7 +22,7 @@ def build_command(
container=None,
include_metadata=False,
include_work_dir_outputs=True,
remote_command_params={}
remote_command_params={},
):
"""
Compose the sequence of commands necessary to execute a job. This will
@@ -30,6 +33,7 @@ def build_command(
- command line taken from job wrapper
- commands to set metadata (if include_metadata is True)
"""
shell = job_wrapper.shell
base_command_line = job_wrapper.get_command_line()
# job_id = job_wrapper.job_id
# log.debug( 'Tool evaluation for job (%s) produced command-line: %s' % ( job_id, base_command_line ) )
@@ -52,7 +56,7 @@ def build_command(
__handle_dependency_resolution(commands_builder, job_wrapper, remote_command_params)
if container or job_wrapper.commands_in_new_shell:
externalized_commands = __externalize_commands(job_wrapper, commands_builder, remote_command_params)
externalized_commands = __externalize_commands(job_wrapper, shell, commands_builder, remote_command_params)
if container:
# Stop now and build command before handling metadata and copying
# working directory files back. These should always happen outside
@@ -76,17 +80,18 @@ def build_command(
return commands_builder.build()
def __externalize_commands(job_wrapper, commands_builder, remote_command_params, script_name="tool_script.sh"):
def __externalize_commands(job_wrapper, shell, commands_builder, remote_command_params, script_name="tool_script.sh"):
local_container_script = join( job_wrapper.working_directory, script_name )
tool_commands = commands_builder.build()
with open( local_container_script, "w" ) as f:
script_contents = u"#!%s\n%s" % (DEFAULT_SHELL, tool_commands)
f.write(script_contents.encode(util.DEFAULT_ENCODING))
chmod( local_container_script, 0755 )
config = job_wrapper.app.config
integrity_injection = ""
if check_script_integrity(config):
integrity_injection = INTEGRITY_INJECTION
script_contents = u"#!%s\n%s%s" % (shell, integrity_injection, tool_commands)
write_script(local_container_script, script_contents, config)
commands = local_container_script
if 'working_directory' in remote_command_params:
commands = "%s %s" % (DEFAULT_SHELL, join(remote_command_params['working_directory'], script_name))
commands = "%s %s" % (shell, join(remote_command_params['working_directory'], script_name))
log.info("Built script [%s] for tool command[%s]" % (local_container_script, tool_commands))
return commands
+4 -36
View File
@@ -20,6 +20,7 @@ from galaxy.util import in_directory
from galaxy.util import ParamsWithSpecs
from galaxy.util import ExecutionTimer
from galaxy.util.bunch import Bunch
from galaxy.jobs.runners.util.job_script import write_script
from galaxy.jobs.runners.util.job_script import job_script
from galaxy.jobs.runners.util.env import env_to_statement
@@ -166,7 +167,7 @@ class BaseJobRunner( object ):
job_wrapper.runner_command_line = self.build_command_line(
job_wrapper,
include_metadata=include_metadata,
include_work_dir_outputs=include_work_dir_outputs
include_work_dir_outputs=include_work_dir_outputs,
)
except:
log.exception("(%s) Failure preparing job" % job_id)
@@ -297,6 +298,7 @@ class BaseJobRunner( object ):
env_setup_commands=env_setup_commands,
working_directory=os.path.abspath( job_wrapper.working_directory ),
command=command_line,
shell=job_wrapper.shell,
)
# Additional logging to enable if debugging from_work_dir handling, metadata
# commands, etc... (or just peak in the job script.)
@@ -306,41 +308,7 @@ class BaseJobRunner( object ):
return job_script(**options)
def write_executable_script( self, path, contents, mode=0o755 ):
with open( path, 'w' ) as f:
if isinstance(contents, unicode):
contents = contents.encode("UTF-8")
f.write( contents )
os.chmod( path, mode )
self._handle_script_integrity( path )
def _handle_script_integrity( self, path ):
if not getattr( self.app.config, "check_job_script_integrity", True ):
return
script_integrity_verified = False
for i in range(10):
try:
proc = subprocess.Popen( [path], shell=True, env={"ABC_TEST_JOB_SCRIPT_INTEGRITY_XYZ": "1"} )
proc.wait()
if proc.returncode == 42:
script_integrity_verified = True
break
# Else we will sync and wait to see if the script becomes
# executable.
try:
# sync file system to avoid "Text file busy" problems.
# These have occurred both in Docker containers and on EC2 clusters
# under high load.
subprocess.check_call(["/bin/sync"])
except Exception:
pass
time.sleep( .25 )
except Exception:
pass
if not script_integrity_verified:
raise Exception("Failed to write job script, could not verify job script integrity.")
write_script( path, contents, self.app.config, mode=mode )
def _complete_terminal_job( self, ajs, **kwargs ):
if ajs.job_wrapper.get_state() != model.Job.states.DELETED:
@@ -1,12 +1,6 @@
#!/bin/sh
# The following block can be used by the job creation system
# to ensure this script is runnable before running it directly
# or submitting it to a cluster manager.
if [ -n "$ABC_TEST_JOB_SCRIPT_INTEGRITY_XYZ" ]; then
exit 42
fi
#!$shell
$integrity_injection
$headers
$slots_statement
export GALAXY_SLOTS
@@ -1,7 +1,14 @@
import os
from string import Template
import subprocess
import time
from pkg_resources import resource_string
from six import text_type
from galaxy.util import unicodify
DEFAULT_SHELL = '/bin/sh'
DEFAULT_JOB_FILE_TEMPLATE = Template(
resource_string(__name__, 'DEFAULT_JOB_FILE_TEMPLATE.sh').decode('UTF-8')
)
@@ -13,6 +20,19 @@ SLOTS_STATEMENT_SINGLE = """
GALAXY_SLOTS="1"
"""
INTEGRITY_INJECTION = """
# The following block can be used by the job system
# to ensure this script is runnable before actually attempting
# to run it.
if [ -n "$ABC_TEST_JOB_SCRIPT_INTEGRITY_XYZ" ]; then
exit 42
fi
"""
INTEGRITY_SYNC_COMMAND = "/bin/sync"
DEFAULT_INTEGRITY_CHECK = True
DEFAULT_INTEGRITY_COUNT = 35
DEFAULT_INTEGRITY_SLEEP = .25
REQUIRED_TEMPLATE_PARAMS = ['working_directory', 'command', 'exit_code_path']
OPTIONAL_TEMPLATE_PARAMS = {
'galaxy_lib': None,
@@ -22,6 +42,8 @@ OPTIONAL_TEMPLATE_PARAMS = {
'slots_statement': SLOTS_STATEMENT_CLUSTER_DEFAULT,
'instrument_pre_commands': '',
'instrument_post_commands': '',
'integrity_injection': INTEGRITY_INJECTION,
'shell': DEFAULT_SHELL,
}
@@ -67,3 +89,56 @@ def job_script(template=DEFAULT_JOB_FILE_TEMPLATE, **kwds):
if not isinstance(template, Template):
template = Template(template)
return template.safe_substitute(template_params)
def check_script_integrity(config):
return getattr(config, "check_job_script_integrity", DEFAULT_INTEGRITY_CHECK)
def write_script(path, contents, config, mode=0o755):
with open(path, 'w') as f:
if isinstance(contents, text_type):
contents = contents.encode("UTF-8")
f.write(contents)
os.chmod(path, mode)
_handle_script_integrity(path, config)
def _handle_script_integrity(path, config):
if not check_script_integrity(config):
return
script_integrity_verified = False
count = getattr(config, "check_job_script_integrity_count", DEFAULT_INTEGRITY_COUNT)
sleep_amt = getattr(config, "check_job_script_integrity_sleep", DEFAULT_INTEGRITY_SLEEP)
for i in range(count):
try:
proc = subprocess.Popen([path], shell=True, env={"ABC_TEST_JOB_SCRIPT_INTEGRITY_XYZ": "1"})
proc.wait()
if proc.returncode == 42:
script_integrity_verified = True
break
# Else we will sync and wait to see if the script becomes
# executable.
try:
# sync file system to avoid "Text file busy" problems.
# These have occurred both in Docker containers and on EC2 clusters
# under high load.
subprocess.check_call(INTEGRITY_SYNC_COMMAND)
except Exception:
pass
time.sleep(sleep_amt)
except Exception:
pass
if not script_integrity_verified:
raise Exception("Failed to write job script, could not verify job script integrity.")
__all__ = [
'check_script_integrity',
'job_script',
'write_script',
'INTEGRITY_INJECTION',
]
+3 -3
View File
@@ -259,6 +259,6 @@ class AccessDatasetRBACPermission( DatasetRBACPermission ):
def _role_is_permitted( self, dataset, role ):
current_roles = self._roles( dataset )
return ( self._is_public_from_roles( current_roles )
# if there's only one role and this is it, let em in
or ( ( len( current_roles ) == 1 ) and ( role == current_roles[0] ) ) )
return ( self._is_public_from_roles( current_roles ) or
# if there's only one role and this is it, let em in
( ( len( current_roles ) == 1 ) and ( role == current_roles[0] ) ) )
+2 -6
View File
@@ -1398,7 +1398,6 @@ class History( object, Dictifiable, UsesAnnotations, HasName ):
assert db_session is not None
query = db_session.query( content_class ).filter( content_class.table.c.history_id == self.id )
query = query.order_by( content_class.table.c.hid.asc() )
python_filter = None
deleted = galaxy.util.string_as_bool_or_none( kwds.get( 'deleted', None ) )
if deleted is not None:
query = query.filter( content_class.deleted == deleted )
@@ -1411,11 +1410,8 @@ class History( object, Dictifiable, UsesAnnotations, HasName ):
if len(ids) < max_in_filter_length:
query = query.filter( content_class.id.in_(ids) )
else:
python_filter = lambda content: content.id in ids
if python_filter:
return ifilter(python_filter, query)
else:
return query
query = ifilter(lambda content: content.id in ids, query)
return query
def __collection_contents_iter( self, **kwds ):
return self.__filter_contents( HistoryDatasetCollectionAssociation, **kwds )
+2 -1
View File
@@ -232,7 +232,8 @@ def total_size(o, handlers={}, verbose=False):
Recipe from: https://code.activestate.com/recipes/577504-compute-memory-footprint-of-an-object-and-its-cont/
"""
dict_handler = lambda d: chain.from_iterable(d.items())
def dict_handler(d):
return chain.from_iterable(d.items())
all_handlers = { tuple: iter,
list: iter,
deque: iter,
@@ -61,7 +61,7 @@ def upgrade(migrate_engine):
if r[1]:
dataset_files = loads(r[1])
for df in dataset_files:
if type(df) == type(dict()):
if isinstance(df, dict):
cmd = "INSERT INTO sample_dataset VALUES (%s, %s, %s, %s, '%s', '%s', '%s', '%s', '%s')"
cmd = cmd % ( nextval(migrate_engine, 'sample_dataset'),
localtimestamp(migrate_engine),
@@ -77,7 +77,7 @@ def upgrade(migrate_engine):
if not str( row[2] ).strip():
continue
fields_list = loads( str( row[2] ).strip() )
if fields_list and type(values_list) == type(list()):
if fields_list and isinstance(values_list, list):
values_dict = {}
for field_index, field in enumerate( fields_list ):
field_name = field[ 'name' ]
@@ -136,7 +136,7 @@ def get_sequencer_id( migrate_engine, sequencer_info ):
continue
values = loads( values )
# proceed only if sequencer_info is a valid list
if values and type( values ) == type( dict() ):
if values and isinstance(values, dict):
if sequencer_info.get( 'host', '' ) == values.get( 'field_0', '' ) \
and sequencer_info.get( 'username', '' ) == values.get( 'field_1', '' ) \
and sequencer_info.get( 'password', '' ) == values.get( 'field_2', '' ) \
@@ -236,7 +236,7 @@ def upgrade(migrate_engine):
continue
sequencer_info = loads( sequencer_info.strip() )
# proceed only if sequencer_info is a valid dict
if sequencer_info and type( sequencer_info ) == type( dict() ):
if sequencer_info and isinstance(sequencer_info, dict):
# check if this sequencer has already been added to the sequencer table
sequencer_id = get_sequencer_id( migrate_engine, sequencer_info )
if not sequencer_id:
+11 -11
View File
@@ -18,7 +18,6 @@ from cgi import FieldStorage
from xml.etree import ElementTree
from mako.template import Template
from paste import httpexceptions
from sqlalchemy import and_
from galaxy import model
from galaxy.managers import histories
@@ -194,14 +193,13 @@ class ToolBox( BaseGalaxyToolBox ):
# Abstract toolbox doesn't have a dependency on the the database, so
# override _get_tool_shed_repository here to provide this information.
# We store only the port, if one exists, in the database.
tool_shed = common_util.remove_protocol_from_tool_shed_url( tool_shed )
return self.app.install_model.context.query( self.app.install_model.ToolShedRepository ) \
.filter( and_( self.app.install_model.ToolShedRepository.table.c.tool_shed == tool_shed,
self.app.install_model.ToolShedRepository.table.c.name == name,
self.app.install_model.ToolShedRepository.table.c.owner == owner,
self.app.install_model.ToolShedRepository.table.c.installed_changeset_revision == installed_changeset_revision ) ) \
.first()
return suc.get_installed_repository(
self.app,
tool_shed=tool_shed,
name=name,
owner=owner,
installed_changeset_revision=installed_changeset_revision
)
def __build_tool_version_select_field( self, tools, tool_id, set_selected ):
"""Build a SelectField whose options are the ids for the received list of tools."""
@@ -1675,7 +1673,7 @@ class Tool( object, Dictifiable ):
if isinstance( input, Conditional ):
cond_messages = {}
if not input.is_job_resource_conditional:
cond_messages = { input.test_param.name: "No value found for '%s%s', using default" % ( prefix, input.label ) }
cond_messages = { input.test_param.name: "No value found for '%s%s', using default" % ( prefix, input.test_param.label ) }
messages[ input.name ] = cond_messages
test_value = input.test_param.get_initial_value( trans, context )
current_case = input.get_current_case( test_value, trans )
@@ -1689,6 +1687,7 @@ class Tool( object, Dictifiable ):
messages[ input.name ].append( rep_dict )
self.check_and_update_param_values_helper( input.inputs, {}, trans, rep_dict, context, rep_prefix, allow_workflow_parameters=allow_workflow_parameters )
elif isinstance( input, Section ):
messages[ input.name ] = {}
self.check_and_update_param_values_helper( input.inputs, {}, trans, messages[ input.name ], context, prefix, allow_workflow_parameters=allow_workflow_parameters )
else:
messages[ input.name ] = "No value found for '%s%s', using default" % ( prefix, input.label )
@@ -1718,7 +1717,8 @@ class Tool( object, Dictifiable ):
current = group_values["__current_case__"]
self.check_and_update_param_values_helper( input.cases[current].inputs, group_values, trans, messages, context, prefix, allow_workflow_parameters=allow_workflow_parameters )
elif isinstance( input, Section ):
self.check_and_update_param_values_helper( input.inputs, values[ input.name ], trans, messages, context, prefix, allow_workflow_parameters=allow_workflow_parameters )
messages[ input.name ] = {}
self.check_and_update_param_values_helper( input.inputs, values[ input.name ], trans, messages[ input.name ], context, prefix, allow_workflow_parameters=allow_workflow_parameters )
else:
# Regular tool parameter, no recursion needed
try:
+8 -3
View File
@@ -273,7 +273,7 @@ class DefaultToolAction( object ):
child_dataset_names = set()
object_store_populator = ObjectStorePopulator( app )
def handle_output( name, output ):
def handle_output( name, output, hidden=None ):
if output.parent:
parent_to_child_pairs.append( ( output.parent, name ) )
child_dataset_names.add( name )
@@ -295,7 +295,9 @@ class DefaultToolAction( object ):
input_ext
)
data = app.model.HistoryDatasetAssociation( extension=ext, create_dataset=True, flush=False )
if output.hidden:
if hidden is None:
hidden = output.hidden
if hidden:
data.visible = False
trans.sa_session.add( data )
trans.app.security_agent.set_all_dataset_permissions( data.dataset, output_permissions, new=True )
@@ -371,7 +373,10 @@ class DefaultToolAction( object ):
current_element_identifiers = current_element_identifiers[ index ][ "element_identifiers" ]
effective_output_name = output_part_def.effective_output_name
element = handle_output( effective_output_name, output_part_def.output_def )
element = handle_output( effective_output_name, output_part_def.output_def, hidden=True )
# TODO: this shouldn't exist in the top-level of the history at all
# but for now we are still working around that by hiding the contents
# there.
# Following hack causes dataset to no be added to history...
child_dataset_names.add( effective_output_name )
+5 -2
View File
@@ -350,7 +350,7 @@ def create_paramfile( trans, uploaded_datasets ):
return json_file_path
def create_job( trans, params, tool, json_file_path, data_list, folder=None, history=None ):
def create_job( trans, params, tool, json_file_path, data_list, folder=None, history=None, job_params=None ):
"""
Create the upload job.
"""
@@ -395,7 +395,10 @@ def create_job( trans, params, tool, json_file_path, data_list, folder=None, his
# open( dataset.file_name, "w" ).close()
job.object_store_id = object_store_id
job.set_state( job.states.NEW )
job.set_handler(tool.get_job_handler(None))
job.set_handler( tool.get_job_handler( None ) )
if job_params:
for name, value in job_params.iteritems():
job.add_parameter( name, value )
trans.sa_session.add( job )
trans.sa_session.flush()
+3 -4
View File
@@ -23,10 +23,9 @@ try:
except ImportError:
shellescape = None
if job is not None:
needs_shell_quoting = job.needs_shell_quoting
else:
needs_shell_quoting = None
import re
needs_shell_quoting = re.compile(r"""(^$|[\s|&;()<>\'"$@])""").search
def ensure_cwltool_available():
+2 -2
View File
@@ -27,11 +27,11 @@ class DependencyResolver(Dictifiable, object):
version for instance if the request version is 'default'.)
"""
def _get_config_option(self, key, dependency_resolver, default=None, prefix=None, **kwds):
def _get_config_option(self, key, dependency_resolver, default=None, config_prefix=None, **kwds):
""" Look in resolver-specific settings for option and then fallback to
global settings.
"""
global_key = "%s_%s" % (prefix, key)
global_key = "%s_%s" % (config_prefix, key)
if key in kwds:
return kwds.get(key)
elif global_key in dependency_resolver.extra_config:
+2 -2
View File
@@ -42,7 +42,7 @@ class CondaDependencyResolver(DependencyResolver, ListableDependencyResolver, In
self.versionless = _string_as_bool(kwds.get('versionless', 'false'))
def get_option(name):
return self._get_config_option(name, dependency_manager, prefix="conda", **kwds)
return self._get_config_option(name, dependency_manager, config_prefix="conda", **kwds)
# Conda context options (these define the environment)
conda_prefix = get_option("prefix")
@@ -177,7 +177,7 @@ class CondaDepenency(Dependency):
return self._exact
def shell_commands(self, requirement):
return """[ "$CONDA_DEFAULT_ENV" = "%s" ] || source %s '%s'""" % (
return """[ "$CONDA_DEFAULT_ENV" = "%s" ] || . %s '%s'""" % (
self.environment_path,
self.activate,
self.environment_path
+9 -5
View File
@@ -754,7 +754,8 @@ class BaseURLToolParameter( HiddenToolParameter ):
return d
DEFAULT_VALUE_MAP = lambda x: x
def DEFAULT_VALUE_MAP(x):
return x
def parse_dynamic_options(param, input_source):
@@ -1873,9 +1874,11 @@ class DataToolParameter( BaseDataToolParameter ):
def _get_select_dataset_collection_fields( self, history, dataset_matcher, multiple=False, suffix="|__collection_multirun__", reduction=False ):
if not reduction:
value_modifier = lambda x: x
def value_modifier(x):
return x
else:
value_modifier = lambda value: "__collection_reduce__|%s" % value
def value_modifier(value):
return "__collection_reduce__|%s" % value
value = dataset_matcher.value
if value is not None:
@@ -2212,14 +2215,15 @@ class DataToolParameter( BaseDataToolParameter ):
return d
# add datasets
visible_hda = other_values.get( self.name )
for hda in history.active_datasets_children_and_roles:
match = dataset_matcher.hda_match( hda )
match = dataset_matcher.hda_match( hda, ensure_visible=visible_hda != hda )
if match:
m = match.hda
d['options']['hda'].append({
'id' : trans.security.encode_id( m.id ),
'hid' : m.hid,
'name' : m.name,
'name' : m.name if m.visible else '(hidden) %s' % m.name,
'src' : 'hda'
})
+34 -7
View File
@@ -2,6 +2,7 @@
"""
import os
import re
import operator
import glob
import json
@@ -220,7 +221,7 @@ def collect_primary_datasets( tool, output, job_working_directory, input_ext ):
primary_output_assigned = True
continue
if name not in primary_datasets:
primary_datasets[ name ] = {}
primary_datasets[ name ] = odict.odict()
visible = fields_match.visible
ext = fields_match.ext
if ext == "input":
@@ -310,6 +311,7 @@ def collect_primary_datasets( tool, output, job_working_directory, input_ext ):
def walk_over_extra_files( extra_file_collectors, job_working_directory, matchable ):
for extra_file_collector in extra_file_collectors:
matches = []
directory = job_working_directory
if extra_file_collector.directory:
directory = os.path.join( directory, extra_file_collector.directory )
@@ -317,12 +319,16 @@ def walk_over_extra_files( extra_file_collectors, job_working_directory, matchab
raise Exception( "Problem with tool configuration, attempting to pull in datasets from outside working directory." )
if not os.path.isdir( directory ):
continue
for filename in sorted( os.listdir( directory ) ):
for filename in os.listdir( directory ):
path = os.path.join( directory, filename )
if not os.path.isfile( path ):
continue
if extra_file_collector.match( matchable, filename ):
yield path, extra_file_collector
match = extra_file_collector.match( matchable, filename, path=path )
if match:
matches.append(match)
for match in extra_file_collector.sort(matches):
yield match.path, extra_file_collector
def dataset_collector( dataset_collection_description ):
@@ -339,6 +345,9 @@ class DatasetCollector( object ):
def __init__( self, dataset_collection_description ):
# dataset_collection_description is an abstract description
# built from the tool parsing module - see galaxy.tools.parser.output_colleciton_def
self.sort_key = dataset_collection_description.sort_key
self.sort_reverse = dataset_collection_description.sort_reverse
self.sort_comp = dataset_collection_description.sort_comp
self.pattern = dataset_collection_description.pattern
self.default_dbkey = dataset_collection_description.default_dbkey
self.default_ext = dataset_collection_description.default_ext
@@ -352,20 +361,38 @@ class DatasetCollector( object ):
token_replacement = str( dataset_instance.id )
return self.pattern.replace( DATASET_ID_TOKEN, token_replacement )
def match( self, dataset_instance, filename ):
def match( self, dataset_instance, filename, path=None ):
pattern = self.pattern_for_dataset( dataset_instance )
re_match = re.match( pattern, filename )
match_object = None
if re_match:
match_object = CollectedDatasetMatch( re_match, self )
match_object = CollectedDatasetMatch( re_match, self, filename, path=path )
return match_object
def sort( self, matches ):
reverse = self.sort_reverse
sort_key = self.sort_key
sort_comp = self.sort_comp
assert sort_key in ["filename", "dbkey", "name", "designation"]
assert sort_comp in ["lexical", "numeric"]
key = operator.attrgetter(sort_key)
if sort_comp == "numeric":
key = _compose(int, key)
return sorted(matches, key=key, reverse=reverse)
def _compose(f, g):
return lambda x: f(g(x))
class CollectedDatasetMatch( object ):
def __init__( self, re_match, collector ):
def __init__( self, re_match, collector, filename, path=None ):
self.re_match = re_match
self.collector = collector
self.filename = filename
self.path = path
@property
def designation( self ):
+3 -1
View File
@@ -593,7 +593,9 @@ def parse_cast_attribute( cast ):
elif cast == 'str':
cast = str
else:
cast = lambda x: x # return value as-is
# return value as-is
def cast(x):
return x
return cast
@@ -5,6 +5,8 @@ dataset collection after jobs are finished.
from galaxy.util import asbool
DEFAULT_EXTRA_FILENAME_PATTERN = r"primary_DATASET_ID_(?P<designation>[^_]+)_(?P<visible>[^_]+)_(?P<ext>[^_]+)(_(?P<dbkey>[^_]+))?"
DEFAULT_SORT_BY = "filename"
DEFAULT_SORT_COMP = "lexical"
# XML can describe custom patterns, but these literals describe named
@@ -44,5 +46,24 @@ class DatasetCollectionDescription(object):
self.default_visible = asbool( kwargs.get( "visible", None ) )
self.directory = kwargs.get( "directory", None )
self.assign_primary_output = asbool( kwargs.get( 'assign_primary_output', False ) )
sort_by = kwargs.get( "sort_by", DEFAULT_SORT_BY )
if sort_by.startswith("reverse_"):
self.sort_reverse = True
sort_by = sort_by[len("reverse_"):]
else:
self.sort_reverse = False
if "_" in sort_by:
sort_comp, sort_by = sort_by.split("_", 1)
assert sort_comp in ["lexical", "numeric"]
else:
sort_comp = DEFAULT_SORT_COMP
assert sort_by in [
"filename",
"name",
"designation",
"dbkey"
]
self.sort_key = sort_by
self.sort_comp = sort_comp
DEFAULT_DATASET_COLLECTOR_DESCRIPTION = DatasetCollectionDescription()
+13 -5
View File
@@ -1,13 +1,15 @@
import logging
import os
import os.path
import galaxy.tools.parameters.basic
import galaxy.tools.parameters.grouping
from galaxy.util import string_as_bool
try:
from nose.tools import nottest
except ImportError:
nottest = lambda x: x
import logging
def nottest(x):
return x
log = logging.getLogger( __name__ )
@@ -74,11 +76,15 @@ class ToolTestBuilder( object ):
query_value = test_param.checked
else:
query_value = _process_bool_param_value( test_param, declared_value )
matches_declared_value = lambda case_value: _process_bool_param_value( test_param, case_value ) == query_value
def matches_declared_value(case_value):
return _process_bool_param_value( test_param, case_value ) == query_value
elif isinstance(test_param, galaxy.tools.parameters.basic.SelectToolParameter):
if declared_value is not None:
# Test case supplied explicit value to check against.
matches_declared_value = lambda case_value: case_value == declared_value
def matches_declared_value(case_value):
return case_value == declared_value
elif test_param.static_options:
# No explicit value in test case, not much to do if options are dynamic but
# if static options are available can find the one specified as default or
@@ -90,7 +96,9 @@ class ToolTestBuilder( object ):
first_option = test_param.static_options[0]
first_option_value = first_option[1]
default_option = first_option_value
matches_declared_value = lambda case_value: case_value == default_option
def matches_declared_value(case_value):
return case_value == default_option
else:
# No explicit value for this param and cannot determine a
# default - give up. Previously this would just result in a key
+15 -1
View File
@@ -17,6 +17,7 @@ from galaxy.util import string_as_bool
from galaxy.util.bunch import Bunch
from .parser import get_toolbox_parser, ensure_tool_conf_item
from .panel import ToolPanelElements
from .panel import ToolSectionLabel
from .panel import ToolSection
@@ -556,11 +557,24 @@ class AbstractToolBox( Dictifiable, ManagesIntegratedToolPanelMixin, object ):
# Backward compatibility issue - the tag used to be named 'changeset_revision'.
installed_changeset_revision_elem = item.elem.find( "changeset_revision" )
installed_changeset_revision = installed_changeset_revision_elem.text
try:
splitted_path = path.split('/')
assert splitted_path[0] == tool_shed
assert splitted_path[2] == repository_owner
assert splitted_path[3] == repository_name
if splitted_path[4] != installed_changeset_revision:
# This can happen if the Tool Shed repository has been
# updated to a new revision and the installed_changeset_revision
# element in shed_tool_conf.xml file has been updated too
log.debug("The installed_changeset_revision for tool %s is %s, using %s instead", path, installed_changeset_revision, splitted_path[4])
installed_changeset_revision = splitted_path[4]
except Exception as e:
log.debug("Error while loading tool %s : %s", path, e)
pass
tool_shed_repository = self._get_tool_shed_repository( tool_shed,
repository_name,
repository_owner,
installed_changeset_revision )
if tool_shed_repository:
# Only load tools if the repository is not deactivated or uninstalled.
can_load_into_panel_dict = not tool_shed_repository.deleted
+5 -4
View File
@@ -53,10 +53,11 @@ class ToolSection( Dictifiable, HasPanelItems, object ):
def __init__( self, item=None ):
""" Build a ToolSection from an ElementTree element or a dictionary.
"""
f = lambda item, val: item is not None and item.get( val ) or ''
self.name = f( item, 'name' )
self.id = f( item, 'id' )
self.version = f( item, 'version' )
if item is None:
item = dict()
self.name = item.get('name') or ''
self.id = item.get('id') or ''
self.version = item.get('version') or ''
self.elems = ToolPanelElements()
def copy( self ):
+2 -1
View File
@@ -9,8 +9,9 @@ try:
from watchdog.observers.polling import PollingObserver
can_watch = True
except ImportError:
Observer = None
FileSystemEventHandler = object
PollingObserver = object
PollingObserver = None
can_watch = False
log = logging.getLogger( __name__ )
+4 -1
View File
@@ -12,9 +12,12 @@ log = getLogger( __name__ )
# remote ComputeEnvironments (such as one used by Pulsar) determine what values to
# rewrite or transfer...
PATH_ATTRIBUTES = [ "path" ]
# ... by default though - don't rewrite anything (if no ComputeEnviornment
# defined or ComputeEnvironment doesn't supply a rewriter).
DEFAULT_PATH_REWRITER = lambda x: x
def DEFAULT_PATH_REWRITER(x):
return x
class ToolParameterValueWrapper( object ):
+2 -1
View File
@@ -94,7 +94,8 @@ INVALID_CHARACTER = "X"
if sys.version_info > (3, 0):
# __coerce__ doesn't do anything under Python anyway.
coerce = lambda x, y: x
def coerce(x, y):
return x
def sanitize_lists_to_string( values, valid_characters=VALID_CHARACTERS, character_map=CHARACTER_MAP, invalid_character=INVALID_CHARACTER ):
+6 -9
View File
@@ -7,12 +7,13 @@ from __future__ import with_statement
import inspect
import os
import sys
import re
import sys
from galaxy.util.properties import NicerConfigParser
import pkg_resources
from six import iteritems
__all__ = ['loadapp', 'loadserver', 'loadfilter', 'appconfig']
@@ -31,15 +32,11 @@ def print_(template, *args, **kwargs):
if sys.version_info < (3, 0):
from urllib import unquote
iteritems = lambda d: d.iteritems()
dictkeys = lambda d: d.keys()
def reraise(t, e, tb):
exec('raise t, e, tb', dict(t=t, e=e, tb=tb))
else:
from urllib.parse import unquote
iteritems = lambda d: d.items()
dictkeys = lambda d: list(d.keys())
def reraise(t, e, tb):
exec('raise e from tb', dict(e=e, tb=tb))
@@ -63,9 +60,9 @@ def fix_type_error(exc_info, callable, varargs, kwargs):
"""
if exc_info is None:
exc_info = sys.exc_info()
if (exc_info[0] != TypeError
or str(exc_info[1]).find('arguments') == -1
or getattr(exc_info[1], '_type_error_fixed', False)):
if (exc_info[0] != TypeError or
str(exc_info[1]).find('arguments') == -1 or
getattr(exc_info[1], '_type_error_fixed', False)):
return exc_info
exc_info[1]._type_error_fixed = True
argspec = inspect.formatargspec(*inspect.getargspec(callable))
@@ -703,7 +700,7 @@ class EggLoader(_Loader):
dist.location,
', '.join(_flatten(object_type.egg_protocols)),
', '.join(_flatten([
dictkeys(pkg_resources.get_entry_info(self.spec, prot, name) or {})
list((pkg_resources.get_entry_info(self.spec, prot, name) or {}).keys())
for prot in protocol_options] or '(no entry points)'))))
if len(possible) > 1:
raise LookupError(
+5 -2
View File
@@ -260,9 +260,12 @@ class Genomes( object ):
# Add app keys to dbkeys.
# If chrom_info is True, only include keys with len files (which contain chromosome info).
filter_fn = lambda b: True
if chrom_info:
filter_fn = lambda b: b.len_file is not None
def filter_fn(b):
return b.len_file is not None
else:
def filter_fn(b):
return True
dbkeys.extend( [ ( genome.description, genome.key ) for key, genome in self.genomes.items() if filter_fn( genome ) ] )
+2 -1
View File
@@ -15,7 +15,8 @@ except ImportError:
oidutil = None
class FakeConsumer( object ):
__getattr__ = lambda x, y: None
def __getattr__(x, y):
return None
consumer = FakeConsumer()

Some files were not shown because too many files have changed in this diff Show More